import {useState} from "react" import type {RecipeModel} from "../../models/RecipeModel" import type {IngredientGroupModel} from "../../models/IngredientGroupModel" import {IngredientGroupListEditor} from "./IngredientGroupListEditor" import Button from "../basics/Button" import {InstructionStepListEditor} from "./InstructionStepListEditor" import type {InstructionStepModel} from "../../models/InstructionStepModel" import {ButtonType} from "../basics/BasicButtonDefinitions" import ButtonGroupLayout from "../basics/ButtonGroupLayout.tsx"; type RecipeEditorProps = { recipe: RecipeModel onSave: (recipe: RecipeModel) => void onCancel: () => void } /** * Editor component for managing a recipe, including title, * ingredients (with amount, unit, name), instructions, and image URL. * @todo adapt to ingredientGroups! */ export default function RecipeEditor({recipe, onSave, onCancel}: RecipeEditorProps) { /** draft of the new recipe */ const [draft, setDraft] = useState(recipe) /** Error list */ const [errors, setErrors] = useState<{ title?: boolean; ingredients?: boolean }>({}) /** * Update ingredients * @param ingredientGroupList updated ingredient groups and ingredients */ const updateIngredientGroupList = (ingredientGroupList: IngredientGroupModel[]) => { setDraft({...draft, ingredientGroupList}) } /** * Update instruction steps * @param instructionStepList updated instructions */ const updateInstructionList = (instructionStepList: InstructionStepModel[]) => { setDraft({...draft, instructionStepList}) } /** * Validate recipe * @returns Information on the errors the validation encountered */ const validate = () => { const newErrors: { title?: boolean; ingredients?: boolean } = {} // each recipe requires a title if (!draft.title.trim()) { newErrors.title = true } /* there must be at least one ingredient group * no group may contain an empty ingredient list * @todo check whether all ingredients are valid * @todo enhance visualization of ingredient errors */ if (!draft.ingredientGroupList || draft.ingredientGroupList.length === 0) { newErrors.ingredients = true } else { const isAnyIngredientListEmpty = draft.ingredientGroupList.some( ingGrp => { return !ingGrp.ingredientList || ingGrp.ingredientList.length === 0 } ) if (isAnyIngredientListEmpty) { newErrors.ingredients = true } } setErrors(newErrors) return Object.keys(newErrors).length === 0 } /** Handles saving and ensures that the draft is only saved if valid */ const handleSave = (draft: RecipeModel) => { if (validate()) { onSave(draft) } } // ensure that there is a recipe and show error otherwise if (!recipe) return
Oops, there's no recipe in RecipeEditor...
// @todo add handling of images return ( /*Container spanning entire screen used to center content horizontally */
{/* Container defining the maximum width of the content */}

{recipe.id ? "Rezept bearbeiten" : "Neues Rezept"}

{/* Title */}

Titel

setDraft({...draft, title: e.target.value})} /> {/* Servings */}

Portionen

{ const tempServings = draft.servings tempServings.amount = Number(e.target.value) setDraft({...draft, servings: tempServings}) }} /> { const tempServings = draft.servings tempServings.unit = e.target.value setDraft({...draft, servings: tempServings}) }} />
{/* Ingredient List - @todo better visualization of errors! */}
{/* Instruction List*/} {/* Save Button */}
) }