Files
haptika/mobile/app/account.tsx
2026-09-09 10:12:49 +02:00

21 lines
4.7 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React,{useState} from 'react';
import {Alert,ActivityIndicator,Pressable,ScrollView,Text,TextInput,View} from 'react-native';
import {useRouter} from 'expo-router';
import {SafeAreaView} from 'react-native-safe-area-context';
import {createUserWithEmailAndPassword,signInWithEmailAndPassword,sendPasswordResetEmail,signOut} from '@react-native-firebase/auth';
import {auth} from '../src/firebase/client';
import {useAuth} from '../src/firebase/auth-state';
import {useAppState} from '../src/state/app-state';
import {theme} from '../src/design/theme';
export default function AccountScreen(){
const router=useRouter();const {user}=useAuth();const {syncStatus,syncError,retry}=useAppState();
const [email,setEmail]=useState(''),[password,setPassword]=useState(''),[register,setRegister]=useState(false),[busy,setBusy]=useState(false),[error,setError]=useState<string|null>(null);
async function submit(){setBusy(true);setError(null);try{if(register)await createUserWithEmailAndPassword(auth,email.trim(),password);else await signInWithEmailAndPassword(auth,email.trim(),password);setPassword('');}catch(e){const code=(e as {code?:string}).code;setError(code==='auth/network-request-failed'?'Connexion indisponible. Réessaie lorsque le réseau est disponible.':code==='auth/weak-password'?'Choisis un mot de passe d’au moins 6 caractères.':code==='auth/email-already-in-use'?'Un compte utilise déjà cette adresse.':'Connexion impossible. Vérifie ton adresse et ton mot de passe.');}finally{setBusy(false);}}
const button=(title:string,action:()=>void)=> <Pressable accessibilityRole="button" disabled={busy} onPress={action} style={{backgroundColor:theme.accent,borderRadius:28,padding:16,marginTop:16}}><Text style={{color:'#06101d',fontSize:16,textAlign:'center',fontWeight:'600'}}>{title}</Text></Pressable>;
return <SafeAreaView style={{flex:1,backgroundColor:theme.background}}><ScrollView keyboardShouldPersistTaps="handled" contentContainerStyle={{padding:24,gap:18}}><Pressable accessibilityRole="button" onPress={()=>router.canGoBack()?router.back():router.replace('/')}><Text style={{color:theme.accent}}>Retour</Text></Pressable><Text style={{fontSize:28,color:theme.text,fontWeight:'600'}}>Mon compte</Text>
{user?<><Text selectable style={{color:theme.text}}>{user.email}</Text><Text accessibilityLiveRegion="polite" style={{color:theme.muted}}>{syncStatus==='synced'?'Profil synchronisé':syncStatus==='pending'?'Modifications en attente':syncStatus==='loading'?'Chargement…':'Synchronisation indisponible'}</Text>{syncError&&<Text style={{color:'#ffb4ab'}}>{syncError}</Text>}{syncStatus==='error'&&button('Réessayer',retry)}{button('Se déconnecter',()=>{if(syncStatus==='pending'||syncStatus==='error'){Alert.alert('Modifications en attente','Elles resteront sur cet appareil, liées à ce compte.',[{text:'Annuler',style:'cancel'},{text:'Se déconnecter',onPress:()=>void signOut(auth).catch(()=>setError('Déconnexion impossible.'))}]);}else void signOut(auth).catch(()=>setError('Déconnexion impossible.'));})}</>:<><Text style={{color:theme.muted}}>Connecte-toi pour retrouver ton profil et tes préférences. Les données du mode local restent sur cet appareil.</Text><TextInput accessibilityLabel="Adresse e-mail" placeholder="Adresse e-mail" placeholderTextColor={theme.muted} autoCapitalize="none" autoCorrect={false} keyboardType="email-address" textContentType="emailAddress" value={email} onChangeText={setEmail} style={{color:theme.text,borderWidth:1,borderColor:theme.muted,borderRadius:14,padding:16}}/><TextInput accessibilityLabel="Mot de passe" placeholder="Mot de passe" placeholderTextColor={theme.muted} secureTextEntry textContentType={register?'newPassword':'password'} value={password} onChangeText={setPassword} style={{color:theme.text,borderWidth:1,borderColor:theme.muted,borderRadius:14,padding:16}}/>{button(register?'Créer mon compte':'Se connecter',()=>void submit())}<Pressable disabled={busy} onPress={()=>{setRegister(!register);setError(null);}}><Text style={{color:theme.accent}}>{register?'J’ai déjà un compte':'Créer un compte'}</Text></Pressable><Pressable disabled={busy} onPress={()=>{if(!email.trim()){setError('Renseigne ton adresse e-mail.');return;}setBusy(true);void sendPasswordResetEmail(auth,email.trim()).then(()=>Alert.alert('Demande envoyée','Si un compte correspond à cette adresse, tu recevras un lien de réinitialisation.')).catch(()=>setError('Impossible d’envoyer la demande. Vérifie ton adresse et réessaie.')).finally(()=>setBusy(false));}}><Text style={{color:theme.accent}}>Mot de passe oublié</Text></Pressable></>}
{busy&&<ActivityIndicator color={theme.accent}/>}{error&&<Text accessibilityRole="alert" style={{color:'#ffb4ab'}}>{error}</Text>}
</ScrollView></SafeAreaView>;
}