memorium/islands/IngredientsList.tsx

101 lines
2.6 KiB
TypeScript
Raw Normal View History

2023-07-30 19:40:39 +02:00
import { Signal } from "@preact/signals";
2025-01-18 00:46:05 +01:00
import type { Ingredient, IngredientGroup } from "@lib/recipeSchema.ts";
2023-07-30 19:40:39 +02:00
import { FunctionalComponent } from "preact";
import { unitsOfMeasure } from "@lib/parseIngredient.ts";
2023-07-30 19:40:39 +02:00
function formatAmount(num: number) {
if (num === 0) return "";
2023-08-04 23:36:35 +02:00
return (Math.floor(num * 4) / 4).toString();
}
2023-07-30 19:40:39 +02:00
function formatUnit(unit: string, amount: number) {
const unitKey = unit.toLowerCase() as keyof typeof unitsOfMeasure;
if (unitKey in unitsOfMeasure) {
if (amount > 1 && unitsOfMeasure[unitKey].plural !== undefined) {
return unitsOfMeasure[unitKey].plural;
}
2025-01-19 20:15:49 +01:00
if (unitKey !== "cup") {
return unitsOfMeasure[unitKey].short;
}
return unitKey.toString();
} else {
return unit;
}
2025-01-18 00:46:05 +01:00
}
2023-07-30 19:40:39 +02:00
const Ingredient = (
{ ingredient, amount, key = "", portion = 1 }: {
ingredient: Ingredient;
amount: Signal<number>;
key?: string | number;
portion?: number;
},
) => {
2025-01-18 00:46:05 +01:00
const { name, quantity, unit } = ingredient;
const parsedQuantity = parseFloat(quantity);
2023-07-30 19:40:39 +02:00
2025-01-18 00:46:05 +01:00
const finalAmount = (typeof parsedQuantity === "number" && amount)
? (parsedQuantity / portion) * (amount?.value || 1)
2023-07-30 19:40:39 +02:00
: "";
return (
<tr key={key}>
<td class="pr-4 py-2">
{formatAmount(finalAmount || 0)}
<span class="ml-0.5 opacity-50">
{formatUnit(unit, finalAmount || 0)}
</span>
2023-07-30 19:40:39 +02:00
</td>
2025-01-18 00:46:05 +01:00
<td class="px-4 py-2">{name}</td>
2023-07-30 19:40:39 +02:00
</tr>
);
};
export const IngredientsList: FunctionalComponent<
2025-01-18 00:46:05 +01:00
{
ingredients: (Ingredient | IngredientGroup)[];
amount: Signal<number>;
portion?: number;
}
2023-07-30 19:40:39 +02:00
> = (
{ ingredients, amount, portion },
) => {
return (
<table class="w-full border-collapse table-auto">
<tbody>
{ingredients.map((item, index) => {
2025-01-18 00:46:05 +01:00
if ("items" in item) {
2023-07-30 19:40:39 +02:00
// Render IngredientGroup
2025-01-18 00:46:05 +01:00
const { name, items: groupIngredients } = item as IngredientGroup;
2023-07-30 19:40:39 +02:00
return (
<>
<tr key={index}>
<td colSpan={3} class="pr-4 py-2 font-italic">{name}</td>
</tr>
{groupIngredients.map((item, index) => {
// Render Ingredient
return (
<Ingredient
key={index}
ingredient={item}
amount={amount}
portion={portion}
/>
);
})}
</>
);
} else {
return (
<Ingredient ingredient={item} amount={amount} portion={portion} />
);
}
})}
</tbody>
</table>
);
};