diff --git a/mobile/app/(auth)/login.tsx b/mobile/app/(auth)/login.tsx new file mode 100644 index 0000000..d620f3a --- /dev/null +++ b/mobile/app/(auth)/login.tsx @@ -0,0 +1,119 @@ +import { View, Text, Button, StyleSheet, TextInput, ActivityIndicator } from 'react-native'; +import { Link } from 'expo-router'; +import { Formik } from 'formik'; +import * as Yup from 'yup'; +import { useAuth } from '../../context/AuthContext'; +import authApi from '../../services/authApi'; +import { useState } from 'react'; + +const LoginSchema = Yup.object().shape({ + email: Yup.string().email('Invalid email').required('Email is required'), + password: Yup.string().required('Password is required'), +}); + +export default function LoginScreen() { + const { login } = useAuth(); + const [error, setError] = useState(null); + + const handleLogin = async (values: any) => { + setError(null); + try { + const response = await authApi.login({ email: values.email, password: values.password }); + if (response.data && response.data.token) { + await login(response.data.token); + } else { + setError('Login failed: No token received.'); + } + } catch (err: any) { + const errorMessage = err.response?.data?.message || 'Invalid credentials or server error.'; + setError(errorMessage); + } + }; + + return ( + + Welcome Back! + + + {({ handleChange, handleBlur, handleSubmit, values, errors, touched, isSubmitting }) => ( + + + {errors.email && touched.email ? {errors.email} : null} + + + {errors.password && touched.password ? {errors.password} : null} + + {error && {error}} + + {isSubmitting ? ( + + ) : ( +