this repo has no description
1import { useState } from 'react';
2import { Link as RouterLink, Navigate } from 'react-router-dom';
3import Box from '@mui/material/Box';
4import Card from '@mui/material/Card';
5import CardContent from '@mui/material/CardContent';
6import TextField from '@mui/material/TextField';
7import Button from '@mui/material/Button';
8import Typography from '@mui/material/Typography';
9import Link from '@mui/material/Link';
10import Alert from '@mui/material/Alert';
11import CircularProgress from '@mui/material/CircularProgress';
12import { useAuth } from '../hooks/useAuth';
13import { Rambi } from '../components/mascot/Rambi';
14
15export function LoginPage() {
16 const { login, user, loading: authLoading } = useAuth();
17 const [email, setEmail] = useState('');
18 const [password, setPassword] = useState('');
19 const [error, setError] = useState('');
20 const [loading, setLoading] = useState(false);
21
22 if (authLoading) {
23 return (
24 <Box
25 sx={{
26 display: 'flex',
27 justifyContent: 'center',
28 alignItems: 'center',
29 minHeight: '100vh',
30 }}
31 >
32 <CircularProgress color="primary" />
33 </Box>
34 );
35 }
36
37 if (user) {
38 return <Navigate to="/home" replace />;
39 }
40
41 async function handleSubmit(e: React.FormEvent) {
42 e.preventDefault();
43 setError('');
44 setLoading(true);
45
46 try {
47 await login(email, password);
48 } catch (err) {
49 setError(err instanceof Error ? err.message : 'Login failed');
50 } finally {
51 setLoading(false);
52 }
53 }
54
55 return (
56 <Box
57 sx={{
58 display: 'flex',
59 flexDirection: 'column',
60 alignItems: 'center',
61 justifyContent: 'center',
62 minHeight: '100vh',
63 px: 2,
64 }}
65 >
66 {/* Rambi peeking over the card */}
67 <Box sx={{ mb: -3, zIndex: 1 }}>
68 <Rambi mood="peek" size={100} />
69 </Box>
70
71 <Card sx={{ width: '100%', maxWidth: 400, position: 'relative' }}>
72 <CardContent sx={{ p: 4 }}>
73 <Typography
74 variant="h4"
75 sx={{ textAlign: 'center', mb: 1, color: '#E8453C' }}
76 >
77 Ayos
78 </Typography>
79 <Typography
80 variant="body2"
81 color="text.secondary"
82 sx={{ textAlign: 'center', mb: 3 }}
83 >
84 Learn Tagalog the fun way
85 </Typography>
86
87 {error && (
88 <Alert severity="error" sx={{ mb: 2 }}>
89 {error}
90 </Alert>
91 )}
92
93 <Box component="form" onSubmit={handleSubmit}>
94 <TextField
95 fullWidth
96 label="Email"
97 type="email"
98 value={email}
99 onChange={(e) => setEmail(e.target.value)}
100 required
101 sx={{ mb: 2 }}
102 />
103 <TextField
104 fullWidth
105 label="Password"
106 type="password"
107 value={password}
108 onChange={(e) => setPassword(e.target.value)}
109 required
110 sx={{ mb: 3 }}
111 />
112 <Button
113 fullWidth
114 type="submit"
115 variant="contained"
116 color="primary"
117 disabled={loading}
118 sx={{ mb: 2 }}
119 >
120 {loading ? <CircularProgress size={24} color="inherit" /> : 'Log In'}
121 </Button>
122 </Box>
123
124 <Typography
125 variant="body2"
126 color="text.secondary"
127 sx={{ textAlign: 'center' }}
128 >
129 Don't have an account?{' '}
130 <Link component={RouterLink} to="/register" color="secondary">
131 Sign up
132 </Link>
133 </Typography>
134 </CardContent>
135 </Card>
136 </Box>
137 );
138}