import { Alert, Platform, Pressable, ScrollView, Text, View, } from 'react-native'; import { useState } from 'react'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useRouter } from 'expo-router'; import { Ionicons } from '@expo/vector-icons'; import { useNativeActionSheet } from '../lib/useNativeActionSheet'; import { useTranslation } from 'react-i18next'; import { colors } from '../lib/theme'; import { useAuthStore } from '../stores/auth'; import { useThemeStore, type ThemeMode } from '../stores/theme'; import { useLanguageStore, type AppLanguage } from '../stores/language'; import { useUserPlan } from '../hooks/useUserPlan'; import { AppHeader } from '../components/AppHeader'; // ─── Settings Screen ─────────────────────────────────────────────────────── type PickerOption = { value: T; label: string }; type SectionRow = { icon: React.ComponentProps['name']; label: string; sublabel: string; soon?: boolean; destructive?: boolean; value?: string; onPress?: () => void; }; type Section = { key: string; title: string; rows: SectionRow[]; }; export default function SettingsScreen() { const router = useRouter(); const insets = useSafeAreaInsets(); const { t } = useTranslation(); const { signOut } = useAuthStore(); const { mode: themeMode, setMode: setThemeMode } = useThemeStore(); const { language, setLanguage } = useLanguageStore(); const { plan } = useUserPlan(); const { showActionSheetWithOptions } = useNativeActionSheet(); // Lyra Voice: hardcoded ElevenLabs voice IDs (expandable by user later) // Backend endpoint PATCH /api/profile/me/demographics does NOT accept lyraVoiceId. // A dedicated PATCH /api/profile/me/lyra-voice endpoint is needed from backend-agent. // For now: picker is wired to local state only, changes are NOT persisted. const [selectedVoice, setSelectedVoice] = useState('EXAVITQu4vr4xnSDxMaL'); function pickFromOptions( title: string, options: PickerOption[], onPick: (value: T) => void, ) { const labels = options.map((o) => o.label); showActionSheetWithOptions( { title, options: [...labels, t('common.cancel')], cancelButtonIndex: labels.length, }, (idx) => { if (idx === undefined || idx === labels.length) return; onPick(options[idx].value); }, ); } async function handleSignOut() { Alert.alert(t('auth.signOut'), '', [ { text: t('common.cancel'), style: 'cancel' }, { text: t('auth.signOut'), style: 'cancel', onPress: async () => { await signOut(); router.replace('/'); }, }, ]); } const themeOptions: PickerOption[] = [ { value: 'system', label: t('settings.theme_system') }, { value: 'light', label: t('settings.theme_light') }, { value: 'dark', label: t('settings.theme_dark') }, ]; const themeLabel = themeMode === 'system' ? t('settings.theme_system') : themeMode === 'light' ? t('settings.theme_light') : t('settings.theme_dark'); const langOptions: PickerOption[] = [ { value: 'de', label: t('settings.language_de') }, { value: 'en', label: t('settings.language_en') }, ]; const voiceOptions: PickerOption[] = [ { value: 'EXAVITQu4vr4xnSDxMaL', label: t('settings.lyra_voice_sarah') }, { value: 'ThT5KcBeYPX3keUQqHPh', label: t('settings.lyra_voice_aria') }, { value: 'XB0fDUnXU5powFXDhCwa', label: t('settings.lyra_voice_charlotte') }, { value: 'Xb7hH8MSUJpSbSDYk0k2', label: t('settings.lyra_voice_alice') }, { value: 'pqHfZKP75CvOlQylNhV4', label: t('settings.lyra_voice_bill') }, ]; const selectedVoiceName = voiceOptions.find((v) => v.value === selectedVoice)?.label ?? t('settings.lyra_voice_sarah'); const sections: Section[] = [ // Profile-Section entfernt — Profile-Edits sind in /profile-Page direkt { key: 'theme', title: t('settings.section_theme'), rows: [ { icon: 'color-palette-outline', label: t('settings.theme'), sublabel: t('settings.theme_desc'), value: themeLabel, onPress: () => pickFromOptions(t('settings.theme'), themeOptions, (v) => setThemeMode(v), ), }, { icon: 'language-outline', label: t('settings.language'), sublabel: t('settings.language_desc'), value: language === 'de' ? t('settings.language_de') : t('settings.language_en'), onPress: () => pickFromOptions(t('settings.language'), langOptions, (v) => setLanguage(v), ), }, ], }, { key: 'notifications', title: t('settings.section_notifications'), rows: [ { icon: 'notifications-outline', label: t('settings.notifications_push'), sublabel: t('settings.notifications_push_desc'), soon: true, }, { icon: 'flame-outline', label: t('settings.notifications_streak'), sublabel: t('settings.notifications_streak_desc'), soon: true, }, ], }, { key: 'devices', title: t('settings.section_devices'), rows: [ { icon: 'phone-portrait-outline', label: t('settings.devices'), sublabel: t('settings.devices_desc'), soon: true, }, { icon: 'star-outline', label: t('settings.subscription'), sublabel: t('settings.subscription_desc'), soon: true, }, ], }, { key: 'lyra', title: t('settings.section_lyra'), rows: [ { icon: 'mic-outline', label: t('settings.lyra_voice'), sublabel: plan === 'legend' ? t('settings.lyra_voice_desc') : t('settings.lyra_voice_only_legend'), value: plan === 'legend' ? selectedVoiceName : undefined, // Voice picker is wired but changes are local-only until // PATCH /api/profile/me/lyra-voice endpoint is added by backend-agent. onPress: plan === 'legend' ? () => pickFromOptions( t('settings.lyra_voice'), voiceOptions, (v) => setSelectedVoice(v), ) : undefined, soon: plan !== 'legend', }, ], }, { key: 'account', title: t('settings.danger_section'), rows: [ { icon: 'log-out-outline', label: t('settings.sign_out'), sublabel: '', onPress: handleSignOut, }, { icon: 'trash-outline', label: t('settings.delete_account'), sublabel: t('settings.delete_desc'), destructive: true, soon: true, }, ], }, ]; if (__DEV__) { sections.push({ key: 'debug', title: t('settings.section_debug'), rows: [ { icon: 'bug-outline', label: t('settings.debug_llm'), sublabel: t('settings.debug_llm_desc'), soon: true, }, { icon: 'volume-high-outline', label: t('settings.debug_tts'), sublabel: t('settings.debug_tts_desc'), soon: true, }, ], }); } return ( {sections.map((section) => ( {section.title} {section.rows.map((row, i) => ( ({ opacity: row.soon ? 0.5 : pressed ? 0.7 : 1, })} > {row.label} {row.sublabel ? ( {row.sublabel} ) : null} {row.soon ? ( {t('settings.soon_badge')} ) : row.value ? ( {row.value} ) : ( )} ))} ))} {t('settings.skeleton_footer')} {Platform.OS} ); }