mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-08-25 13:49:40 +00:00
150 lines
4.2 KiB
TypeScript
150 lines
4.2 KiB
TypeScript
import { Alert, Box, Button, Container, Paper, TextField, Typography } from '@mui/material';
|
|
import React, { useState } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { useAuth } from '../../contexts/AuthContext';
|
|
import { GrantType } from '../../enums';
|
|
import { AppleLogin } from './AppleLogin';
|
|
import { GoogleLogin } from './GoogleLogin';
|
|
export const LoginForm = () => {
|
|
const { login } = useAuth();
|
|
const navigate = useNavigate();
|
|
const [formData, setFormData] = useState({
|
|
email: '',
|
|
password: '',
|
|
});
|
|
const [error, setError] = useState('');
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setError('');
|
|
setLoading(true);
|
|
|
|
try {
|
|
await login({ email: formData.email, password: formData.password, grantType: GrantType.PASSWORD });
|
|
navigate('/dashboard');
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : 'Login failed. Please check your credentials.');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const { name, value } = e.target;
|
|
setFormData((prev) => ({
|
|
...prev,
|
|
[name]: value,
|
|
}));
|
|
};
|
|
return (
|
|
<Box
|
|
sx={{
|
|
minHeight: '100vh',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
backgroundColor: 'background.default',
|
|
}}
|
|
>
|
|
<Container maxWidth="sm" sx={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
|
|
<Box sx={{ mb: 4, textAlign: 'center' }}>
|
|
<Typography variant="h3" component="h1" gutterBottom sx={{ fontWeight: 700, color: 'primary.main' }}>
|
|
Zod Alkhair | API TEST
|
|
</Typography>
|
|
<Typography variant="h6" sx={{ color: 'text.secondary', mb: 4 }}>
|
|
login to your account.
|
|
</Typography>
|
|
</Box>
|
|
|
|
<Paper
|
|
elevation={0}
|
|
sx={{
|
|
p: 4,
|
|
borderRadius: 3,
|
|
border: '1px solid',
|
|
borderColor: 'divider',
|
|
backgroundColor: 'background.paper',
|
|
}}
|
|
>
|
|
{error && (
|
|
<Alert severity="error" sx={{ mb: 3 }}>
|
|
{error}
|
|
</Alert>
|
|
)}
|
|
|
|
<Box component="form" onSubmit={handleSubmit}>
|
|
<TextField
|
|
fullWidth
|
|
margin="normal"
|
|
label="Email"
|
|
name="email"
|
|
type="email"
|
|
value={formData.email}
|
|
onChange={handleInputChange}
|
|
required
|
|
autoFocus
|
|
sx={{
|
|
'& .MuiOutlinedInput-root': {
|
|
borderRadius: 2,
|
|
},
|
|
}}
|
|
/>
|
|
|
|
<TextField
|
|
fullWidth
|
|
margin="normal"
|
|
label="Password"
|
|
name="password"
|
|
type="password"
|
|
value={formData.password}
|
|
onChange={handleInputChange}
|
|
required
|
|
sx={{
|
|
'& .MuiOutlinedInput-root': {
|
|
borderRadius: 2,
|
|
},
|
|
}}
|
|
/>
|
|
|
|
<Button
|
|
type="submit"
|
|
fullWidth
|
|
variant="contained"
|
|
size="large"
|
|
sx={{
|
|
mt: 3,
|
|
mb: 2,
|
|
height: 48,
|
|
borderRadius: 2,
|
|
textTransform: 'none',
|
|
fontSize: '1rem',
|
|
}}
|
|
disabled={loading}
|
|
>
|
|
{loading ? 'Signing in...' : 'Sign in'}
|
|
</Button>
|
|
|
|
<Button
|
|
fullWidth
|
|
variant="text"
|
|
sx={{
|
|
textTransform: 'none',
|
|
fontSize: '1rem',
|
|
color: 'text.secondary',
|
|
'&:hover': {
|
|
color: 'primary.main',
|
|
},
|
|
}}
|
|
onClick={() => navigate('/register')}
|
|
>
|
|
signup
|
|
</Button>
|
|
<AppleLogin setError={setError} setLoading={setLoading} />
|
|
<GoogleLogin setError={setError} setLoading={setLoading} />
|
|
</Box>
|
|
</Paper>
|
|
</Container>
|
|
</Box>
|
|
);
|
|
};
|