223 lines
8.0 KiB
TypeScript
223 lines
8.0 KiB
TypeScript
import { ScrollView, View, Text, Pressable, Switch } from 'react-native';
|
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
import { useRouter } from 'expo-router';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
import { useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useAuthStore } from '../stores/auth';
|
|
import { Card } from '../components/Card';
|
|
import { Button } from '../components/Button';
|
|
import { colors } from '../lib/theme';
|
|
|
|
type SettingRow = {
|
|
label: string;
|
|
sublabel?: string;
|
|
icon: React.ComponentProps<typeof Ionicons>['name'];
|
|
iconColor: string;
|
|
onPress?: () => void;
|
|
right?: React.ReactNode;
|
|
};
|
|
|
|
export default function SettingsScreen() {
|
|
const router = useRouter();
|
|
const { t } = useTranslation();
|
|
const { user, signOut } = useAuthStore();
|
|
const [notifPush, setNotifPush] = useState(true);
|
|
const [notifStreak, setNotifStreak] = useState(true);
|
|
|
|
const email = user?.email ?? '';
|
|
const initials = email.slice(0, 2).toUpperCase();
|
|
|
|
async function handleSignOut() {
|
|
await signOut();
|
|
router.replace('/');
|
|
}
|
|
|
|
const accountRows: SettingRow[] = [
|
|
{
|
|
label: t('settings.edit_profile'),
|
|
icon: 'pencil-outline',
|
|
iconColor: '#6366f1',
|
|
onPress: () => {},
|
|
},
|
|
{
|
|
label: t('settings.devices'),
|
|
sublabel: t('settings.devices_desc'),
|
|
icon: 'phone-portrait-outline',
|
|
iconColor: '#16a34a',
|
|
onPress: () => {},
|
|
},
|
|
{
|
|
label: t('settings.subscription'),
|
|
sublabel: t('settings.plan_free'),
|
|
icon: 'star-outline',
|
|
iconColor: colors.brandOrange,
|
|
onPress: () => {},
|
|
},
|
|
];
|
|
|
|
const prefRows: SettingRow[] = [
|
|
{
|
|
label: t('settings.push_notifications'),
|
|
icon: 'notifications-outline',
|
|
iconColor: '#2563eb',
|
|
right: (
|
|
<Switch
|
|
value={notifPush}
|
|
onValueChange={setNotifPush}
|
|
trackColor={{ false: '#e5e5e5', true: colors.brandOrange + '60' }}
|
|
thumbColor={notifPush ? colors.brandOrange : '#a3a3a3'}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
label: t('settings.streak_reminders'),
|
|
icon: 'flame-outline',
|
|
iconColor: '#f97316',
|
|
right: (
|
|
<Switch
|
|
value={notifStreak}
|
|
onValueChange={setNotifStreak}
|
|
trackColor={{ false: '#e5e5e5', true: colors.brandOrange + '60' }}
|
|
thumbColor={notifStreak ? colors.brandOrange : '#a3a3a3'}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
label: t('settings.language'),
|
|
sublabel: t('settings.language_current'),
|
|
icon: 'language-outline',
|
|
iconColor: '#a78bfa',
|
|
onPress: () => {},
|
|
},
|
|
];
|
|
|
|
return (
|
|
<SafeAreaView className="flex-1 bg-neutral-50" edges={['top']}>
|
|
<View className="px-3 pt-1 pb-3 flex-row items-center gap-2">
|
|
<Pressable
|
|
onPress={() => router.replace('/(app)' as never)}
|
|
hitSlop={8}
|
|
className="w-10 h-10 items-center justify-center"
|
|
style={({ pressed }) => ({ opacity: pressed ? 0.6 : 1 })}
|
|
>
|
|
<Ionicons name="chevron-back" size={26} color={colors.text} />
|
|
</Pressable>
|
|
<Text className="text-neutral-900 text-xl" style={{ fontFamily: 'Nunito_700Bold' }}>{t('settings.title')}</Text>
|
|
</View>
|
|
|
|
<ScrollView
|
|
className="flex-1"
|
|
contentContainerStyle={{ paddingHorizontal: 20, paddingBottom: 40, paddingTop: 4 }}
|
|
showsVerticalScrollIndicator={false}
|
|
>
|
|
{/* Account Card */}
|
|
<Card className="mb-5">
|
|
<View className="flex-row items-center gap-3">
|
|
<View className="w-14 h-14 rounded-full bg-rebreak-500 items-center justify-center">
|
|
<Text className="text-white text-lg" style={{ fontFamily: 'Nunito_800ExtraBold' }}>{initials}</Text>
|
|
</View>
|
|
<View className="flex-1">
|
|
<Text className="text-neutral-900 text-base" numberOfLines={1} style={{ fontFamily: 'Nunito_700Bold' }}>
|
|
{email}
|
|
</Text>
|
|
<View className="flex-row items-center gap-1.5 mt-1">
|
|
<View className="w-1.5 h-1.5 rounded-full bg-green-500" />
|
|
<Text className="text-neutral-500 text-xs" style={{ fontFamily: 'Nunito_400Regular' }}>{t('settings.plan_free')}</Text>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
<View className="mt-4 pt-3 border-t border-neutral-100">
|
|
<Button variant="secondary" onPress={() => {}}>
|
|
{t('settings.upgrade_cta')}
|
|
</Button>
|
|
</View>
|
|
</Card>
|
|
|
|
{/* Account Section */}
|
|
<Text className="text-neutral-400 text-xs uppercase tracking-wider mb-2" style={{ fontFamily: 'Nunito_600SemiBold' }}>
|
|
{t('settings.account_section')}
|
|
</Text>
|
|
<Card className="mb-5 py-0 overflow-hidden">
|
|
{accountRows.map((row, i) => (
|
|
<Pressable
|
|
key={row.label}
|
|
onPress={row.onPress}
|
|
className={`flex-row items-center gap-3 px-4 py-3.5 ${
|
|
i < accountRows.length - 1 ? 'border-b border-neutral-100' : ''
|
|
}`}
|
|
style={({ pressed }) => ({ opacity: pressed ? 0.7 : 1 })}
|
|
>
|
|
<View
|
|
className="w-8 h-8 rounded-xl items-center justify-center"
|
|
style={{ backgroundColor: row.iconColor + '18' }}
|
|
>
|
|
<Ionicons name={row.icon} size={16} color={row.iconColor} />
|
|
</View>
|
|
<View className="flex-1">
|
|
<Text className="text-neutral-800 text-sm" style={{ fontFamily: 'Nunito_600SemiBold' }}>{row.label}</Text>
|
|
{row.sublabel ? (
|
|
<Text className="text-neutral-400 text-xs mt-0.5" style={{ fontFamily: 'Nunito_400Regular' }}>{row.sublabel}</Text>
|
|
) : null}
|
|
</View>
|
|
{row.right ?? (
|
|
<Ionicons name="chevron-forward" size={14} color="#a3a3a3" />
|
|
)}
|
|
</Pressable>
|
|
))}
|
|
</Card>
|
|
|
|
{/* Preferences Section */}
|
|
<Text className="text-neutral-400 text-xs uppercase tracking-wider mb-2" style={{ fontFamily: 'Nunito_600SemiBold' }}>
|
|
{t('settings.prefs_section')}
|
|
</Text>
|
|
<Card className="mb-5 py-0 overflow-hidden">
|
|
{prefRows.map((row, i) => (
|
|
<View
|
|
key={row.label}
|
|
className={`flex-row items-center gap-3 px-4 py-3.5 ${
|
|
i < prefRows.length - 1 ? 'border-b border-neutral-100' : ''
|
|
}`}
|
|
>
|
|
<View
|
|
className="w-8 h-8 rounded-xl items-center justify-center"
|
|
style={{ backgroundColor: row.iconColor + '18' }}
|
|
>
|
|
<Ionicons name={row.icon} size={16} color={row.iconColor} />
|
|
</View>
|
|
<View className="flex-1">
|
|
<Text className="text-neutral-800 text-sm" style={{ fontFamily: 'Nunito_600SemiBold' }}>{row.label}</Text>
|
|
{row.sublabel ? (
|
|
<Text className="text-neutral-400 text-xs mt-0.5" style={{ fontFamily: 'Nunito_400Regular' }}>{row.sublabel}</Text>
|
|
) : null}
|
|
</View>
|
|
{row.right ?? (
|
|
<Pressable onPress={row.onPress}>
|
|
<Ionicons name="chevron-forward" size={14} color="#a3a3a3" />
|
|
</Pressable>
|
|
)}
|
|
</View>
|
|
))}
|
|
</Card>
|
|
|
|
{/* Danger Zone */}
|
|
<Text className="text-neutral-400 text-xs uppercase tracking-wider mb-2" style={{ fontFamily: 'Nunito_600SemiBold' }}>
|
|
{t('settings.danger_section')}
|
|
</Text>
|
|
<Card className="mb-3">
|
|
<Button variant="danger" onPress={() => {}} className="mb-2">
|
|
{t('settings.delete_account')}
|
|
</Button>
|
|
<Text className="text-neutral-400 text-xs text-center" style={{ fontFamily: 'Nunito_400Regular' }}>
|
|
{t('settings.delete_desc')}
|
|
</Text>
|
|
</Card>
|
|
|
|
<Button variant="secondary" onPress={handleSignOut}>
|
|
{t('settings.sign_out')}
|
|
</Button>
|
|
</ScrollView>
|
|
</SafeAreaView>
|
|
);
|
|
}
|