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 Button from "../basics/Button"
import {ButtonType} from "../basics/BasicButtonDefinitions" import {ButtonType} from "../basics/BasicButtonDefinitions"
/**
* Editor for handling the ingredient list
* Ingredients can be edited, added and removed
*/
type IngredientListEditorProps = { type IngredientListEditorProps = {
ingredients: IngredientModel[] ingredients: IngredientModel[]
onChange: (ingredients: IngredientModel[]) => void 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) { export function IngredientListEditor({ingredients, onChange}: IngredientListEditorProps) {
const handleUpdate = (index: number, field: keyof IngredientModel, value: string | number) => { const handleUpdate = (
const updated = ingredients.map((ing, i) => index: number,
i === index ? {...ing, [field]: field === "amount" ? Number(value) : value} : ing field: keyof IngredientModel,
) value: string | number | undefined
onChange(updated) ) => {
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 = () => { const handleAdd = () => {
onChange([...ingredients, {name: "", amount: 0, unit: ""}]) onChange([...ingredients, {name: "", unit: ""}])
} }
const handleRemove = (index: number) => { const handleRemove = (index: number) => {
@ -36,8 +59,11 @@ export function IngredientListEditor({ingredients, onChange}: IngredientListEdit
type="number" type="number"
className="input-field" className="input-field"
placeholder="Menge" placeholder="Menge"
value={ing.amount} value={ing.amount === undefined || ing.amount === null ? "" : ing.amount}
onChange={e => handleUpdate(index, "amount", e.target.value)} onChange={e => {
const value = e.target.value;
handleUpdate(index, "amount", value === "" ? undefined : Number(value));
}}
/> />
<input <input
className="input-field w-20" className="input-field w-20"

View file

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

View file

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

View file

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