Component for mobile instruction step editor's list item

This commit is contained in:
araemer 2025-10-21 13:22:47 +02:00
parent 9b53f6e676
commit 05595fba94
2 changed files with 80 additions and 43 deletions

View file

@ -2,11 +2,12 @@
* Mobile editor using Up/Down buttons for reordering * Mobile editor using Up/Down buttons for reordering
*/ */
import {ArrowDown, ArrowUp, Plus, X} from "lucide-react"; import {Plus} from "lucide-react";
import type {InstructionStepModel} from "../../models/InstructionStepModel"; import type {InstructionStepModel} from "../../models/InstructionStepModel";
import Button from "../basics/Button"; import Button from "../basics/Button";
import {ButtonType} from "../basics/BasicButtonDefinitions"; import {ButtonType} from "../basics/BasicButtonDefinitions";
import {instructionStepListEditorMethods} from "./InstructionStepListEditorMethods.ts"; import {instructionStepListEditorMethods} from "./InstructionStepListEditorMethods.ts";
import {InstructionStepMobileListItem} from "./InstructionStepMobileListItem.tsx";
type InstructionStepListEditorMobileProps = { type InstructionStepListEditorMobileProps = {
instructionStepList: InstructionStepModel[]; instructionStepList: InstructionStepModel[];
@ -36,48 +37,15 @@ export function InstructionStepListMobileEditor({
<h2 className="section-heading mb-2">Zubereitung</h2> <h2 className="section-heading mb-2">Zubereitung</h2>
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
{instructionStepList.map((step, index) => ( {instructionStepList.map((step, index) => (
<div <InstructionStepMobileListItem
key={step.id} index={index}
className="flex items-start gap-3 bg-gray-50 rounded-xl p-3 shadow-sm" step={step}
> onMove={moveStep}
<div className="flex flex-col items-center pt-1"> onUpdate={handleUpdate}
<div className="circular-container"> onRemove={handleRemove}
{index + 1} isFirst={index === 0}
</div> isLast={index === instructionStepList.length - 1}
<div className="flex flex-col mt-2"> />
<Button
icon={ArrowUp}
onClick={() => moveStep(index, "up")}
buttonType={ButtonType.TransparentButton}
disabled={index === 0} // disable if first item
/>
<Button
icon={ArrowDown}
onClick={() => moveStep(index, "down")}
buttonType={ButtonType.TransparentButton}
disabled={index === instructionStepList.length - 1} // disable if last item
/>
</div>
</div>
<textarea
className="input-field w-full min-h-[120px] resize-none overflow-hidden"
placeholder={`Schritt ${index + 1}`}
value={step.text}
onChange={(e) => handleUpdate(index, e.target.value)}
onInput={(e) => {
const el = e.target as HTMLTextAreaElement;
el.style.height = "auto";
el.style.height = `${el.scrollHeight}px`;
}}
/>
<Button
onClick={() => handleRemove(index)}
icon={X}
buttonType={ButtonType.DarkButton}
/>
</div>
))} ))}
<Button <Button
onClick={handleAdd} onClick={handleAdd}

View file

@ -0,0 +1,69 @@
import Button from "../basics/Button.tsx";
import {ArrowDown, ArrowUp, X} from "lucide-react";
import {ButtonType} from "../basics/BasicButtonDefinitions.ts";
import type {InstructionStepModel} from "../../models/InstructionStepModel.ts";
type InstructionStepMobileListItemProps = {
index: number;
step: InstructionStepModel;
onMove(index: number, direction: "up" | "down"): void;
onUpdate: (index: number, value: string) => void;
onRemove: (index: number) => void;
isFirst: boolean;
isLast: boolean;
};
export function InstructionStepMobileListItem({
index,
step,
onMove,
onUpdate,
onRemove,
isFirst,
isLast
}: InstructionStepMobileListItemProps) {
return (
<div
key={step.id}
className="flex items-start gap-3 bg-gray-50 rounded-xl p-3 shadow-sm"
>
<div className="flex flex-col items-center pt-1">
<div className="circular-container">
{index + 1}
</div>
<div className="flex flex-col mt-2">
<Button
icon={ArrowUp}
onClick={() => onMove(index, "up")}
buttonType={ButtonType.TransparentButton}
disabled={isFirst} // disable if first item
/>
<Button
icon={ArrowDown}
onClick={() => onMove(index, "down")}
buttonType={ButtonType.TransparentButton}
disabled={isLast} // disable if last item
/>
</div>
</div>
<textarea
className="input-field w-full min-h-[120px] resize-none overflow-hidden"
placeholder={`Schritt ${index + 1}`}
value={step.text}
onChange={(e) => onUpdate(index, e.target.value)}
onInput={(e) => {
const el = e.target as HTMLTextAreaElement;
el.style.height = "auto";
el.style.height = `${el.scrollHeight}px`;
}}
/>
<Button
onClick={() => onRemove(index)}
icon={X}
buttonType={ButtonType.DarkButton}
/>
</div>
);
}