import React, { useEffect, useRef, useState } from 'react'; import { Animated, Easing, Image, ScrollView, StyleSheet, Text, View } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { Ionicons } from '@expo/vector-icons'; import { router } from 'expo-router'; import Svg, { Circle } from 'react-native-svg'; import { useApp } from '../../context/AppContext'; import { useColors } from '../../constants/Colors'; import { useSafeAnalytics } from '../../services/analytics'; import { PreAuthOnboardingService, PreAuthAnswers } from '../../services/preAuthOnboardingService'; import { Language } from '../../types'; const getCopy = (language: Language) => { if (language === 'de') { return { status: 'Dein Plan wird zusammengestellt…', // Schritte beschreiben den Nutzen fuer den Nutzer, nicht unsere Prozesse. steps: [ 'Deine Antworten werden ausgewertet', 'Mögliche Ursachen für dein Symptom werden gewichtet', 'Prüfschritte für deine Lichtsituation werden ausgewählt', 'Dein 7-Tage-Plan steht', ], summaryTitle: 'Dein Plan basiert auf', noAnswers: 'Deinen Angaben aus dem Gespräch', situations: { acute: 'Akutes Problem', slow: 'Langsame Veränderung', prevention: 'Vorbeugung', } as Record, symptoms: { yellow: 'Gelbe Blätter', brown_tips: 'Braune Spitzen', drooping: 'Hängende Blätter', spots: 'Flecken oder Belag', pests: 'Schädlinge', other: 'Anderes Symptom', } as Record, lights: { bright_indirect: 'Helles, indirektes Licht', low_light: 'Wenig Licht', direct_sunlight: 'Direkte Sonne', } as Record, experiences: { beginner: 'Einsteigerin', intermediate: 'Etwas Erfahrung', advanced: 'Erfahren', } as Record, }; } if (language === 'es') { return { status: 'Preparando tu plan…', steps: [ 'Analizando tus respuestas', 'Ponderando las causas posibles de tu síntoma', 'Eligiendo pasos de revisión para tu luz', 'Tu plan de 7 días está listo', ], summaryTitle: 'Tu plan se basa en', noAnswers: 'Lo que nos contaste en el chat', situations: { acute: 'Problema agudo', slow: 'Cambio lento', prevention: 'Prevención', } as Record, symptoms: { yellow: 'Hojas amarillas', brown_tips: 'Puntas marrones', drooping: 'Hojas caídas', spots: 'Manchas o residuo', pests: 'Plagas', other: 'Otro síntoma', } as Record, lights: { bright_indirect: 'Luz brillante indirecta', low_light: 'Poca luz', direct_sunlight: 'Sol directo', } as Record, experiences: { beginner: 'Principiante', intermediate: 'Algo de experiencia', advanced: 'Con experiencia', } as Record, }; } return { status: 'Putting your plan together…', steps: [ 'Reviewing your answers', 'Weighing possible causes for your symptom', 'Picking checks for your light situation', 'Your 7-day plan is ready', ], summaryTitle: 'Your plan is based on', noAnswers: 'What you told us in the chat', situations: { acute: 'Acute problem', slow: 'Slow change', prevention: 'Prevention', } as Record, symptoms: { yellow: 'Yellow leaves', brown_tips: 'Brown tips', drooping: 'Drooping leaves', spots: 'Spots or residue', pests: 'Pests', other: 'Other symptom', } as Record, lights: { bright_indirect: 'Bright, indirect light', low_light: 'Low light', direct_sunlight: 'Direct sun', } as Record, experiences: { beginner: 'Beginner', intermediate: 'Some experience', advanced: 'Experienced', } as Record, }; }; const STEP_THRESHOLDS = [25, 50, 75, 95]; const RING_SIZE = 150; const RING_STROKE_WIDTH = 7; const RING_RADIUS = (RING_SIZE - RING_STROKE_WIDTH) / 2; const RING_CIRCUMFERENCE = 2 * Math.PI * RING_RADIUS; const AnimatedCircle = Animated.createAnimatedComponent(Circle); export default function OnboardingPersonalizingScreen() { const { language, isDarkMode, colorPalette } = useApp(); const colors = useColors(isDarkMode, colorPalette); const posthog = useSafeAnalytics(); const copy = getCopy(language); const progress = useRef(new Animated.Value(0)).current; const [percent, setPercent] = useState(0); const [answers, setAnswers] = useState({}); const navigated = useRef(false); // Die eigenen Angaben zurueckspiegeln beweist "es geht um MEINE Pflanze" // (Belief 4) durch Demonstration statt durch Behauptung. useEffect(() => { void PreAuthOnboardingService.getAnswers().then(setAnswers); }, []); const summaryChips = [ answers.situation ? copy.situations[answers.situation] : null, answers.symptom ? copy.symptoms[answers.symptom] : null, answers.lightLevel ? copy.lights[answers.lightLevel] : null, answers.experienceLevel ? copy.experiences[answers.experienceLevel] : null, ].filter((chip): chip is string => Boolean(chip)); const strokeDashoffset = progress.interpolate({ inputRange: [0, 100], outputRange: [RING_CIRCUMFERENCE, 0], }); useEffect(() => { posthog.capture('onboarding_personalizing_viewed'); const listener = progress.addListener(({ value }) => setPercent(Math.round(value))); Animated.timing(progress, { toValue: 100, duration: 6000, easing: Easing.inOut(Easing.cubic), useNativeDriver: false, }).start(({ finished }) => { if (finished && !navigated.current) { navigated.current = true; setTimeout(() => { posthog.capture('paywall_opened', { source: 'onboarding' }); router.replace('/profile/billing?view=paywall&context=onboarding'); }, 450); } }); return () => progress.removeListener(listener); }, [progress, posthog]); return ( {/* Scrollbar, damit die Zusammenfassungs-Karte auf kleinen Geraeten und bei grosser Systemschrift nicht unten wegfaellt. */} {percent}% {copy.status} {copy.steps.map((label, index) => { const done = percent >= STEP_THRESHOLDS[index]; return ( {label} ); })} {copy.summaryTitle} {summaryChips.length > 0 ? ( summaryChips.map((chip) => ( {chip} )) ) : ( {copy.noAnswers} )} ); } const styles = StyleSheet.create({ safe: { flex: 1 }, scroll: { flex: 1 }, scrollContent: { flexGrow: 1, alignItems: 'center', paddingHorizontal: 24, paddingTop: 30, paddingBottom: 16 }, percent: { fontSize: 56, fontWeight: '900', marginBottom: 16 }, ringWrap: { width: 150, height: 150, alignItems: 'center', justifyContent: 'center', marginBottom: 22 }, ringImage: { width: 112, height: 112, borderRadius: 56 }, statusPill: { flexDirection: 'row', alignItems: 'center', gap: 8, borderRadius: 999, paddingHorizontal: 18, paddingVertical: 11, marginBottom: 26 }, statusText: { fontSize: 14.5, fontWeight: '800' }, checklist: { alignSelf: 'stretch', gap: 15, marginBottom: 26, paddingHorizontal: 8 }, checkRow: { flexDirection: 'row', alignItems: 'center', gap: 12 }, checkLabel: { fontSize: 16.5, fontWeight: '700' }, testimonialCard: { alignSelf: 'stretch', borderRadius: 18, padding: 16, marginBottom: 14 }, testimonialText: { fontSize: 14, lineHeight: 20 }, summaryTitle: { fontSize: 10.5, fontWeight: '900', letterSpacing: 0.9, textTransform: 'uppercase', marginBottom: 10 }, summaryChips: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 }, summaryChip: { borderRadius: 999, paddingHorizontal: 12, paddingVertical: 7 }, summaryChipText: { fontSize: 12.5, fontWeight: '700' }, });