import { useEffect, useRef, useState } from 'react'; import { View, Text, TouchableOpacity, Animated } from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { useRouter } from 'expo-router'; import { Ionicons } from '@expo/vector-icons'; import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { useMe } from '../hooks/useMe'; import { useProtectionCoverage } from '../hooks/useProfileData'; import { apiFetch } from '../lib/api'; import { FormSheet } from './FormSheet'; import { useColors } from '../lib/theme'; const MILESTONES = [3, 7, 10] as const; function storageKey(userId: string, days: number) { return `@rebreak/diga_milestone_${userId}_${days}`; } type DemographicsResp = { birthYear: number | null } & Record; export function DiGaMilestoneModal() { const { t } = useTranslation(); const colors = useColors(); const router = useRouter(); const { me } = useMe(); const { coverage } = useProtectionCoverage(); const [milestone, setMilestone] = useState(null); const scaleAnim = useRef(new Animated.Value(0.8)).current; // Lean demographics check — only birthYear needed to determine completeness const { data: demo } = useQuery({ queryKey: ['diga-demo-check'], queryFn: () => apiFetch('/api/profile/me/demographics'), enabled: !!me, staleTime: 60_000, }); useEffect(() => { if (!me || demo === undefined) return; // Kumulative Schutz-Tage (fällt NIE auf 0 zurück, anders als die // zusammenhängende Streak-Phase). So erreicht jeder engagierte User // irgendwann einen Milestone — auch rückfall-anfällige, deren DiGA-Daten // am wertvollsten sind. const protectedDays = coverage?.protectedDays ?? 0; const demographicsComplete = !!(demo?.birthYear); if (demographicsComplete) return; // already filled → never show (async () => { // Find highest milestone reached and not yet shown for (let i = MILESTONES.length - 1; i >= 0; i--) { const m = MILESTONES[i]; if (protectedDays < m) continue; const shown = await AsyncStorage.getItem(storageKey(me.id, m)); if (!shown) { setMilestone(m); return; } } })(); }, [me?.id, coverage?.protectedDays, demo]); useEffect(() => { if (milestone !== null) { Animated.spring(scaleAnim, { toValue: 1, useNativeDriver: true, damping: 14 }).start(); } else { scaleAnim.setValue(0.8); } }, [milestone]); async function dismiss() { if (!me || !milestone) return; await AsyncStorage.setItem(storageKey(me.id, milestone), '1'); setMilestone(null); } async function openProfile() { await dismiss(); router.push('/profile?openDemo=1' as any); } if (!milestone) return null; const badgeColor = milestone >= 10 ? '#f59e0b' : milestone >= 7 ? '#8b5cf6' : colors.brandOrange; return ( {/* Milestone badge */} {milestone >= 10 ? '🏆' : milestone >= 7 ? '🌟' : '🎉'} {t('diga_milestone.badge', { days: milestone })} {t('diga_milestone.title', { days: milestone })} {t('diga_milestone.body')} {/* Primary CTA */} {t('diga_milestone.cta')} {/* Dismiss */} {t('diga_milestone.later')} ); }