feat(weekplan): MIKRO WEEK-2 dagliga måltidsslots (vardag middag, helg lunch+middag)

This commit is contained in:
Sven (AAMOS AI)
2026-08-17 19:17:27 +07:00
parent 9777c2ff1b
commit 97b5baa367
3 changed files with 10 additions and 2 deletions
+6 -1
View File
@@ -79,6 +79,11 @@ export default function PlanScreen() {
}, []); }, []);
const mondayKey = toKey(monday); const mondayKey = toKey(monday);
const weekDays = useMemo(() => Array.from({ length: 7 }, (_, i) => addDays(monday, i)), [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.
const mealSlots = useMemo(
() => weekDays.map((d) => (d.getDay() === 0 || d.getDay() === 6 ? ["lunch", "dinner"] : ["dinner"])),
[weekDays],
);
const query = useQuery({ const query = useQuery({
queryKey: ["week-plan", mondayKey], queryKey: ["week-plan", mondayKey],
@@ -125,7 +130,7 @@ export default function PlanScreen() {
mutationFn: () => mutationFn: () =>
api("/v1/week-plans/generate", { api("/v1/week-plans/generate", {
method: "POST", method: "POST",
body: { weekStartDate: mondayKey, mealTypes: ["lunch", "dinner"] }, body: { weekStartDate: mondayKey, mealTypes: ["lunch", "dinner"], mealSlots },
}), }),
onSuccess: () => setGenerating(true), onSuccess: () => setGenerating(true),
onError: onMutationError, onError: onMutationError,
+3 -1
View File
@@ -18,6 +18,7 @@ interface WeekPlanJobInput {
weekStartDate: string; weekStartDate: string;
daysToPlann?: number; daysToPlann?: number;
mealTypes: MealType[]; mealTypes: MealType[];
mealSlots?: MealType[][];
portionsPerMeal?: number; portionsPerMeal?: number;
budgetMinorTotal?: number; budgetMinorTotal?: number;
preferLeftoversFirst: boolean; preferLeftoversFirst: boolean;
@@ -228,7 +229,8 @@ export async function processGenerateWeekPlan(
const date = new Date(Date.parse(data.input.weekStartDate) + day * 86_400_000) const date = new Date(Date.parse(data.input.weekStartDate) + day * 86_400_000)
.toISOString() .toISOString()
.slice(0, 10); .slice(0, 10);
for (const mealType of mealTypes) { const dayMeals = data.input.mealSlots ? (data.input.mealSlots[day] ?? []) : mealTypes;
for (const mealType of dayMeals) {
// Matlåda om det finns och portionerna räcker // Matlåda om det finns och portionerna räcker
const box = mealBoxes[boxIndex]; const box = mealBoxes[boxIndex];
if (box && box.portionsRemaining >= Math.min(portions, 2)) { if (box && box.portionsRemaining >= Math.min(portions, 2)) {
+1
View File
@@ -7,6 +7,7 @@ export const generateWeekPlanInputSchema = z.object({
weekStartDate: dateStringSchema, weekStartDate: dateStringSchema,
daysToPlann: z.number().int().min(1).max(14).optional(), daysToPlann: z.number().int().min(1).max(14).optional(),
mealTypes: z.array(z.enum(MEAL_TYPES)).min(1).default(["dinner"]), mealTypes: z.array(z.enum(MEAL_TYPES)).min(1).default(["dinner"]),
mealSlots: z.array(z.array(z.enum(MEAL_TYPES))).optional(),
portionsPerMeal: z.number().int().min(1).max(20).optional(), portionsPerMeal: z.number().int().min(1).max(20).optional(),
budgetMinorTotal: z.number().int().min(0).max(5_000_000).optional(), budgetMinorTotal: z.number().int().min(0).max(5_000_000).optional(),
/** T.ex. "Sju middagar för fyra personer under 1 000 kr" (spec §26). */ /** T.ex. "Sju middagar för fyra personer under 1 000 kr" (spec §26). */