feat(mobile): slutför-profil-prompt samlar kost & allergier progressivt (MIKRO 57)
CI / Typecheck, test & build (push) Failing after 42s

This commit is contained in:
Sven (AAMOS AI)
2026-08-14 18:59:39 +07:00
parent 9390cc0e66
commit 1e6407d9e6
2 changed files with 21 additions and 1 deletions
+19 -1
View File
@@ -1,7 +1,9 @@
import { Pressable, View } from "react-native"; import { Pressable, View } from "react-native";
import { router } from "expo-router"; import { useCallback } from "react";
import { router, useFocusEffect } from "expo-router";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { api } from "@/lib/api"; import { api } from "@/lib/api";
import { useAuth } from "@/lib/auth";
import { t } from "@/lib/i18n"; import { t } from "@/lib/i18n";
import { formatMinor } from "@/lib/money"; import { formatMinor } from "@/lib/money";
import { import {
@@ -53,10 +55,18 @@ export default function HomeScreen() {
queryKey: ["budget"], queryKey: ["budget"],
queryFn: () => api<BudgetSummary>("/v1/budget/summary"), queryFn: () => api<BudgetSummary>("/v1/budget/summary"),
}); });
const onboardingStatus = useQuery({
queryKey: ["onboarding-status"],
queryFn: () =>
api<{ step: "a" | "b" | "c"; onboardingCompleted: boolean }>("/v1/onboarding/status"),
});
const setOnboardingStep = useAuth((s) => s.setOnboardingStep);
if (inventory.isLoading) return <LoadingView />; if (inventory.isLoading) return <LoadingView />;
if (inventory.isError) return <ErrorView onRetry={() => void inventory.refetch()} />; if (inventory.isError) return <ErrorView onRetry={() => void inventory.refetch()} />;
useFocusEffect(useCallback(() => { void onboardingStatus.refetch(); }, []));
const items = inventory.data?.items ?? []; const items = inventory.data?.items ?? [];
const urgent = expiring.data?.items ?? []; const urgent = expiring.data?.items ?? [];
@@ -68,10 +78,18 @@ export default function HomeScreen() {
} }
const trustStatus = inventory.data?.trustStatus; const trustStatus = inventory.data?.trustStatus;
const needsProfile = onboardingStatus.data && !onboardingStatus.data.onboardingCompleted;
const profileStep = onboardingStatus.data?.step ?? "b";
return ( return (
<Screen> <Screen>
<Title>{t("home.title")}</Title> <Title>{t("home.title")}</Title>
{needsProfile && (
<Card onPress={() => { setOnboardingStep(profileStep); router.push("/onboarding"); }}>
<Heading>{t("home.completeProfile.title")}</Heading>
<Small>{t("home.completeProfile.body")}</Small>
</Card>
)}
{trustStatus && ( {trustStatus && (
<Pressable onPress={() => router.push("/reconciliation")}> <Pressable onPress={() => router.push("/reconciliation")}>
<Small style={{ marginBottom: spacing.xs, opacity: 0.8, color: colors.primary }}> <Small style={{ marginBottom: spacing.xs, opacity: 0.8, color: colors.primary }}>
+2
View File
@@ -87,6 +87,8 @@
"home.shopping": "Inköpslista", "home.shopping": "Inköpslista",
"home.thisWeek": "Denna vecka", "home.thisWeek": "Denna vecka",
"home.title": "Hemma", "home.title": "Hemma",
"home.completeProfile.title": "Gör appen smartare",
"home.completeProfile.body": "Berätta om kost och allergier så blir förslagen mer personliga (ca 30 sek).",
"home.useSoon": "Använd snart", "home.useSoon": "Använd snart",
"home.useSoonHint": "Bäst före handlar om kvalitet lukta, titta och smaka innan du slänger. Sista förbrukningsdag ska däremot respekteras.", "home.useSoonHint": "Bäst före handlar om kvalitet lukta, titta och smaka innan du slänger. Sista förbrukningsdag ska däremot respekteras.",
"home.waste": "Matsvinn", "home.waste": "Matsvinn",