feat(mobile): refonte design DSFR complète + partie admin
- écrans auth/dashboard/journal/info/urgence/profil refondus sur le design system - AppBar institutionnel République Française sur tous les écrans - partie admin (utilisateurs, contenus, émotions) avec AdminGuard - entrée Espace administration dans le profil (admins uniquement) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { View, Text, StyleSheet, ScrollView, TouchableOpacity, Linking, Alert } from 'react-native';
|
||||
import { View, Text, StyleSheet, ScrollView, Linking, Alert } from 'react-native';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { Colors } from '@/lib/colors';
|
||||
import { FontSize, FontWeight, Radius, Spacing } from '@/lib/theme';
|
||||
import { AppBar, Button, Card } from '@/components/ui';
|
||||
|
||||
type Contact = {
|
||||
nom: string;
|
||||
@@ -65,61 +67,78 @@ export default function UrgenceScreen() {
|
||||
};
|
||||
|
||||
return (
|
||||
<ScrollView style={styles.container} contentContainerStyle={styles.content}>
|
||||
<View style={styles.header}>
|
||||
<View style={styles.iconBadge}>
|
||||
<Ionicons name="heart" size={20} color={Colors.error} />
|
||||
</View>
|
||||
<Text style={styles.headerTitle}>Vous n'êtes pas seul(e)</Text>
|
||||
<Text style={styles.headerSubtitle}>
|
||||
<View style={styles.screen}>
|
||||
<AppBar title="Urgence" subtitle="Vous n'êtes pas seul(e)" />
|
||||
<ScrollView style={styles.container} contentContainerStyle={styles.content}>
|
||||
<Text style={styles.intro}>
|
||||
Si vous ou un proche traversez une période difficile, ces services sont là pour vous écouter.
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{CONTACTS.map((c) => (
|
||||
<TouchableOpacity key={c.numero} style={styles.card} onPress={() => appeler(c.numero, c.nom)}>
|
||||
<View style={styles.cardIcon}>
|
||||
<Ionicons name="call" size={22} color={Colors.error} />
|
||||
</View>
|
||||
<View style={styles.cardContent}>
|
||||
<Text style={styles.cardName}>{c.nom}</Text>
|
||||
<Text style={styles.cardNumber}>{formatNumero(c.numero)}</Text>
|
||||
{CONTACTS.map((c) => (
|
||||
<Card key={c.numero} style={styles.card}>
|
||||
<View style={styles.cardHeader}>
|
||||
<View style={styles.cardIcon}>
|
||||
<Ionicons name="call" size={22} color={Colors.error} />
|
||||
</View>
|
||||
<View style={styles.cardHeaderText}>
|
||||
<Text style={styles.cardName}>{c.nom}</Text>
|
||||
<Text style={styles.cardNumber}>{formatNumero(c.numero)}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<Text style={styles.cardDescription}>{c.description}</Text>
|
||||
<Text style={styles.cardAvailability}>{c.disponibilite}</Text>
|
||||
</View>
|
||||
<Ionicons name="chevron-forward" size={18} color={Colors.gray[300]} />
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
<View style={styles.cardAvailabilityRow}>
|
||||
<Ionicons name="time-outline" size={14} color={Colors.gray[500]} />
|
||||
<Text style={styles.cardAvailability}>{c.disponibilite}</Text>
|
||||
</View>
|
||||
<Button
|
||||
title={`Appeler le ${formatNumero(c.numero)}`}
|
||||
variant="danger"
|
||||
icon="call"
|
||||
fullWidth
|
||||
onPress={() => appeler(c.numero, c.nom)}
|
||||
style={styles.cardButton}
|
||||
/>
|
||||
</Card>
|
||||
))}
|
||||
|
||||
<View style={styles.warning}>
|
||||
<Ionicons name="warning" size={18} color={Colors.error} />
|
||||
<Text style={styles.warningText}>
|
||||
En cas d'urgence vitale, appelez immédiatement le <Text style={styles.bold}>15</Text> (SAMU) ou le <Text style={styles.bold}>112</Text>.
|
||||
</Text>
|
||||
</View>
|
||||
</ScrollView>
|
||||
<Card style={styles.warning} padding={Spacing.lg}>
|
||||
<View style={styles.warningRow}>
|
||||
<Ionicons name="warning" size={20} color={Colors.error} />
|
||||
<Text style={styles.warningText}>
|
||||
En cas d'urgence vitale, appelez immédiatement le <Text style={styles.bold}>15</Text> (SAMU) ou le{' '}
|
||||
<Text style={styles.bold}>112</Text>.
|
||||
</Text>
|
||||
</View>
|
||||
</Card>
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: { flex: 1, backgroundColor: Colors.white },
|
||||
content: { padding: 16, paddingBottom: 32 },
|
||||
header: { marginBottom: 20, alignItems: 'flex-start' },
|
||||
iconBadge: { width: 40, height: 40, borderRadius: 4, backgroundColor: Colors.errorBg, justifyContent: 'center', alignItems: 'center', marginBottom: 12 },
|
||||
headerTitle: { fontSize: 22, fontWeight: '800', color: Colors.black, marginBottom: 6 },
|
||||
headerSubtitle: { fontSize: 14, color: Colors.gray[500], lineHeight: 20 },
|
||||
card: {
|
||||
flexDirection: 'row', alignItems: 'center', gap: 14, padding: 16,
|
||||
backgroundColor: Colors.white, borderRadius: 4, marginBottom: 10,
|
||||
borderWidth: 1, borderColor: Colors.gray[200],
|
||||
screen: { flex: 1, backgroundColor: Colors.gray[50] },
|
||||
container: { flex: 1 },
|
||||
content: { padding: Spacing.lg, paddingBottom: Spacing.xxl, gap: Spacing.md },
|
||||
intro: { fontSize: FontSize.sm, color: Colors.gray[500], lineHeight: 20, marginBottom: Spacing.xs },
|
||||
card: { padding: Spacing.lg, gap: Spacing.sm },
|
||||
cardHeader: { flexDirection: 'row', alignItems: 'center', gap: Spacing.md },
|
||||
cardIcon: {
|
||||
width: 44,
|
||||
height: 44,
|
||||
borderRadius: Radius.sm,
|
||||
backgroundColor: Colors.errorBg,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
cardIcon: { width: 44, height: 44, borderRadius: 4, backgroundColor: Colors.errorBg, justifyContent: 'center', alignItems: 'center' },
|
||||
cardContent: { flex: 1 },
|
||||
cardName: { fontSize: 14, fontWeight: '700', color: Colors.black, marginBottom: 2 },
|
||||
cardNumber: { fontSize: 20, fontWeight: '800', color: Colors.error, marginBottom: 6 },
|
||||
cardDescription: { fontSize: 12, color: Colors.gray[500], lineHeight: 17 },
|
||||
cardAvailability: { fontSize: 11, color: Colors.primary, marginTop: 4, fontWeight: '600' },
|
||||
warning: { marginTop: 8, padding: 14, borderRadius: 4, backgroundColor: Colors.errorBg, borderWidth: 1, borderColor: Colors.error, flexDirection: 'row', gap: 10, alignItems: 'flex-start' },
|
||||
warningText: { flex: 1, fontSize: 13, color: Colors.error, lineHeight: 19 },
|
||||
bold: { fontWeight: '800' },
|
||||
cardHeaderText: { flex: 1 },
|
||||
cardName: { fontSize: FontSize.md, fontWeight: FontWeight.bold, color: Colors.black, marginBottom: 2 },
|
||||
cardNumber: { fontSize: FontSize.xl, fontWeight: FontWeight.heavy, color: Colors.error },
|
||||
cardDescription: { fontSize: FontSize.xs, color: Colors.gray[600], lineHeight: 19 },
|
||||
cardAvailabilityRow: { flexDirection: 'row', alignItems: 'center', gap: Spacing.xs },
|
||||
cardAvailability: { fontSize: FontSize.tiny, color: Colors.gray[500], fontWeight: FontWeight.semibold },
|
||||
cardButton: { marginTop: Spacing.xs },
|
||||
warning: { backgroundColor: Colors.errorBg, borderColor: Colors.error },
|
||||
warningRow: { flexDirection: 'row', gap: Spacing.md, alignItems: 'flex-start' },
|
||||
warningText: { flex: 1, fontSize: FontSize.xs, color: Colors.error, lineHeight: 19 },
|
||||
bold: { fontWeight: FontWeight.heavy },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user