Make amount for an ingredient optional.

This commit is contained in:
araemer 2025-10-21 15:32:48 +02:00
parent 3c9c94957f
commit 0dc2eb2e3c
4 changed files with 122 additions and 96 deletions

View file

@ -3,25 +3,48 @@ import type {IngredientModel} from "../../models/IngredientModel"
import Button from "../basics/Button"
import {ButtonType} from "../basics/BasicButtonDefinitions"
/**
* Editor for handling the ingredient list
* Ingredients can be edited, added and removed
*/
type IngredientListEditorProps = {
ingredients: IngredientModel[]
onChange: (ingredients: IngredientModel[]) => void
}
/**
* Editor for handling the ingredient list
*
* Ingredients can be edited, added and removed
* @param ingredient List of IngredientModels describing the ingredient
* @param onChange Method to call on changing an ingredient.
*/
export function IngredientListEditor({ingredients, onChange}: IngredientListEditorProps) {
const handleUpdate = (index: number, field: keyof IngredientModel, value: string | number) => {
const updated = ingredients.map((ing, i) =>
i === index ? {...ing, [field]: field === "amount" ? Number(value) : value} : ing
)
onChange(updated)
const handleUpdate = (
index: number,
field: keyof IngredientModel,
value: string | number | undefined
) => {
const updated = ingredients.map((ing, i) => {
if (i !== index) return ing;
if (field === "amount") {
// Handle optional numeric value
if (value === undefined || value === "") {
const {amount, ...rest} = ing; // remove the field
return rest as IngredientModel;
}
// valid number
return {...ing, amount: Number(value)};
}
// handle other fields normally
return {...ing, [field]: value};
});
onChange(updated);
};
const handleAdd = () => {
onChange([...ingredients, {name: "", amount: 0, unit: ""}])
onChange([...ingredients, {name: "", unit: ""}])
}
const handleRemove = (index: number) => {
@ -36,8 +59,11 @@ export function IngredientListEditor({ingredients, onChange}: IngredientListEdit
type="number"
className="input-field"
placeholder="Menge"
value={ing.amount}
onChange={e => handleUpdate(index, "amount", e.target.value)}
value={ing.amount === undefined || ing.amount === null ? "" : ing.amount}
onChange={e => {
const value = e.target.value;
handleUpdate(index, "amount", value === "" ? undefined : Number(value));
}}
/>
<input
className="input-field w-20"

View file

@ -58,7 +58,7 @@ export default function RecipeDetailPage() {
...ingGrp,
ingredientList: ingGrp.ingredientList.map((ing) => ({
...ing,
amount: ing.amount * factor,
amount: ing.amount !== undefined ? ing.amount * factor : ing.amount,
}))
}))
@ -121,7 +121,7 @@ export default function RecipeDetailPage() {
<ul className="default-list">
{group.ingredientList.map((ing, j) => (
<li key={j}>
{ing.amount} {ing.unit ?? ""} {ing.name}
{ing.amount ?? ""} {ing.unit ?? ""} {ing.name}
</li>
))}
</ul>

View file

@ -40,7 +40,7 @@ export function mapRecipeDtoToModel(dto: RecipeDto): RecipeModel {
.map(ing => ({
id: ing.id,
name: ing.name ?? "", // @todo ensure that name and amount are indeed present
amount: ing.amount ?? 0,
amount: ing.amount,
unit: ing.unit,
//subtext: ing.subtext ?? undefined,
})),

View file

@ -7,7 +7,7 @@ export interface IngredientModel {
name: string
/** Quantity required (e.g. 200, 1.5) */
amount: number
amount?: number
/** Unit of measurement (e.g. "g", "tbsp", "cups").
* Optional for cases like "1 egg".