fix(veckoplan): byt-ratt-fel, navigera veckor, lagg till maltid manuellt
- Byt rätt gav 'något gick fel': limit=30 översteg schemats tak (20). Höjt taket till 50, byt rätt hämtar 40 + sök vilken rätt som helst. - Veckonavigering: pilarna byter nu VECKA (weekOffset) i stället för att bara flytta markerad dag -> går att planera nästa vecka. Titel visar veckans datumintervall; bakåt spärras före denna vecka. - Lägg till måltid: ny POST /v1/week-plans/:id/entries + knapp 'Lägg till måltid' (väljer måltidstyp -> receptväljaren i lägg-till-läge) + knapp 'Planera om veckan'. Går nu att fylla en tom dag igen. Verifierat: swap 200 (40 varierade), add-entry 201, delete 200, api 104/104.
This commit is contained in:
@@ -2,6 +2,7 @@ import type { FastifyInstance } from "fastify";
|
||||
import { and, desc, eq, gte, sql } from "drizzle-orm";
|
||||
import { schema } from "@app/database";
|
||||
import {
|
||||
addPlanEntryInputSchema,
|
||||
generateWeekPlanInputSchema,
|
||||
idParamSchema,
|
||||
updatePlanEntryInputSchema,
|
||||
@@ -178,6 +179,64 @@ export async function planningRoutes(app: FastifyInstance) {
|
||||
return { ok: true };
|
||||
});
|
||||
|
||||
// Lägg till en enskild måltid i planen (t.ex. på en tom dag).
|
||||
app.post("/v1/week-plans/:id/entries", auth, async (req, reply) => {
|
||||
const params = req.params as { id: string };
|
||||
const [plan] = await app.db
|
||||
.select()
|
||||
.from(schema.weekPlans)
|
||||
.where(eq(schema.weekPlans.id, params.id))
|
||||
.limit(1);
|
||||
if (!plan) throw errors.notFound("Planen finns inte.");
|
||||
await requireMembership(app.db, plan.householdId, req.userId);
|
||||
|
||||
const input = parse(addPlanEntryInputSchema, req.body);
|
||||
const [recipe] = await app.db
|
||||
.select({
|
||||
id: schema.recipes.id,
|
||||
titleSv: schema.recipes.titleSv,
|
||||
portions: schema.recipes.portions,
|
||||
})
|
||||
.from(schema.recipes)
|
||||
.where(and(eq(schema.recipes.id, input.recipeId), eq(schema.recipes.status, "published")))
|
||||
.limit(1);
|
||||
if (!recipe) throw errors.notFound("Receptet finns inte.");
|
||||
|
||||
const sameDay = await app.db
|
||||
.select({ sortOrder: schema.weekPlanEntries.sortOrder })
|
||||
.from(schema.weekPlanEntries)
|
||||
.where(
|
||||
and(
|
||||
eq(schema.weekPlanEntries.weekPlanId, params.id),
|
||||
eq(schema.weekPlanEntries.date, input.date),
|
||||
),
|
||||
);
|
||||
const nextSort = sameDay.reduce((m, e) => Math.max(m, e.sortOrder ?? 0), -1) + 1;
|
||||
|
||||
const [row] = await app.db
|
||||
.insert(schema.weekPlanEntries)
|
||||
.values({
|
||||
weekPlanId: params.id,
|
||||
date: input.date,
|
||||
mealType: input.mealType,
|
||||
recipeId: recipe.id,
|
||||
titleSv: recipe.titleSv,
|
||||
portions: recipe.portions ?? 2,
|
||||
status: "planned",
|
||||
sortOrder: nextSort,
|
||||
})
|
||||
.returning();
|
||||
|
||||
await emitEvent(app.db, {
|
||||
type: "WEEK_PLAN_UPDATED",
|
||||
payload: { weekPlanId: params.id, reason: "entry_added" },
|
||||
userId: req.userId,
|
||||
householdId: plan.householdId,
|
||||
correlationId: req.correlationId,
|
||||
});
|
||||
return reply.status(201).send(row);
|
||||
});
|
||||
|
||||
app.post("/v1/week-plans/:id/activate", auth, async (req) => {
|
||||
const { id } = parse(idParamSchema, req.params);
|
||||
const [plan] = await app.db
|
||||
|
||||
Reference in New Issue
Block a user