From 3942890d6f70c845d7cc77c39e551c744ddbde1b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 16:02:57 +0000 Subject: [PATCH] =?UTF-8?q?fix(matlager):=20stada=20upp=20=E2=80=93=20flyt?= =?UTF-8?q?ta=20lager=20till=20egen=20vy,=20gruppera=20per=20plats,=20fixa?= =?UTF-8?q?=20limit-bugg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BUGG: kitchen hamtade ?limit=500 men schemat tillat max 200 -> 400-fel nar man gick in i matlager / tryckte "+N till". Hojer inventoryQuerySchema.limit till 500. - Hem: tar bort den roriga inline-listan (matlager lag kvar under Hemma). Ersatts med ett "Matlager"-kort med genvagsknappar per plats (Kyl/Frys/Skafferi) + "Allt". - Matlager-skarmen: grupperad per plats med rubrik + antal, sorterad pa namn, plats-filter via chips ELLER djuplank (?loc=), sok, markera flera, massradering. - Byter skarmtitel "Ditt kok" -> "Matlager". - Fixar aven en latent hooks-ordningsbugg i home (useFocusEffect efter early return). --- apps/mobile/src/app/(tabs)/home.tsx | 149 ++++++++++++------------ apps/mobile/src/app/_layout.tsx | 2 +- apps/mobile/src/app/kitchen.tsx | 163 ++++++++++++++++----------- packages/validation/src/inventory.ts | 2 +- 4 files changed, 168 insertions(+), 148 deletions(-) diff --git a/apps/mobile/src/app/(tabs)/home.tsx b/apps/mobile/src/app/(tabs)/home.tsx index 8fdd20a..2d9092e 100644 --- a/apps/mobile/src/app/(tabs)/home.tsx +++ b/apps/mobile/src/app/(tabs)/home.tsx @@ -1,7 +1,7 @@ -import { Alert, Pressable, View } from "react-native"; -import { useCallback } from "react"; +import { Pressable, View } from "react-native"; +import { useCallback, useMemo } from "react"; import { router, useFocusEffect } from "expo-router"; -import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { useQuery } from "@tanstack/react-query"; import { api } from "@/lib/api"; import { useAuth } from "@/lib/auth"; import { t } from "@/lib/i18n"; @@ -11,7 +11,6 @@ import { Body, Button, Card, - EmptyState, ErrorView, Heading, LoadingView, @@ -23,7 +22,6 @@ import { Title, } from "@/components/ui"; import { colors, spacing } from "@/lib/theme"; -import { formatQuantity } from "@/lib/units"; /** Hemma (spec §4.4): matlager, bäst före, matlådor, inköpslista, budget, hushåll. */ @@ -33,6 +31,7 @@ interface InventoryItem { quantity: number; unit: string; locationName: string; + locationType: string; expiry: { status: string; daysLeft: number | null; pastBestBefore: boolean }; } interface BudgetSummary { @@ -41,24 +40,18 @@ interface BudgetSummary { month: { purchasedMinor: number; wasteMinor: number }; } +const LOCATION_ORDER = ["fridge", "freezer", "pantry", "garage_freezer", "wine_fridge"]; +const orderIndex = (type: string) => { + const i = LOCATION_ORDER.indexOf(type); + return i === -1 ? LOCATION_ORDER.length : i; +}; + export default function HomeScreen() { - const queryClient = useQueryClient(); - const remove = useMutation({ - mutationFn: (id: string) => api(`/v1/inventory/items/${id}`, { method: "DELETE" }), - onError: (err) => - Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")), - onSettled: () => void queryClient.invalidateQueries({ queryKey: ["inventory"] }), - }); - const confirmRemove = (id: string, name: string) => - Alert.alert("Ta bort", `Ta bort ${name} ur ditt lager?`, [ - { text: t("common.cancel"), style: "cancel" }, - { text: "Ta bort", style: "destructive", onPress: () => remove.mutate(id) }, - ]); const inventory = useQuery({ queryKey: ["inventory"], queryFn: () => api<{ items: InventoryItem[]; trustStatus?: "up_to_date" | "needs_check" | "uncertain" }>( - "/v1/inventory?limit=100", + "/v1/inventory?limit=200", ), }); const expiring = useQuery({ @@ -76,21 +69,26 @@ export default function HomeScreen() { }); const setOnboardingStep = useAuth((s) => s.setOnboardingStep); + useFocusEffect( + useCallback(() => { + void onboardingStatus.refetch(); + }, []), + ); + + const items = inventory.data?.items ?? []; + // Distinkta platser (Kyl/Frys/Skafferi …) för genvägsknappar in i Matlager. + const locations = useMemo(() => { + const seen = new Map(); + for (const it of items) if (!seen.has(it.locationType)) seen.set(it.locationType, it.locationName); + return [...seen.entries()] + .map(([type, name]) => ({ type, name })) + .sort((a, b) => orderIndex(a.type) - orderIndex(b.type)); + }, [items]); + if (inventory.isLoading) return ; if (inventory.isError) return void inventory.refetch()} />; - useFocusEffect(useCallback(() => { void onboardingStatus.refetch(); }, [])); - - const items = inventory.data?.items ?? []; const urgent = expiring.data?.items ?? []; - - const grouped = new Map(); - for (const item of items) { - const list = grouped.get(item.locationName) ?? []; - list.push(item); - grouped.set(item.locationName, list); - } - const trustStatus = inventory.data?.trustStatus; const needsProfile = onboardingStatus.data && !onboardingStatus.data.onboardingCompleted; const profileStep = onboardingStatus.data?.step ?? "b"; @@ -130,10 +128,42 @@ export default function HomeScreen() { router.push("/saved-recipes")}> ⭐ Dina sparade recept - router.push("/kitchen")}> - 🧺 Ditt kök + + {/* Matlager – städat, öppnas per plats eller som helhet (spec §8). */} + + 🧺 {t("home.inventory")} + Allt du har hemma – öppna en plats eller sök i hela lagret. + + {locations.map((loc) => ( +