expo-starter/app/(tabs)/settings.tsx

222 lines
5.3 KiB
TypeScript

import { MaterialCommunityIcons } from '@expo/vector-icons';
import { Redirect, router } from 'expo-router';
import { useState } from 'react';
import {
ActivityIndicator,
Alert,
Pressable,
StyleSheet,
Text,
View,
} from 'react-native';
import { Avatar } from '@/components/common/Avatar';
import { Catamaran, FunnelSans } from '@/constants/fonts';
import { Palette } from '@/constants/palette';
import { Radius, Spacing } from '@/constants/styles';
import { useAuth } from '@/providers/AuthProvider';
import { sendTestPushNotification } from '@/services/notifications';
function SettingsRow({
label,
description,
onPress,
}: {
label: string;
description: string;
onPress: () => void;
}) {
return (
<Pressable onPress={onPress} style={styles.row}>
<View style={styles.rowContent}>
<Text style={styles.rowLabel}>{label}</Text>
<Text style={styles.rowDescription}>{description}</Text>
</View>
<MaterialCommunityIcons
color={Palette.gray}
name="chevron-right"
size={24}
/>
</Pressable>
);
}
export default function SettingsScreen() {
const { initializing, user } = useAuth();
const [sendingNotification, setSendingNotification] = useState(false);
if (initializing) {
return (
<View style={styles.centered}>
<ActivityIndicator color={Palette.black} />
</View>
);
}
if (!user) {
return <Redirect href="/login" />;
}
const registeredPushTokens = user.expoPushTokens?.length ?? 0;
async function handleSendTestNotification() {
try {
setSendingNotification(true);
await sendTestPushNotification();
Alert.alert(
'Notification envoyee',
'Une notification push de test a ete demandee.'
);
} catch (error) {
const message =
error instanceof Error
? error.message
: "Impossible d'envoyer la notification.";
Alert.alert('Erreur', message);
} finally {
setSendingNotification(false);
}
}
return (
<View style={styles.container}>
<View style={styles.header}>
<Text style={styles.title}>Settings</Text>
<Text style={styles.subtitle}>Gere ton compte et ton profil.</Text>
</View>
<View style={styles.previewCard}>
<Avatar
name={user.username}
size="md"
uri={user.profilePicture}
/>
<View style={styles.previewContent}>
<Text style={styles.previewTitle}>{user.username}</Text>
<Text style={styles.previewSubtitle}>{user.email}</Text>
</View>
</View>
<View style={styles.section}>
<Text style={styles.sectionTitle}>Account</Text>
<View style={styles.sectionCard}>
<SettingsRow
description="Photo, pseudo, email et dates de creation."
label="Profile"
onPress={() => router.push('/profile')}
/>
</View>
</View>
<View style={styles.section}>
<Text style={styles.sectionTitle}>Notifications</Text>
<View style={styles.sectionCard}>
<SettingsRow
description={
registeredPushTokens > 0
? `${registeredPushTokens} appareil(x) enregistre(s).`
: 'Aucun appareil enregistre pour les notifications.'
}
label="Etat des notifications"
onPress={() => undefined}
/>
<SettingsRow
description={
sendingNotification
? 'Envoi en cours...'
: 'Envoyer une notification push de test.'
}
label="Tester une notification"
onPress={handleSendTestNotification}
/>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
centered: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: Palette.cream,
},
container: {
flex: 1,
paddingHorizontal: Spacing.lg,
paddingTop: Spacing.xl,
gap: Spacing.lg,
backgroundColor: Palette.cream,
},
header: {
gap: Spacing.xs,
},
title: {
...Catamaran.extraBold34,
color: Palette.black,
},
subtitle: {
...FunnelSans.regular16,
color: Palette.gray,
},
previewCard: {
flexDirection: 'row',
alignItems: 'center',
gap: Spacing.md,
padding: Spacing.md,
borderWidth: 1,
borderColor: Palette.cream,
borderRadius: Radius.md,
backgroundColor: Palette.white,
},
previewContent: {
flex: 1,
gap: Spacing.xs,
},
previewTitle: {
...FunnelSans.medium16,
color: Palette.black,
},
previewSubtitle: {
...FunnelSans.medium14,
color: Palette.gray,
},
section: {
gap: Spacing.sm,
},
sectionTitle: {
...FunnelSans.medium12,
color: Palette.gray,
textTransform: 'uppercase',
},
sectionCard: {
borderWidth: 1,
borderColor: Palette.cream,
borderRadius: Radius.sm,
backgroundColor: Palette.white,
overflow: 'hidden',
},
row: {
flexDirection: 'row',
alignItems: 'center',
gap: Spacing.md,
paddingHorizontal: Spacing.md,
paddingVertical: Spacing.sm,
},
rowContent: {
flex: 1,
gap: Spacing.xs,
},
rowLabel: {
...FunnelSans.medium16,
color: Palette.black,
},
rowDescription: {
...FunnelSans.regular16,
color: Palette.gray,
},
});