import { useParams } from "react-router-dom" import type { Recipe } from "../../types/recipe" import { useEffect, useState } from "react" import { fetchRecipe } from "../../api/points/RecipePoint" import { getRecipeEditUrl, getRecipeListUrl } from "../../routes" import ButtonLink from "../basics/ButtonLink" /** * Displays the full detail of a single recipe, * including its ingredients, instructions, and image. */ export default function RecipeDetailPage() { // Extract recipe ID from route params const { id } = useParams<{ id: string }>() // the recipe loaded from the backend, don't change this! it's required for scaling const [recipe, setRecipe] = useState(null) // Working copy for re-calculating ingredients const [recipeWorkingCopy, setRecipeWorkingCopy] = useState(null) // load recipe data whenever id changes useEffect(() => { const loadRecipe = async () => { if (id) { try { // Fetch recipe data when editing an existing one console.log("loading recipe with id", id) const data = await fetchRecipe(id) setRecipe(data) } catch (err) { console.error(err) } } } loadRecipe() }, [id]) // set original recipe data and working copy when recipe changes useEffect( ()=> { setRecipeWorkingCopy(recipe); }, [recipe]) if (!recipe || !recipeWorkingCopy) { return

Recipe not found.

} /** recalculate ingredients based on the amount of servings */ const recalculateIngredients = (newAmount: number) => { // Always calculate factor from the *original recipe*, not the working copy const factor = newAmount / recipe.servings.amount // Create a new ingredient list with updated amounts const updatedIngredientGroupList = recipe.ingredientGroupList.map((ingGrp) => ({ ...ingGrp, ingredientList: ingGrp.ingredientList.map((ing) => ({ ...ing, amount: ing.amount * factor, })) })) // Update working copy with new servings + recalculated ingredients setRecipeWorkingCopy({ ...recipeWorkingCopy, servings: { ...recipeWorkingCopy.servings, amount: newAmount, }, ingredientGroupList: updatedIngredientGroupList, }) } return (

{recipeWorkingCopy.title}

{/* Recipe image */} {recipe.imageUrl && ( {recipe.title} )} {/* Servings */}

For {recipeWorkingCopy.servings.amount} {recipeWorkingCopy.servings.unit}

{ recalculateIngredients(Number(e.target.value)) } } />
{/* Ingredients */}

Zutaten

    {recipeWorkingCopy.ingredientGroupList.map((group,i) => (
    {/* the title is optional, only print if present */} {group.title && group.title.trim() !== "" && (

    {group.title}

    )}
      {group.ingredientList.map((ing, j) => (
    • {ing.amount} {ing.unit ?? ""} {ing.name}
    • ))}
    ))}
{/* Instructions */}

Zubereitung

{recipe.instructions}

{/* Action buttons */}
) }