/** * Settings FormSheet * Profile, preferences, premium, legal, reset progress. */ import { View, Text, StyleSheet, ScrollView, Pressable, Switch, Alert } from 'react-native' import { useRouter } from 'expo-router' import { useSafeAreaInsets } from 'react-native-safe-area-context' import { useTranslation } from 'react-i18next' import { Icon, type IconName } from '@/src/shared/components/Icon' import { useUserStore } from '@/src/shared/stores/userStore' import { useProgressStore } from '@/src/shared/stores/progressStore' import { TYPOGRAPHY } from '@/src/shared/constants/typography' import { SPACING } from '@/src/shared/constants/spacing' import { RADIUS } from '@/src/shared/constants/borderRadius' import { TEXT, NAVY, GREEN, BORDER_COLORS } from '@/src/shared/constants/colors' export default function SettingsScreen() { const router = useRouter() const insets = useSafeAreaInsets() const { t } = useTranslation() const profile = useUserStore(s => s.profile) const settings = useUserStore(s => s.settings) const updateSettings = useUserStore(s => s.updateSettings) const resetProgress = useProgressStore(s => s.resetProgress) const isPremium = profile.subscription !== 'free' const handleResetProgress = () => { Alert.alert( t('screens:settings.resetTitle'), t('screens:settings.resetMessage'), [ { text: t('common:cancel'), style: 'cancel' }, { text: t('screens:settings.resetConfirm'), style: 'destructive', onPress: () => { resetProgress() }, }, ], ) } return ( {t('screens:settings.title')} {/* Profile */}
{!isPremium && ( router.push('/paywall')} accent={GREEN[500]} /> )}
{/* Preferences */}
updateSettings({ haptics: v })} /> updateSettings({ soundEffects: v })} /> updateSettings({ voiceCoaching: v })} /> updateSettings({ musicEnabled: v })} />
{/* Legal */}
router.push('/terms')} /> router.push('/privacy')} />
{/* Danger */}
{t('screens:settings.resetProgress')}
{t('screens:settings.version')}
) } function Section({ title, children }: { title: string; children: React.ReactNode }) { return ( {title} {children} ) } function Row({ label, value, accent }: { label: string; value: string; accent?: string }) { return ( {label} {value} ) } function SwitchRow({ label, value, onChange, }: { label: string value: boolean onChange: (value: boolean) => void }) { return ( {label} ) } function LinkRow({ icon, label, onPress, accent, }: { icon: IconName label: string onPress: () => void accent?: string }) { return ( {label} ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: NAVY[900] }, header: { ...TYPOGRAPHY.LARGE_TITLE, color: TEXT.PRIMARY, marginBottom: SPACING[4] }, section: { marginBottom: SPACING[6] }, sectionTitle: { ...TYPOGRAPHY.CAPTION_1, color: TEXT.TERTIARY, textTransform: 'uppercase', letterSpacing: 0.5, marginBottom: SPACING[2], paddingHorizontal: SPACING[2], }, sectionBody: { backgroundColor: NAVY[800], borderRadius: RADIUS.MD, borderWidth: 1, borderColor: BORDER_COLORS.DIM, overflow: 'hidden', }, row: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: SPACING[4], paddingVertical: SPACING[3], borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: BORDER_COLORS.DIM, gap: SPACING[3], }, rowLabel: { ...TYPOGRAPHY.BODY, color: TEXT.PRIMARY }, rowValue: { ...TYPOGRAPHY.BODY, color: TEXT.SECONDARY }, linkLeft: { flexDirection: 'row', alignItems: 'center', gap: SPACING[3] }, dangerRow: { flexDirection: 'row', alignItems: 'center', gap: SPACING[3], paddingHorizontal: SPACING[4], paddingVertical: SPACING[3], }, dangerText: { ...TYPOGRAPHY.BODY, color: '#FF453A' }, version: { ...TYPOGRAPHY.CAPTION_1, color: TEXT.TERTIARY, textAlign: 'center', marginTop: SPACING[4], }, })