- Update package.json to Expo ~54.0.35, expo-router ~6.0.24, RN 0.81.5 - Remove NativeWind/Tailwind dependencies - Fix babel.config.js: presets babel-preset-expo only - Rewrite all screens with StyleSheet.create (no className) - Add lucide-react-native + react-native-svg - Export design tokens C from _layout.tsx for shared usage - Install node_modules (702 packages) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
82 lines
3.2 KiB
TypeScript
82 lines
3.2 KiB
TypeScript
import { useState } from 'react'
|
|
import {
|
|
View, Text, TextInput, TouchableOpacity,
|
|
KeyboardAvoidingView, Platform, ActivityIndicator,
|
|
Alert, StyleSheet,
|
|
} from 'react-native'
|
|
import { useAuthStore } from '@/lib/store'
|
|
import { C } from '../_layout'
|
|
|
|
export default function LoginScreen() {
|
|
const [email, setEmail] = useState('')
|
|
const [password, setPassword] = useState('')
|
|
const [loading, setLoading] = useState(false)
|
|
const login = useAuthStore((s) => s.login)
|
|
|
|
const handleLogin = async () => {
|
|
if (!email.trim() || !password.trim()) return
|
|
setLoading(true)
|
|
try {
|
|
await login(email.trim().toLowerCase(), password)
|
|
} catch (e: any) {
|
|
Alert.alert('Connexion échouée', e.message)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'} style={s.container}>
|
|
<View style={s.inner}>
|
|
<View style={s.logoBlock}>
|
|
<Text style={s.logo}>Momento</Text>
|
|
<Text style={s.tagline}>Votre espace de connaissance</Text>
|
|
</View>
|
|
|
|
<View style={s.form}>
|
|
<Text style={s.label}>Email</Text>
|
|
<TextInput
|
|
value={email} onChangeText={setEmail}
|
|
placeholder="vous@exemple.com" autoCapitalize="none"
|
|
keyboardType="email-address" autoComplete="email"
|
|
style={s.input} placeholderTextColor={C.concrete}
|
|
/>
|
|
<Text style={[s.label, { marginTop: 16 }]}>Mot de passe</Text>
|
|
<TextInput
|
|
value={password} onChangeText={setPassword}
|
|
placeholder="••••••••" secureTextEntry
|
|
autoComplete="password" style={s.input}
|
|
placeholderTextColor={C.concrete} onSubmitEditing={handleLogin}
|
|
/>
|
|
<TouchableOpacity
|
|
onPress={handleLogin}
|
|
disabled={loading || !email || !password}
|
|
style={[s.btn, (loading || !email || !password) && s.btnDisabled]}
|
|
>
|
|
{loading
|
|
? <ActivityIndicator color={C.white} size="small" />
|
|
: <Text style={s.btnText}>Se connecter</Text>}
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
<Text style={s.footer}>memento-note.com</Text>
|
|
</View>
|
|
</KeyboardAvoidingView>
|
|
)
|
|
}
|
|
|
|
const s = StyleSheet.create({
|
|
container: { flex: 1, backgroundColor: C.paper },
|
|
inner: { flex: 1, justifyContent: 'center', paddingHorizontal: 32 },
|
|
logoBlock: { marginBottom: 48, alignItems: 'center' },
|
|
logo: { fontSize: 36, fontStyle: 'italic', color: C.ink, fontWeight: '600' },
|
|
tagline: { fontSize: 14, color: C.concrete, marginTop: 4 },
|
|
form: {},
|
|
label: { fontSize: 11, fontWeight: '700', letterSpacing: 1.5, textTransform: 'uppercase', color: C.concrete, marginBottom: 6 },
|
|
input: { borderWidth: 1, borderColor: C.border, borderRadius: 12, paddingHorizontal: 16, paddingVertical: 12, fontSize: 15, color: C.ink, backgroundColor: C.white },
|
|
btn: { marginTop: 24, backgroundColor: C.ink, borderRadius: 12, paddingVertical: 14, alignItems: 'center' },
|
|
btnDisabled: { opacity: 0.5 },
|
|
btnText: { color: C.white, fontWeight: '600', fontSize: 15 },
|
|
footer: { textAlign: 'center', fontSize: 12, color: C.concrete, marginTop: 32 },
|
|
})
|