Initial commit (unpacked platform)

This commit is contained in:
Sven (AAMOS AI)
2026-08-05 19:21:11 +07:00
commit ac5340195a
314 changed files with 57584 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
import { useEffect, useState } from "react";
import { Stack } from "expo-router";
import { StatusBar } from "expo-status-bar";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { QueryClient } from "@tanstack/react-query";
import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client";
import { createAsyncStoragePersister } from "@tanstack/query-async-storage-persister";
import { useAuth } from "@/lib/auth";
import { BRAND } from "@/lib/brand";
import { t, useI18nVersion } from "@/lib/i18n";
import { colors } from "@/lib/theme";
import { LoadingView } from "@/components/ui";
/**
* Rotlayout: React Query med AsyncStorage-persistens för Smart Cache/offline
* (spec §44: cachelagrade recept, lager och inköpslista fungerar offline).
*/
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 30_000,
gcTime: 7 * 24 * 3600_000, // behåll cache en vecka för offline-läge
retry: 1,
},
},
});
const persister = createAsyncStoragePersister({
storage: AsyncStorage,
key: `${BRAND.slug}-query-cache`,
});
export default function RootLayout() {
const hydrate = useAuth((s) => s.hydrate);
const hydrated = useAuth((s) => s.hydrated);
const [ready, setReady] = useState(false);
// Språkbyte utan omstart (i18n M4): versionen bumpar vid setLocale och
// key={} re-monterar hela trädet så att alla t()-strängar byts direkt.
const i18nVersion = useI18nVersion();
useEffect(() => {
void hydrate().then(() => setReady(true));
}, [hydrate]);
if (!hydrated || !ready) return <LoadingView />;
return (
<PersistQueryClientProvider
key={`i18n-${i18nVersion}`}
client={queryClient}
persistOptions={{ persister }}
>
<StatusBar style="dark" />
<Stack
screenOptions={{
headerStyle: { backgroundColor: colors.background },
headerTintColor: colors.text,
headerShadowVisible: false,
contentStyle: { backgroundColor: colors.background },
}}
>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="(auth)/login" options={{ headerShown: false }} />
<Stack.Screen name="(auth)/register" options={{ headerShown: false }} />
<Stack.Screen name="(auth)/forgot-password" options={{ headerShown: false }} />
<Stack.Screen name="(auth)/reset-password" options={{ headerShown: false }} />
<Stack.Screen name="(auth)/verify-email" options={{ headerShown: false }} />
<Stack.Screen name="onboarding" options={{ headerShown: false, gestureEnabled: false }} />
<Stack.Screen name="recipe/[id]" options={{ title: "" }} />
<Stack.Screen
name="cooking/[id]"
options={{ title: "", presentation: "fullScreenModal" }}
/>
<Stack.Screen name="scan-review/[jobId]" options={{ title: t("scan.review.title") }} />
<Stack.Screen name="shopping" options={{ title: t("shopping.title") }} />
<Stack.Screen name="meal-boxes" options={{ title: t("mealbox.title") }} />
<Stack.Screen name="household" options={{ title: t("home.household") }} />
<Stack.Screen name="memory" options={{ title: t("memory.title") }} />
<Stack.Screen name="profile" options={{ title: t("profile.title") }} />
<Stack.Screen
name="paywall"
options={{ title: t("paywall.title"), presentation: "modal" }}
/>
<Stack.Screen
name="log-meal"
options={{ title: t("myday.logMeal"), presentation: "modal" }}
/>
<Stack.Screen name="barcode" options={{ title: "Streckkod" }} />
</Stack>
</PersistQueryClientProvider>
);
}