import React, { useState, useCallback, useRef } from 'react'; import { View, Text, TextInput, TouchableOpacity, StyleSheet, KeyboardAvoidingView, Platform, ScrollView, ActivityIndicator, Linking, type TextInput as TextInputType, } from 'react-native'; import { useColorScheme } from 'react-native'; import { router } from 'expo-router'; import { Colors } from '../../constants/Colors'; import { useAuthStore } from '../../stores/authStore'; import { config } from '../../lib/config'; /** * Email validation regex */ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; /** * Login screen component * Handles user authentication with email and password */ export default function LoginScreen() { const colorScheme = useColorScheme() ?? 'dark'; const colors = Colors[colorScheme]; // Form state const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [emailError, setEmailError] = useState(null); const [passwordError, setPasswordError] = useState(null); // Refs for input focus const passwordInputRef = useRef(null); // Auth store const signIn = useAuthStore((state) => state.signIn); const isLoading = useAuthStore((state) => state.isLoading); const authError = useAuthStore((state) => state.error); const clearError = useAuthStore((state) => state.clearError); /** * Validate email format */ const validateEmail = useCallback((value: string): boolean => { if (!value.trim()) { setEmailError('Email is required'); return false; } if (!EMAIL_REGEX.test(value.trim())) { setEmailError('Please enter a valid email address'); return false; } setEmailError(null); return true; }, []); /** * Validate password */ const validatePassword = useCallback((value: string): boolean => { if (!value) { setPasswordError('Password is required'); return false; } if (value.length < 6) { setPasswordError('Password must be at least 6 characters'); return false; } setPasswordError(null); return true; }, []); /** * Handle email change */ const handleEmailChange = useCallback( (value: string) => { setEmail(value); if (emailError) { setEmailError(null); } if (authError) { clearError(); } }, [emailError, authError, clearError] ); /** * Handle password change */ const handlePasswordChange = useCallback( (value: string) => { setPassword(value); if (passwordError) { setPasswordError(null); } if (authError) { clearError(); } }, [passwordError, authError, clearError] ); /** * Handle login button press */ const handleLogin = useCallback(async () => { // Clear previous errors clearError(); // Validate inputs const isEmailValid = validateEmail(email); const isPasswordValid = validatePassword(password); if (!isEmailValid || !isPasswordValid) { return; } // Attempt sign in const success = await signIn(email, password); if (success) { // Navigate to main app router.replace('/(tabs)'); } }, [email, password, signIn, validateEmail, validatePassword, clearError]); /** * Handle forgot password link press */ const handleForgotPassword = useCallback(() => { Linking.openURL(config.forgotPasswordUrl); }, []); /** * Handle email submit (move focus to password) */ const handleEmailSubmit = useCallback(() => { passwordInputRef.current?.focus(); }, []); /** * Get combined error message */ const displayError = authError || emailError || passwordError; return ( Welcome to Makima Sign in to continue {/* Email Input */} Email {emailError && ( {emailError} )} {/* Password Input */} Password {passwordError && ( {passwordError} )} {/* Auth Error */} {authError && ( {authError} )} {/* Login Button */} {isLoading ? ( ) : ( Sign In )} {/* Forgot Password Link */} Forgot Password? {/* Footer */} By signing in, you agree to our{' '} Linking.openURL(config.termsOfServiceUrl)} > Terms of Service {' and '} Linking.openURL(config.privacyPolicyUrl)} > Privacy Policy ); } const styles = StyleSheet.create({ container: { flex: 1, }, scrollContent: { flexGrow: 1, justifyContent: 'center', paddingHorizontal: 24, paddingVertical: 40, }, headerContainer: { alignItems: 'center', marginBottom: 40, }, title: { fontSize: 28, fontWeight: 'bold', marginBottom: 8, }, subtitle: { fontSize: 16, }, formContainer: { width: '100%', }, inputContainer: { marginBottom: 20, }, label: { fontSize: 14, fontWeight: '600', marginBottom: 8, }, input: { height: 50, borderWidth: 1, borderRadius: 12, paddingHorizontal: 16, fontSize: 16, }, fieldError: { fontSize: 12, marginTop: 4, }, errorContainer: { padding: 12, borderRadius: 8, marginBottom: 20, }, errorText: { fontSize: 14, textAlign: 'center', }, button: { height: 50, borderRadius: 12, justifyContent: 'center', alignItems: 'center', marginTop: 8, }, buttonText: { fontSize: 16, fontWeight: '600', }, forgotPasswordContainer: { alignItems: 'center', marginTop: 20, }, forgotPasswordText: { fontSize: 14, }, footerContainer: { marginTop: 40, alignItems: 'center', }, footerText: { fontSize: 12, textAlign: 'center', lineHeight: 18, }, linkText: { textDecorationLine: 'underline', }, });