diff --git a/apps/api/src/routes/shopping.ts b/apps/api/src/routes/shopping.ts index b050cab..a3db70b 100644 --- a/apps/api/src/routes/shopping.ts +++ b/apps/api/src/routes/shopping.ts @@ -101,7 +101,8 @@ export async function shoppingRoutes(app: FastifyInstance) { eq(schema.shoppingLists.householdId, householdId), eq(schema.shoppingLists.status, "active"), ), - ); + ) + .orderBy(desc(schema.shoppingLists.createdAt)); return { lists }; }); @@ -109,14 +110,46 @@ export async function shoppingRoutes(app: FastifyInstance) { const input = parse(createShoppingListInputSchema, req.body); const householdId = await requireActiveHousehold(app.db, req.userId); - const [list] = await app.db - .insert(schema.shoppingLists) - .values({ householdId, name: input.name, weekPlanId: input.weekPlanId ?? null }) - .returning(); - - // Generera från veckoplan: receptbehov − befintligt lager (spec §27) + // Generera från veckoplan: återanvänd EN aktiv lista per veckoplan så att + // "skapa inköpslista" inte staplar nya (tomma) listor. Utan detta pekade + // appen på en annan/äldre lista och den genererade listan såg tom ut. + let list; if (input.generateFromPlan && input.weekPlanId) { + const [existing] = await app.db + .select() + .from(schema.shoppingLists) + .where( + and( + eq(schema.shoppingLists.householdId, householdId), + eq(schema.shoppingLists.status, "active"), + eq(schema.shoppingLists.weekPlanId, input.weekPlanId), + ), + ) + .limit(1); + if (existing) { + list = existing; + // Rensa tidigare plan-rader så omgenerering inte dubblerar. + await app.db + .delete(schema.shoppingListItems) + .where( + and( + eq(schema.shoppingListItems.shoppingListId, existing.id), + eq(schema.shoppingListItems.origin, "plan"), + ), + ); + } else { + [list] = await app.db + .insert(schema.shoppingLists) + .values({ householdId, name: input.name, weekPlanId: input.weekPlanId }) + .returning(); + } + // Receptbehov − befintligt lager (spec §27) await generateItemsFromPlan(app, list!.id, input.weekPlanId, householdId, req.userId); + } else { + [list] = await app.db + .insert(schema.shoppingLists) + .values({ householdId, name: input.name, weekPlanId: input.weekPlanId ?? null }) + .returning(); } const items = await app.db diff --git a/apps/mobile/src/app/shopping.tsx b/apps/mobile/src/app/shopping.tsx index 94e335c..b2dd486 100644 --- a/apps/mobile/src/app/shopping.tsx +++ b/apps/mobile/src/app/shopping.tsx @@ -1,6 +1,7 @@ import { useState } from "react"; import { Alert, Pressable, Text, View } from "react-native"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { useLocalSearchParams } from "expo-router"; import { api } from "@/lib/api"; import { t } from "@/lib/i18n"; import { formatMinor } from "@/lib/money"; @@ -61,6 +62,8 @@ const sectionLabel = (id: string): string => export default function ShoppingScreen() { const queryClient = useQueryClient(); const [newItem, setNewItem] = useState(""); + const params = useLocalSearchParams<{ listId?: string }>(); + const paramListId = typeof params.listId === "string" ? params.listId : undefined; const lists = useQuery({ queryKey: ["shopping-lists"], @@ -76,7 +79,9 @@ export default function ShoppingScreen() { return result.lists; }, }); - const listId = lists.data?.[0]?.id; + // Prioritera listId från navigering (t.ex. nygenererad från veckoplan), + // annars nyaste aktiva listan. + const listId = paramListId ?? lists.data?.[0]?.id; const list = useQuery({ queryKey: ["shopping-list", listId],