diff --git a/packages/liftograph-app/src/liftograph-main/components/bottom-toolbar.tsx b/packages/liftograph-app/src/liftograph-main/components/bottom-toolbar.tsx
new file mode 100644
index 0000000..cf10a9d
--- /dev/null
+++ b/packages/liftograph-app/src/liftograph-main/components/bottom-toolbar.tsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import { Paper } from '@mui/material';
+
+export interface BottomToolbarProps {
+ children: React.ReactNode;
+}
+
+/** Toolbar fixed to the bottom of the screen. */
+export function BottomToolbar(props: BottomToolbarProps) {
+ const { children } = props;
+ return (
+
+ {children}
+
+ );
+}
diff --git a/packages/liftograph-app/src/liftograph-main/workouts/workouts.tsx b/packages/liftograph-app/src/liftograph-main/workouts/workouts.tsx
index fbc4f53..2f20839 100644
--- a/packages/liftograph-app/src/liftograph-main/workouts/workouts.tsx
+++ b/packages/liftograph-app/src/liftograph-main/workouts/workouts.tsx
@@ -1,42 +1,164 @@
import { addWorkout, getWorkoutsSelector, useStoreDispatch, useStoreSelection } from '@liftograph/application-store';
import { Link } from 'react-router-dom';
-import { Box, ListItem, ListItemText } from '@mui/material';
-import React from 'react';
-import { Button } from '@mui/base';
+import { Box, Button, Divider, IconButton, ListItem, ListItemText, Modal, Paper, TextField, Typography } from '@mui/material';
+import AddIcon from '@mui/icons-material/Add';
+import React, { useState } from 'react';
import { v4 } from 'uuid';
+import { BottomToolbar } from '../components/bottom-toolbar';
export const WORKOUT_EDITOR_LINK_DATA_TESTID = 'workout-editor-link';
export function Workouts() {
const workouts = useStoreSelection(getWorkoutsSelector);
- const dispatch = useStoreDispatch();
+ const [ isModalOpen, openModal ] = useState(false);
+
return (
-
{workouts.map((workout, id) => (
-
-
-
-
-
+
+
+
+
+
))}
+
+ openModal(true)}
+ >
+
+
+
+ handleModalClose()}
+ />
);
-}
\ No newline at end of file
+
+ function handleModalClose() {
+ openModal(false);
+ }
+}
+
+interface CreateWorkoutModalProps {
+ isOpen: boolean;
+ close(): void;
+}
+
+function CreateWorkoutModal(props: CreateWorkoutModalProps) {
+ const { isOpen, close } = props;
+ const dispatch = useStoreDispatch();
+ const [ name, setName ] = useState('');
+ const [ hasValidName, setHasValidName ] = useState(false);
+
+ return (
+
+
+ Create a workout!
+
+ {
+ const {
+ target: {
+ value
+ }
+ } = event;
+ setName(value);
+ }}
+ onBlur={() => {
+ if (isValidName()) {
+ setHasValidName(true);
+ } else {
+ setHasValidName(false);
+ }
+ }}
+ />
+
+
+
+
+
+
+ );
+
+ function cancel() {
+ resetName();
+ close();
+ }
+
+ function save() {
+ if (isValidName()) {
+ dispatch(
+ addWorkout({
+ name,
+ id: v4(),
+ exercises: []
+ })
+ );
+ resetName();
+ close();
+ }
+ }
+
+ function resetName() {
+ setName('');
+ setHasValidName(false);
+ }
+
+ function isValidName() {
+ const trimmedName = name.trim();
+ if (trimmedName === '') {
+ return false;
+ }
+ return true;
+ }
+}