import { Alert } from "react-native"; import { router } from "expo-router"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { api } from "@/lib/api"; import { firebaseAuthProvider } from "@/lib/auth-provider/firebase"; import { persistLanguageTag, useAuth } from "@/lib/auth"; import { SUPPORTED_LANGUAGES, t } from "@/lib/i18n"; import { Body, Button, Card, ErrorView, Heading, LoadingView, Row, Screen, Small, Spacer, Tag, } from "@/components/ui"; /** Profil: konto, samtycken, minne, prenumeration, GDPR-åtgärder. */ interface Me { displayName: string; email: string; emailVerified: boolean; precisionMode: string; } interface Entitlements { plan: string; status: string; aiScansPerMonth: number; aiScansUsedThisMonth: number; expiresAt?: string; } interface Consent { kind: string; status: string; } interface Prefs { dietPattern?: string | null; allergens?: string[] | null; religiousRule?: string | null; } /** Samtyckesetiketter ur i18n-katalogen: profile.consent. (12 språk). */ const CONSENT_KINDS = [ "personalization", "anonymized_improvement", "image_training", "health_integration", "location_weather", "push_notifications", "product_analytics", ] as const; const DIETS = [ "omnivore", "flexitarian", "pescatarian", "vegetarian", "vegan", "nordic", "paleo", "low_carb", "carnivore", ] as const; const ALLERGENS = [ "gluten", "milk", "eggs", "tree_nuts", "peanuts", "fish", "crustaceans", "soy", "sesame", ] as const; const RELIGIOUS = ["none", "halal", "kosher", "hindu_no_beef", "buddhist_vegetarian"] as const; export default function ProfileScreen() { const queryClient = useQueryClient(); const rawLogout = useAuth((s) => s.logout); const logout = async () => { await firebaseAuthProvider.signOut().catch(() => {}); await rawLogout(); }; const me = useQuery({ queryKey: ["me"], queryFn: () => api("/v1/me") }); const entitlements = useQuery({ queryKey: ["entitlements"], queryFn: () => api("/v1/me/entitlements"), }); const consents = useQuery({ queryKey: ["consents"], queryFn: () => api("/v1/me/consents"), }); const prefs = useQuery({ queryKey: ["preferences"], queryFn: () => api("/v1/me/preferences"), }); const savePrefs = useMutation({ mutationFn: (body: Record) => api("/v1/me/preferences", { method: "PATCH", body }), onSuccess: () => void queryClient.invalidateQueries({ queryKey: ["preferences"] }), onError: (err) => Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")), }); const setConsent = useMutation({ mutationFn: ({ kind, granted }: { kind: string; granted: boolean }) => api("/v1/me/consents", { method: "PUT", body: { kind, granted } }), onSuccess: () => void queryClient.invalidateQueries({ queryKey: ["consents"] }), onError: (err) => Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")), }); const togglePrecision = useMutation({ mutationFn: (mode: string) => api("/v1/me", { method: "PATCH", body: { precisionMode: mode } }), onSuccess: () => void queryClient.invalidateQueries({ queryKey: ["me"] }), onError: (err) => Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")), }); const deleteAccount = useMutation({ mutationFn: () => api("/v1/me", { method: "DELETE" }), onSuccess: () => void logout().then(() => router.replace("/(auth)/login")), onError: (err) => Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")), }); const resend = useMutation({ mutationFn: () => api("/v1/auth/resend-verification", { method: "POST" }), onError: (err) => Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")), }); // Språkval (i18n M4): sparas i backend-preferenserna + lokalt, byter direkt. const localePrefs = useQuery({ queryKey: ["locale-preferences"], queryFn: () => api<{ languageTag: string }>("/v1/me/locale-preferences"), }); const setLanguage = useMutation({ mutationFn: (languageTag: string) => api("/v1/me/locale-preferences", { method: "PATCH", body: { languageTag } }), onSuccess: async (_data, languageTag) => { await persistLanguageTag(languageTag); await queryClient.invalidateQueries(); }, onError: (err) => Alert.alert(t("common.oops"), err instanceof Error ? err.message : t("common.error")), }); if (me.isLoading) return ; if (me.isError) return void me.refetch()} />; const consentMap = new Map((consents.data ?? []).map((c) => [c.kind, c.status])); const curDiet = prefs.data?.dietPattern ?? "omnivore"; const curAllergens = prefs.data?.allergens ?? []; const curReligious = prefs.data?.religiousRule ?? "none"; return ( {me.data?.displayName} {me.data?.email} {me.data && !me.data.emailVerified && ( <> ⚠︎ {t("profile.emailUnverified")}