Files
Cibello-app/apps/mobile/src/app/(tabs)/_layout.tsx
T
Sven (AAMOS AI) 72b1d9d5a3
CI / Typecheck, test & build (push) Successful in 1m35s
fix(mobile): samtyckesgrinden hämtar om status efter accept (fastnade annars)
2026-08-14 05:29:01 +07:00

111 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Redirect, Tabs } from "expo-router";
import { Text } from "react-native";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { api, getConsent, type ConsentStatus } from "@/lib/api";
import { persistLanguageTag, useAuth } from "@/lib/auth";
import { colors } from "@/lib/theme";
import { getLanguageTag, t } from "@/lib/i18n";
import { setMeasurementSystem, setUnitLanguage } from "@/lib/units";
import { ConsentScreen } from "@/components/ConsentScreen";
import type { MeasurementSystem } from "@app/shared-types";
import { TERMS_VERSION } from "@app/shared-types";
function TabIcon({ glyph, focused }: { glyph: string; focused: boolean }) {
return <Text style={{ fontSize: 22, opacity: focused ? 1 : 0.45 }}>{glyph}</Text>;
}
interface LocalePrefs {
languageTag: string;
measurementSystem: MeasurementSystem;
}
/** Applicera backend-preferenser på språk/mått vid inloggad start (i18n M4M5). */
function useApplyLocalePreferences(enabled: boolean) {
useQuery({
queryKey: ["locale-preferences"],
queryFn: async () => {
const prefs = await api<LocalePrefs>("/v1/me/locale-preferences");
setMeasurementSystem(prefs.measurementSystem);
setUnitLanguage(prefs.languageTag.split("-")[0] ?? "sv");
if (prefs.languageTag !== getLanguageTag()) await persistLanguageTag(prefs.languageTag);
return prefs;
},
enabled,
staleTime: 3600_000,
});
}
export default function TabsLayout() {
const accessToken = useAuth((s) => s.accessToken);
const onboardingCompleted = useAuth((s) => s.onboardingCompleted);
const onboardingStep = useAuth((s) => s.onboardingStep);
useApplyLocalePreferences(Boolean(accessToken));
const queryClient = useQueryClient();
const { data: consent, isLoading: consentLoading } = useQuery<ConsentStatus>({
queryKey: ["consent"],
queryFn: getConsent,
enabled: Boolean(accessToken),
staleTime: 60_000,
});
if (!accessToken) return <Redirect href="/(auth)/login" />;
if (consentLoading) return null;
if (!consent?.accepted || consent.version !== TERMS_VERSION) {
return (
<ConsentScreen
onAccepted={() => void queryClient.invalidateQueries({ queryKey: ["consent"] })}
/>
);
}
// Progressive onboarding (FAS 1b): only block if step A not done
if (!onboardingCompleted && onboardingStep === "a") return <Redirect href="/onboarding" />;
return (
<Tabs
screenOptions={{
headerShown: false,
tabBarActiveTintColor: colors.primaryDark,
tabBarInactiveTintColor: colors.textMuted,
tabBarStyle: { backgroundColor: colors.surface, borderTopColor: colors.border },
}}
>
<Tabs.Screen
name="index"
options={{
title: t("tabs.whatToEat"),
tabBarIcon: ({ focused }) => <TabIcon glyph="🍽️" focused={focused} />,
}}
/>
<Tabs.Screen
name="scan"
options={{
title: t("tabs.scan"),
tabBarIcon: ({ focused }) => <TabIcon glyph="📷" focused={focused} />,
}}
/>
<Tabs.Screen
name="my-day"
options={{
title: t("tabs.myDay"),
tabBarIcon: ({ focused }) => <TabIcon glyph="📊" focused={focused} />,
}}
/>
<Tabs.Screen
name="plan"
options={{
title: t("tabs.plan"),
tabBarIcon: ({ focused }) => <TabIcon glyph="📅" focused={focused} />,
}}
/>
<Tabs.Screen
name="home"
options={{
title: t("tabs.home"),
tabBarIcon: ({ focused }) => <TabIcon glyph="🏠" focused={focused} />,
}}
/>
</Tabs>
);
}