diff --git a/apps/web/src/components/ui/dropdown-menu.tsx b/apps/web/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..a3c2863 --- /dev/null +++ b/apps/web/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,51 @@ +import type { ComponentProps } from 'react'; +import { DropdownMenu as DropdownMenuPrimitive } from 'radix-ui'; + +import { cn } from '@/lib/utils'; + +const DropdownMenu = DropdownMenuPrimitive.Root; +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; + +function DropdownMenuContent({ + className, + sideOffset = 4, + ...props +}: ComponentProps) { + return ( + + + + ); +} + +function DropdownMenuItem({ + className, + ...props +}: ComponentProps) { + return ( + + ); +} + +export { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +}; diff --git a/apps/web/src/features/routines/create/editor/routine-editor.tsx b/apps/web/src/features/routines/create/editor/routine-editor.tsx index c6f667f..89b4a5e 100644 --- a/apps/web/src/features/routines/create/editor/routine-editor.tsx +++ b/apps/web/src/features/routines/create/editor/routine-editor.tsx @@ -9,7 +9,10 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { PageTitle } from '@/components/ui/page-title'; import { cn } from '@/lib/utils'; -import type { RoutineDraftFormValues } from '../routine-draft-form'; +import type { + RoutineDraftExerciseFormValues, + RoutineDraftFormValues, +} from '../routine-draft-form'; import { RoutineExerciseList } from './routine-exercise-list'; import { RoutineScheduleField } from './routine-schedule-field'; @@ -21,17 +24,28 @@ export function RoutineEditor() { await navigate({ to: '/routines/new/exercises' }); }; + const editExercise = async (exercise: RoutineDraftExerciseFormValues) => { + await navigate({ + params: { exerciseId: exercise.exerciseId }, + search: { position: exercise.position }, + to: '/routines/new/exercises/$exerciseId', + }); + }; + return (
reset()} />
-
- - void addExercise()} /> -
- + + +
+ void addExercise()} + onEditExercise={(exercise) => void editExercise(exercise)} + /> +
); @@ -93,17 +107,44 @@ function RoutineDetails() { ); } -function ExerciseSection({ onAddExercise }: { onAddExercise: () => void }) { - const { control } = useFormContext(); +function ExerciseSection({ + onAddExercise, + onEditExercise, +}: { + onAddExercise: () => void; + onEditExercise: (exercise: RoutineDraftExerciseFormValues) => void; +}) { + const { control, getValues, setValue } = + useFormContext(); const exercises = useWatch({ control, name: 'exercises' }); + function removeExercise(position: number) { + const remainingExercises = getValues('exercises') + .filter((exercise) => exercise.position !== position) + .map((exercise, nextPosition) => ({ + ...exercise, + position: nextPosition, + })); + + setValue('exercises', remainingExercises, { + shouldDirty: true, + shouldValidate: true, + }); + } + return (
- {exercises.length > 0 && } + {exercises.length > 0 && ( + + )}
0 ? 'mt-1' : 'mt-3'}> diff --git a/apps/web/src/features/routines/create/editor/routine-exercise-list.tsx b/apps/web/src/features/routines/create/editor/routine-exercise-list.tsx index 84529a8..dd5ac0a 100644 --- a/apps/web/src/features/routines/create/editor/routine-exercise-list.tsx +++ b/apps/web/src/features/routines/create/editor/routine-exercise-list.tsx @@ -1,16 +1,27 @@ /** Displays configured exercises in the routine draft. */ import { Dumbbell, GripVertical, MoreHorizontal } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; import { cn } from '@/lib/utils'; import type { RoutineDraftExerciseFormValues } from '../routine-draft-form'; export function RoutineExerciseList({ exercises, + onEdit, + onRemove, }: { exercises: RoutineDraftExerciseFormValues[]; + onEdit: (exercise: RoutineDraftExerciseFormValues) => void; + onRemove: (position: number) => void; }) { return ( -
+
{exercises.map((exercise) => ( - + ))}
@@ -37,13 +53,17 @@ export function RoutineExerciseList({ function RoutineExerciseRow({ exercise, + onEdit, + onRemove, }: { exercise: RoutineDraftExerciseFormValues; + onEdit: (exercise: RoutineDraftExerciseFormValues) => void; + onRemove: (position: number) => void; }) { return (
  • @@ -64,22 +84,58 @@ function RoutineExerciseRow({
  • - + {exercise.sets} - + {exercise.targetReps} - + {exercise.weight} {exercise.weightUnit} - + {exercise.restBetweenSetsSeconds}s -