* Extended functionalities
* Added different UIs
This commit is contained in:
154
meal-plan-frontend-mobile/app/(main)/(tabs)/settings.tsx
Normal file
154
meal-plan-frontend-mobile/app/(main)/(tabs)/settings.tsx
Normal file
@@ -0,0 +1,154 @@
|
||||
import { router } from 'expo-router';
|
||||
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button } from '@/src/components/Button';
|
||||
import { Screen } from '@/src/components/Screen';
|
||||
import { useAuth } from '@/src/context/AuthContext';
|
||||
import { useAppearance } from '@/src/context/AppearanceContext';
|
||||
import { APPEARANCE_OPTIONS } from '@/src/theme/appearance';
|
||||
import { setAppLanguage } from '@/src/i18n';
|
||||
|
||||
export default function SettingsScreen() {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { user, logout } = useAuth();
|
||||
const { colors, appearanceId, setAppearance } = useAppearance();
|
||||
|
||||
return (
|
||||
<Screen title={t('settings.title')}>
|
||||
<ScrollView contentContainerStyle={styles.scroll}>
|
||||
<Text style={[styles.section, { color: colors.text }]}>{t('settings.account')}</Text>
|
||||
<View style={[styles.card, { backgroundColor: colors.surface, borderColor: colors.border }]}>
|
||||
<Text style={[styles.label, { color: colors.textMuted }]}>{t('auth.email')}</Text>
|
||||
<Text style={[styles.value, { color: colors.text }]}>{user?.email ?? '—'}</Text>
|
||||
{user?.userName ? (
|
||||
<>
|
||||
<Text style={[styles.label, { color: colors.textMuted, marginTop: 8 }]}>
|
||||
{t('auth.displayName')}
|
||||
</Text>
|
||||
<Text style={[styles.value, { color: colors.text }]}>{user.userName}</Text>
|
||||
</>
|
||||
) : null}
|
||||
</View>
|
||||
|
||||
<Text style={[styles.section, { color: colors.text }]}>{t('settings.preferences')}</Text>
|
||||
<Text style={[styles.subsection, { color: colors.text }]}>{t('language.label')}</Text>
|
||||
<View style={styles.row}>
|
||||
{(['en', 'pl'] as const).map((code) => {
|
||||
const selected = i18n.language.startsWith(code);
|
||||
return (
|
||||
<Pressable
|
||||
key={code}
|
||||
onPress={() => setAppLanguage(code)}
|
||||
style={[
|
||||
styles.chip,
|
||||
{
|
||||
backgroundColor: selected ? colors.brand : colors.surface,
|
||||
borderColor: selected ? colors.brand : colors.border,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Text style={{ color: selected ? '#fff' : colors.text }}>
|
||||
{t(`language.${code}`)}
|
||||
</Text>
|
||||
</Pressable>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
|
||||
<Text style={[styles.subsection, { color: colors.text }]}>{t('appearance.label')}</Text>
|
||||
{APPEARANCE_OPTIONS.map((option) => {
|
||||
const selected = appearanceId === option.id;
|
||||
return (
|
||||
<Pressable
|
||||
key={option.id}
|
||||
onPress={() => setAppearance(option.id)}
|
||||
style={[
|
||||
styles.appearanceRow,
|
||||
{
|
||||
backgroundColor: colors.surface,
|
||||
borderColor: selected ? colors.brand : colors.border,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<View style={[styles.swatch, { backgroundColor: option.swatch }]} />
|
||||
<View style={styles.appearanceText}>
|
||||
<Text style={[styles.appearanceTitle, { color: colors.text }]}>
|
||||
{t(option.labelKey)}
|
||||
</Text>
|
||||
<Text style={{ color: colors.textMuted }}>{t(option.descriptionKey)}</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
);
|
||||
})}
|
||||
|
||||
<Button
|
||||
title={t('nav.logout')}
|
||||
variant="danger"
|
||||
onPress={async () => {
|
||||
await logout();
|
||||
router.replace('/(auth)/login');
|
||||
}}
|
||||
/>
|
||||
</ScrollView>
|
||||
</Screen>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
scroll: {
|
||||
gap: 12,
|
||||
paddingBottom: 32,
|
||||
},
|
||||
section: {
|
||||
fontSize: 18,
|
||||
fontWeight: '700',
|
||||
marginTop: 4,
|
||||
},
|
||||
subsection: {
|
||||
fontSize: 15,
|
||||
fontWeight: '600',
|
||||
},
|
||||
card: {
|
||||
borderWidth: 1,
|
||||
borderRadius: 14,
|
||||
padding: 14,
|
||||
},
|
||||
label: {
|
||||
fontSize: 13,
|
||||
},
|
||||
value: {
|
||||
fontSize: 16,
|
||||
fontWeight: '500',
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
gap: 10,
|
||||
},
|
||||
chip: {
|
||||
borderWidth: 1,
|
||||
borderRadius: 999,
|
||||
paddingHorizontal: 16,
|
||||
paddingVertical: 10,
|
||||
},
|
||||
appearanceRow: {
|
||||
borderWidth: 1,
|
||||
borderRadius: 14,
|
||||
padding: 12,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 12,
|
||||
},
|
||||
swatch: {
|
||||
width: 28,
|
||||
height: 28,
|
||||
borderRadius: 14,
|
||||
},
|
||||
appearanceText: {
|
||||
flex: 1,
|
||||
gap: 2,
|
||||
},
|
||||
appearanceTitle: {
|
||||
fontWeight: '600',
|
||||
fontSize: 15,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user