diff --git a/frontend/src/api/dtos/RecipeInstructionStepDto.ts b/frontend/src/api/dtos/RecipeInstructionStepDto.ts index b9b902e..a6f5b3b 100644 --- a/frontend/src/api/dtos/RecipeInstructionStepDto.ts +++ b/frontend/src/api/dtos/RecipeInstructionStepDto.ts @@ -2,6 +2,7 @@ import { UUID } from "crypto"; import { AbstractDto } from "./AbstractDto.ts"; export class RecipeInstructionStepDto extends AbstractDto{ + id?: string; text!: string; sortOrder!: number; recipeId?: UUID; diff --git a/frontend/src/api/points/CompactRecipePoint.ts b/frontend/src/api/points/CompactRecipePoint.ts index 7855594..45cf28b 100644 --- a/frontend/src/api/points/CompactRecipePoint.ts +++ b/frontend/src/api/points/CompactRecipePoint.ts @@ -19,7 +19,7 @@ const RECIPE_URL = `${BASE_URL}/compact-recipe` * @returns Array of recipe */ export async function fetchRecipeList(searchString : string): Promise { - let url : string = RECIPE_URL; + let url : string = RECIPE_URL; // add an s to the base URL as we want to load a list // if there's a search string add it as query parameter if(searchString && searchString !== ""){ url +="?search=" + searchString; diff --git a/frontend/src/components/recipes/IngredientListEditor.tsx b/frontend/src/components/recipes/IngredientListEditor.tsx index 19c3d65..9b029ae 100644 --- a/frontend/src/components/recipes/IngredientListEditor.tsx +++ b/frontend/src/components/recipes/IngredientListEditor.tsx @@ -1,6 +1,6 @@ import type { IngredientModel } from "../../models/IngredientModel" import Button, { ButtonType } from "../basics/Button" -import SvgIcon, { Icon } from "../basics/SvgIcon" +import { Icon } from "../basics/SvgIcon" /** * Editor for handling the ingredient list diff --git a/frontend/src/components/recipes/InstructionStepListEditor.tsx b/frontend/src/components/recipes/InstructionStepListEditor.tsx new file mode 100644 index 0000000..c1fb4ee --- /dev/null +++ b/frontend/src/components/recipes/InstructionStepListEditor.tsx @@ -0,0 +1,56 @@ +import type { InstructionStepModel } from "../../models/InstructionStepModel" +import Button, { ButtonType } from "../basics/Button" +import { Icon } from "../basics/SvgIcon" + +/** + * Editor for handling the instruction step list + * Ingredients can be edited, added and removed + */ +type InstructionStepListEditorProps = { + instructionStepList: InstructionStepModel[] + onChange: (ingredients: InstructionStepModel[]) => void +} + +export function InstructionStepListEditor({ instructionStepList, onChange }: InstructionStepListEditorProps) { + const handleUpdate = (index: number, field: keyof InstructionStepModel, value: string) => { + const updated = instructionStepList.map((ing, i) => + i === index ? { ...ing, [field]: value } : ing + ) + onChange(updated) + } + + const handleAdd = () => { + onChange([...instructionStepList, { text: "" }]) + } + + const handleRemove = (index: number) => { + onChange(instructionStepList.filter((_, i) => i !== index)) + } + + return ( +
+

Zubereitung

+ {instructionStepList.map((step, index) => ( +
+ handleUpdate(index, "text", e.target.value)} + /> +
+ ))} +
+ ) +} diff --git a/frontend/src/components/recipes/RecipeDetailPage.tsx b/frontend/src/components/recipes/RecipeDetailPage.tsx index aebbc66..7e8e863 100644 --- a/frontend/src/components/recipes/RecipeDetailPage.tsx +++ b/frontend/src/components/recipes/RecipeDetailPage.tsx @@ -122,9 +122,15 @@ export default function RecipeDetailPage() { ))} - {/* Instructions */} + {/* Instructions - @todo add reasonable list delegate component*/}

Zubereitung

-

{recipe.instructions}

+
    + {recipe.instructionStepList.map((step,j) =>( +
  1. + {step.text} +
  2. + ))} +
{/* Action buttons */}
diff --git a/frontend/src/components/recipes/RecipeEditPage.tsx b/frontend/src/components/recipes/RecipeEditPage.tsx index 3732056..2b9d8b2 100644 --- a/frontend/src/components/recipes/RecipeEditPage.tsx +++ b/frontend/src/components/recipes/RecipeEditPage.tsx @@ -30,7 +30,7 @@ export default function RecipeEditPage() { title: "", ingredientGroupList: [ ], - instructions: "", + instructionStepList: [], servings: { amount: 1, unit: "" diff --git a/frontend/src/components/recipes/RecipeEditor.tsx b/frontend/src/components/recipes/RecipeEditor.tsx index e4f1289..e5b7062 100644 --- a/frontend/src/components/recipes/RecipeEditor.tsx +++ b/frontend/src/components/recipes/RecipeEditor.tsx @@ -3,6 +3,8 @@ import type { RecipeModel } from "../../models/RecipeModel" import type { IngredientGroupModel } from "../../models/IngredientGroupModel" import { IngredientGroupListEditor } from "./IngredientGroupListEditor" import Button, { ButtonType } from "../basics/Button" +import { InstructionStepListEditor } from "./InstructionStepListEditor" +import type { InstructionStepModel } from "../../models/InstructionStepModel" type RecipeEditorProps = { recipe: RecipeModel @@ -23,11 +25,20 @@ export default function RecipeEditor({ recipe, onSave, onCancel }: RecipeEditorP /** * Update ingredients - * @param ingredients new 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 @@ -119,14 +130,12 @@ export default function RecipeEditor({ recipe, onSave, onCancel }: RecipeEditorP />
-

Instructions

- {/* Instructions */} -