Files
DeineDorfApp-Admin-Panel/src/pages/Auth/RegisterPage.jsx

161 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from 'react';
import { useNavigate, Link as RouterLink } from 'react-router-dom';
import {
Box, Card, CardContent, TextField, Button, Typography,
Alert, CircularProgress, Link, Divider, FormControlLabel, Checkbox
} from '@mui/material';
import PersonAddOutlinedIcon from '@mui/icons-material/PersonAddOutlined';
import axiosInstance from '../../api/axiosInstance.js';
export default function RegisterPage() {
const navigate = useNavigate();
const [form, setForm] = useState({ email: '', nickname: '', password: '', confirmPassword: '' });
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const [accepted, setAccepted] = useState(false);
const handleChange = (e) => setForm((prev) => ({ ...prev, [e.target.name]: e.target.value }));
const handleSubmit = async (e) => {
e.preventDefault();
setError('');
if (form.password !== form.confirmPassword) {
setError('Passwörter stimmen nicht überein.');
return;
}
setLoading(true);
try {
await axiosInstance.post('/auth/register', {
email: form.email,
nickname: form.nickname,
password: form.password,
});
navigate('/login', { state: { registered: true } });
} catch (err) {
setError(err.response?.data?.message ?? 'Registrierung fehlgeschlagen');
} finally {
setLoading(false);
}
};
return (
<Box
sx={{
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
bgcolor: 'grey.50',
}}
>
<Card sx={{ width: 400, p: 1 }}>
<CardContent>
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', mb: 3 }}>
<Box sx={{
width: 48, height: 48, borderRadius: '50%', bgcolor: 'primary.main',
display: 'flex', alignItems: 'center', justifyContent: 'center', mb: 2,
}}>
<PersonAddOutlinedIcon sx={{ color: 'white' }} />
</Box>
<Typography variant="h5" fontWeight={600}>Account erstellen</Typography>
<Typography variant="body2" color="text.secondary" mt={0.5}>
Neuen Admin-Account registrieren
</Typography>
</Box>
{error && <Alert severity="error" sx={{ mb: 2 }}>{error}</Alert>}
<Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<TextField
label="E-Mail"
name="email"
type="email"
value={form.email}
onChange={handleChange}
required
autoFocus
fullWidth
/>
<TextField
label="Nickname"
name="nickname"
value={form.nickname}
onChange={handleChange}
required
fullWidth
inputProps={{ minLength: 3, maxLength: 30 }}
helperText="330 Zeichen"
/>
<TextField
label="Passwort"
name="password"
type="password"
value={form.password}
onChange={handleChange}
required
fullWidth
inputProps={{ minLength: 8 }}
helperText="Mindestens 8 Zeichen"
/>
<TextField
label="Passwort bestätigen"
name="confirmPassword"
type="password"
value={form.confirmPassword}
onChange={handleChange}
required
fullWidth
error={form.confirmPassword.length > 0 && form.password !== form.confirmPassword}
helperText={
form.confirmPassword.length > 0 && form.password !== form.confirmPassword
? 'Passwörter stimmen nicht überein'
: ''
}
/>
<FormControlLabel
control={
<Checkbox
checked={accepted}
onChange={(e) => setAccepted(e.target.checked)}
size="small"
/>
}
label={
<Typography variant="body2">
Ich habe die{' '}
<Link component={RouterLink} to="/datenschutz" underline="hover" target="_blank">
Datenschutzerklärung
</Link>
{' '}gelesen und stimme zu.
</Typography>
}
/>
<Button
type="submit"
variant="contained"
fullWidth
size="large"
disabled={loading || !accepted}
sx={{ mt: 1 }}
>
{loading ? <CircularProgress size={24} color="inherit" /> : 'Registrieren'}
</Button>
</Box>
<Divider sx={{ my: 2.5 }} />
<Typography variant="body2" color="text.secondary" textAlign="center">
Bereits ein Account?{' '}
<Link component={RouterLink} to="/login" underline="hover">
Zum Login
</Link>
</Typography>
</CardContent>
</Card>
</Box>
);
}