import React, { useState, useEffect } from 'react'; import { View, Text, TextInput, TouchableOpacity, StyleSheet, KeyboardAvoidingView, Platform, Alert, Image, } from 'react-native'; import { useRouter } from 'expo-router'; import { Ionicons } from '@expo/vector-icons'; import { useAuthStore } from '../../store/authStore'; import { useThemeContext } from '../../components/ThemeProvider'; import { register } from '../../services/auth'; import { spacing, borderRadius, shadows } from '../../constants/theme'; import { isBiometricsAvailable, authenticateWithBiometrics, saveBiometricCredentials, getBiometricUsername, } from '../../services/biometrics'; type Tab = 'login' | 'register'; export default function LoginScreen() { const router = useRouter(); const { login } = useAuthStore(); const { colors } = useThemeContext(); const [tab, setTab] = useState('login'); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [isLoading, setIsLoading] = useState(false); const [biometricsAvailable, setBiometricsAvailable] = useState(false); const [biometricUsername, setBiometricUsername] = useState(null); const isRegister = tab === 'register'; useEffect(() => { checkBiometrics(); }, []); useEffect(() => { setUsername(''); setPassword(''); setConfirmPassword(''); }, [tab]); const checkBiometrics = async () => { try { const available = await isBiometricsAvailable(); setBiometricsAvailable(available); if (available) { const savedUsername = await getBiometricUsername(); setBiometricUsername(savedUsername); } } catch (error) { console.error('Error checking biometrics:', error); } }; const handleSubmit = async () => { if (!username.trim() || !password) { Alert.alert('Error', 'Por favor completa todos los campos'); return; } if (isRegister) { if (password.length < 8) { Alert.alert('Error', 'La contraseña debe tener al menos 8 caracteres'); return; } if (password !== confirmPassword) { Alert.alert('Error', 'Las contraseñas no coinciden'); return; } } setIsLoading(true); try { if (isRegister) { await register(username.trim(), password); Alert.alert('Éxito', 'Cuenta creada correctamente', [ { text: 'OK', onPress: () => setTab('login') }, ]); } else { await login(username.trim(), password); if (biometricsAvailable) { await saveBiometricCredentials(username.trim()); } router.replace('/(tabs)'); } } catch (error) { Alert.alert( 'Error', isRegister ? 'No se pudo crear la cuenta' : 'Credenciales incorrectas' ); } finally { setIsLoading(false); } }; const handleBiometricLogin = async () => { if (!biometricUsername) { Alert.alert('Error', 'No hay credenciales biométricas guardadas'); return; } setIsLoading(true); try { const authenticated = await authenticateWithBiometrics(); if (authenticated) { await login(biometricUsername, ''); router.replace('/(tabs)'); } else { Alert.alert('Error', 'Autenticación biométrica fallida'); } } catch (error) { Alert.alert('Error', 'Error en la autenticación biométrica'); } finally { setIsLoading(false); } }; return ( {/* Logo */} FarmaClic {/* Tabs */} setTab('login')} disabled={isLoading} > Iniciar Sesión setTab('register')} disabled={isLoading} > Crear Cuenta {/* Card */} {/* Header */} {isRegister ? 'Crea tu cuenta' : 'Bienvenido de nuevo'} {isRegister ? 'Guarda tu dirección y recibe notificaciones cuando lleguen medicamentos.' : 'Inicia sesión para gestionar tu perfil y notificaciones.'} {/* Username */} {/* Password */} {/* Confirm password (register only) */} {isRegister && ( )} {/* Hints (register only) */} {isRegister && ( 3-32 caracteres para el usuario Mínimo 8 caracteres para la contraseña )} {/* Submit button */} {isLoading ? ( ) : ( {isRegister ? 'Crear Cuenta' : 'Iniciar Sesión'} )} {/* Biometrics (login only) */} {!isRegister && biometricsAvailable && biometricUsername && ( Iniciar con biometría )} {/* Footer link */} setTab(isRegister ? 'login' : 'register')} > {isRegister ? '¿Ya tienes cuenta? Inicia sesión' : '¿No tienes cuenta? Regístrate'} ); } const styles = StyleSheet.create({ container: { flex: 1, }, content: { flex: 1, justifyContent: 'center', paddingHorizontal: spacing.lg, gap: spacing.lg, }, logoSection: { alignItems: 'center', gap: spacing.sm, }, logo: { width: 80, height: 80, }, brandName: { fontSize: 22, fontWeight: '700', letterSpacing: -0.3, }, tabBar: { flexDirection: 'row', borderRadius: borderRadius.lg, padding: 4, }, tab: { flex: 1, paddingVertical: spacing.sm + 2, borderRadius: borderRadius.md, alignItems: 'center', }, tabActive: { shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 2, }, tabText: { fontSize: 14, fontWeight: '500', }, tabTextActive: { fontWeight: '700', }, card: { borderRadius: borderRadius.xl, padding: spacing.lg, gap: spacing.sm, }, title: { fontSize: 22, fontWeight: '700', marginBottom: spacing.xs, }, subtitle: { fontSize: 14, lineHeight: 20, marginBottom: spacing.sm, }, inputWrapper: { flexDirection: 'row', alignItems: 'center', borderRadius: borderRadius.md, borderWidth: 1, paddingHorizontal: spacing.md, }, inputIcon: { marginRight: spacing.sm, }, input: { flex: 1, paddingVertical: spacing.md, fontSize: 16, }, hints: { gap: 2, marginTop: spacing.xs, }, hint: { fontSize: 12, lineHeight: 18, }, button: { borderRadius: borderRadius.md, padding: spacing.md, alignItems: 'center', marginTop: spacing.sm, flexDirection: 'row', justifyContent: 'center', }, buttonDisabled: { opacity: 0.6, }, buttonText: { fontSize: 16, fontWeight: '700', }, biometricButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', borderRadius: borderRadius.md, padding: spacing.md, marginTop: spacing.xs, borderWidth: 1, gap: spacing.sm, }, biometricText: { fontSize: 15, fontWeight: '600', }, linkButton: { alignItems: 'center', paddingVertical: spacing.sm, }, linkText: { fontSize: 14, fontWeight: '600', }, });