From 3c9c94957f3f918b8e6b3c1e4fad9cb93463987a Mon Sep 17 00:00:00 2001 From: araemer Date: Tue, 21 Oct 2025 15:09:15 +0200 Subject: [PATCH] Add control for moving items up and down a list. --- .../components/basics/MoveButtonControl.tsx | 36 ++++++++++ .../InstructionStepListDesktopEditor.tsx | 16 +++-- .../InstructionStepListMobileEditor.tsx | 23 +++++-- .../recipes/InstructionStepMobileListItem.tsx | 67 +++++++++++++------ 4 files changed, 113 insertions(+), 29 deletions(-) create mode 100644 frontend/src/components/basics/MoveButtonControl.tsx diff --git a/frontend/src/components/basics/MoveButtonControl.tsx b/frontend/src/components/basics/MoveButtonControl.tsx new file mode 100644 index 0000000..a8b60b0 --- /dev/null +++ b/frontend/src/components/basics/MoveButtonControl.tsx @@ -0,0 +1,36 @@ +import Button from "./Button.tsx"; +import {ArrowDown, ArrowUp} from "lucide-react"; +import {ButtonType} from "./BasicButtonDefinitions.ts"; + +type MoveButtonControlProps = { + isUpDisabled: boolean; + isDownDisabled: boolean; + onMoveUp(): void; + onMoveDown(): void; +} + +/** + * Up and down buttons for reordering list items when not using drag & drop, e.g., on mobile devices. + * @param isUpDisabled Indicates whether the up button is enabled + * @param isDownDisabled Indicates whether the down button is enabled + * @param onMoveUp Method to call when move up is clicked + * @param onMoveDown Method to call when move down is clicked + */ +export function MoveButtonControl({isUpDisabled, isDownDisabled, onMoveUp, onMoveDown}: MoveButtonControlProps) { + return ( +
+
+ ); +} \ No newline at end of file diff --git a/frontend/src/components/recipes/InstructionStepListDesktopEditor.tsx b/frontend/src/components/recipes/InstructionStepListDesktopEditor.tsx index da99ab3..e4cc784 100644 --- a/frontend/src/components/recipes/InstructionStepListDesktopEditor.tsx +++ b/frontend/src/components/recipes/InstructionStepListDesktopEditor.tsx @@ -1,7 +1,3 @@ -/** - * Desktop editor using drag-and-drop via @dnd-kit - */ - import {closestCenter, DndContext, PointerSensor, useSensor, useSensors,} from "@dnd-kit/core"; import {arrayMove, SortableContext, verticalListSortingStrategy,} from "@dnd-kit/sortable"; import type {InstructionStepModel} from "../../models/InstructionStepModel"; @@ -16,10 +12,19 @@ type InstructionStepListDesktopEditorProps = { onChange: (steps: InstructionStepModel[]) => void; }; +/** + * Desktop editor using drag-and-drop via @dnd-kit + * @param instructionStepList List instruction step models + * @param onChange Method to call on any change to the list + * @constructor + */ export function InstructionStepListDesktopEditor({ instructionStepList, onChange, }: InstructionStepListDesktopEditorProps) { + /* Import methods for handling update of instruction steps as well as adding and removing steps. + * Those methods are shared by all versions of the instruction step editor, e.g., mobile and desktop. + */ const {handleUpdate, handleAdd, handleRemove} = instructionStepListEditorMethods( instructionStepList, onChange @@ -27,6 +32,9 @@ export function InstructionStepListDesktopEditor({ const sensors = useSensors(useSensor(PointerSensor, {activationConstraint: {distance: 8}})); + /** + * Handle the drag end event and reorder list + */ const handleDragEnd = (event: any) => { const {active, over} = event; if (active.id !== over.id) { diff --git a/frontend/src/components/recipes/InstructionStepListMobileEditor.tsx b/frontend/src/components/recipes/InstructionStepListMobileEditor.tsx index c471842..e3977ce 100644 --- a/frontend/src/components/recipes/InstructionStepListMobileEditor.tsx +++ b/frontend/src/components/recipes/InstructionStepListMobileEditor.tsx @@ -1,7 +1,3 @@ -/** - * Mobile editor using Up/Down buttons for reordering - */ - import {Plus} from "lucide-react"; import type {InstructionStepModel} from "../../models/InstructionStepModel"; import Button from "../basics/Button"; @@ -14,15 +10,28 @@ type InstructionStepListEditorMobileProps = { onChange: (steps: InstructionStepModel[]) => void; }; +/** + * Mobile editor using Up/Down buttons for reordering + * @param instructionStepList List instruction step models + * @param onChange Method to call on any change to the list + */ export function InstructionStepListMobileEditor({ instructionStepList, onChange, }: InstructionStepListEditorMobileProps) { + /* Import methods for handling update of instruction steps as well as adding and removing steps. + * Those methods are shared by all versions of the instruction step editor, e.g., mobile and desktop. + */ const {handleUpdate, handleAdd, handleRemove} = instructionStepListEditorMethods( instructionStepList, onChange ); + /** + * Move an instruction step either up or down in list. + * @param index Current index of the step to move + * @param direction Direction to move the step in. Either "up" or "down". + */ const moveStep = (index: number, direction: "up" | "down") => { const newIndex = direction === "up" ? index - 1 : index + 1; if (newIndex < 0 || newIndex >= instructionStepList.length) return; @@ -35,11 +44,13 @@ export function InstructionStepListMobileEditor({ return (

Zubereitung

+ + {/* Instruction list */}
{instructionStepList.map((step, index) => ( ))} + + {/* Button for adding an additional instruction step */}
+ onMove(index, "up")} + onMoveDown={() => onMove(index, "down")} + />
+ {/* Center column: Instruction step */}