feat(veckoplan): tillbehor (t.ex. potatisgratang) foreslar proteinbit
Rena tillbehor utan protein i titeln (potatisgratang, mos, pommes) far en not: 'servera med en proteinbit (ryggbiff/entrecote, kyckling, fisk eller tofu/halloumi)'. Kott-/korv-/fiskgratanger raknas som hela ratter. Verifierat mot riktig data: 5 av 19 gratang-traffar klassas som tillbehor, inga falska traffar pa proteinratter.
This commit is contained in:
@@ -232,6 +232,17 @@ export async function processGenerateWeekPlan(
|
||||
`${r.cuisine}|${isSoup(r) ? "soup" : "dish"}`;
|
||||
let lastSignature: string | null = null;
|
||||
|
||||
// Tillbehör/sides (t.ex. potatisgratäng, mos, pommes) är inte en hel middag
|
||||
// i sig. Om titeln redan innehåller ett protein (köttfärs-/korvgratäng) är den
|
||||
// komplett. Annars föreslår vi en proteinbit att servera till.
|
||||
const proteinWords =
|
||||
/kött|korv|kyckling|lax|fisk|fläsk|skinka|biff|färs|räk|tofu|halloumi|ägg|bön|lins|kikärt|falafel|quorn|chorizo|bacon|lamm|anka|kalkon|tonfisk|torsk|sill/i;
|
||||
const sideWords = /gratäng|potatismos|rotmos|pommes|klyftpotatis|potatisstomp|potatissallad/i;
|
||||
const isSideDish = (r: { titleSv: string }) =>
|
||||
sideWords.test(r.titleSv) && !proteinWords.test(r.titleSv);
|
||||
const sideSuggestion =
|
||||
"Tillbehör – servera med en proteinbit: t.ex. en stekt eller grillad ryggbiff eller entrecôte, kyckling, fisk, eller tofu/halloumi för en vegetarisk variant.";
|
||||
|
||||
for (let day = 0; day < days; day++) {
|
||||
const date = new Date(Date.parse(data.input.weekStartDate) + day * 86_400_000)
|
||||
.toISOString()
|
||||
@@ -288,6 +299,13 @@ export async function processGenerateWeekPlan(
|
||||
recipeUseCount.set(chosen.recipe.id, (recipeUseCount.get(chosen.recipe.id) ?? 0) + 1);
|
||||
usedRecipeIds.add(chosen.recipe.id);
|
||||
const expiring = chosen.coverage.expiringUsed[0];
|
||||
const notes: string[] = [];
|
||||
if (isSideDish(chosen.recipe) && (mealType === "lunch" || mealType === "dinner")) {
|
||||
notes.push(sideSuggestion);
|
||||
}
|
||||
if (expiring) {
|
||||
notes.push(`Använder ${expiring.displayNameSv.toLowerCase()} som bör ätas snart.`);
|
||||
}
|
||||
entries.push({
|
||||
weekPlanId,
|
||||
date,
|
||||
@@ -296,9 +314,7 @@ export async function processGenerateWeekPlan(
|
||||
titleSv: chosen.recipe.titleSv,
|
||||
portions,
|
||||
status: "planned",
|
||||
rescheduleReasonSv: expiring
|
||||
? `Använder ${expiring.displayNameSv.toLowerCase()} som bör ätas snart.`
|
||||
: null,
|
||||
rescheduleReasonSv: notes.length > 0 ? notes.join(" ") : null,
|
||||
sortOrder: entries.length,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user