feat(veckoplan): fyll alla maltider, variation, ratt maltidstyp + plan-atgarder
Veckoplanen fyller nu ALLA slots (stegvis fallback, inga tomma dagar), undviker tva soppor/samma kok i rad och styr soppor mot lunch (inte middag). Default lunch+middag varje dag. Plan-atgarder: 'Jag lagade detta' bara ratt dag; 'Hoppa over' ersatt med 'Ta bort' (ny DELETE /v1/week-plans/:id/entries/:entryId). Verifierat mot 393 recept: 14/14 slots fyllda, 0 upprepningar, 0 soppor pa middag.
This commit is contained in:
@@ -79,9 +79,9 @@ export default function PlanScreen() {
|
||||
}, []);
|
||||
const mondayKey = toKey(monday);
|
||||
const weekDays = useMemo(() => Array.from({ length: 7 }, (_, i) => addDays(monday, i)), [monday]);
|
||||
// Vardag: middag. Helg (lör/sön): lunch + middag. Realistisk förifylld default.
|
||||
// Lunch + middag varje dag som default (fler fyllda måltider), går att toggla.
|
||||
const [mealSlots, setMealSlots] = useState<string[][]>(() =>
|
||||
weekDays.map((d) => (d.getDay() === 0 || d.getDay() === 6 ? ["lunch", "dinner"] : ["dinner"])),
|
||||
weekDays.map(() => ["lunch", "dinner"]),
|
||||
);
|
||||
const toggleSlot = (dayIdx: number, meal: string) =>
|
||||
setMealSlots((prev) =>
|
||||
@@ -151,6 +151,13 @@ export default function PlanScreen() {
|
||||
onError: onMutationError,
|
||||
});
|
||||
|
||||
const removeEntry = useMutation({
|
||||
mutationFn: (vars: { planId: string; entryId: string }) =>
|
||||
api(`/v1/week-plans/${vars.planId}/entries/${vars.entryId}`, { method: "DELETE" }),
|
||||
onSuccess: () => invalidate(),
|
||||
onError: onMutationError,
|
||||
});
|
||||
|
||||
const activate = useMutation({
|
||||
mutationFn: (id: string) => api(`/v1/week-plans/${id}/activate`, { method: "POST" }),
|
||||
onSuccess: () => invalidate(),
|
||||
@@ -159,31 +166,39 @@ export default function PlanScreen() {
|
||||
|
||||
const createList = useMutation({
|
||||
mutationFn: (weekPlanId: string) =>
|
||||
api("/v1/shopping-lists", {
|
||||
api<{ list: { id: string } }>("/v1/shopping-lists", {
|
||||
method: "POST",
|
||||
body: { weekPlanId, generateFromPlan: true },
|
||||
}),
|
||||
onSuccess: () => router.push("/shopping"),
|
||||
// Navigera med listId så rätt (nygenererade) lista visas, inte en äldre tom.
|
||||
onSuccess: (res) => router.push(`/shopping?listId=${res.list.id}`),
|
||||
onError: onMutationError,
|
||||
});
|
||||
|
||||
const openActions = (entry: WeekPlanEntry) => {
|
||||
if (!planId) return;
|
||||
Alert.alert(entry.titleSv, undefined, [
|
||||
{
|
||||
text: t("recipe.iCookedThis"),
|
||||
onPress: () => patchEntry.mutate({ planId, entryId: entry.id, status: "cooked" }),
|
||||
},
|
||||
{
|
||||
text: t("common.skip"),
|
||||
onPress: () => patchEntry.mutate({ planId, entryId: entry.id, status: "skipped" }),
|
||||
},
|
||||
// "Jag lagade detta" bara på rätt dag – inte för framtida måltider.
|
||||
...(entry.date === todayKey
|
||||
? [
|
||||
{
|
||||
text: t("recipe.iCookedThis"),
|
||||
onPress: () => patchEntry.mutate({ planId, entryId: entry.id, status: "cooked" }),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
text: "Byt rätt",
|
||||
onPress: () =>
|
||||
router.push(`/swap-meal/${entry.id}?planId=${planId}&mealType=${entry.mealType}`),
|
||||
},
|
||||
{ text: t("common.cancel"), style: "cancel" },
|
||||
// Ersätter "Hoppa över": ta bort måltiden man inte lagat.
|
||||
{
|
||||
text: t("common.remove"),
|
||||
style: "destructive" as const,
|
||||
onPress: () => removeEntry.mutate({ planId, entryId: entry.id }),
|
||||
},
|
||||
{ text: t("common.cancel"), style: "cancel" as const },
|
||||
]);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user