File size: 4,027 Bytes
b0c3c39 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
import React, { useState, useCallback } from 'react';
import axios, { handleApiError } from '../utils/axios';
import styles from './Auth.module.css';
interface AuthForm {
username: string;
email: string;
password: string;
}
interface AuthProps {
isLogin: boolean;
}
const Auth: React.FC<AuthProps> = ({ isLogin }) => {
const [form, setForm] = useState<AuthForm>({ username: '', email: '', password: '' });
const [error, setError] = useState<string>('');
const [isLoading, setIsLoading] = useState(false);
const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
setForm(prev => ({ ...prev, [e.target.name]: e.target.value }));
setError(''); // Clear error when user starts typing
}, []);
const validateForm = useCallback((): boolean => {
if (!form.username.trim()) {
setError('Username is required');
return false;
}
if (!form.password.trim()) {
setError('Password is required');
return false;
}
if (!isLogin && !form.email.trim()) {
setError('Email is required');
return false;
}
if (!isLogin && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email)) {
setError('Please enter a valid email address');
return false;
}
return true;
}, [form, isLogin]);
const handleSubmit = useCallback(async (e: React.FormEvent) => {
e.preventDefault();
setError('');
if (!validateForm()) {
return;
}
setIsLoading(true);
try {
if (isLogin) {
const formData = new FormData();
formData.append('username', form.username);
formData.append('password', form.password);
const res = await axios.post('/login', formData, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
const { access_token, refresh_token } = res.data;
localStorage.setItem('token', access_token);
localStorage.setItem('refreshToken', refresh_token);
window.location.href = '/editor';
} else {
await axios.post('/signup', form);
window.location.href = '/login';
}
} catch (error) {
setError(handleApiError(error));
} finally {
setIsLoading(false);
}
}, [form, isLogin, validateForm]);
return (
<div className={styles.authContainer}>
<form onSubmit={handleSubmit} className={styles.authForm}>
<h2>{isLogin ? 'Login' : 'Sign Up'}</h2>
<div className={styles.formGroup}>
<label htmlFor="username">Username</label>
<input
type="text"
id="username"
name="username"
value={form.username}
onChange={handleChange}
disabled={isLoading}
required
/>
</div>
{!isLogin && (
<div className={styles.formGroup}>
<label htmlFor="email">Email</label>
<input
type="email"
id="email"
name="email"
value={form.email}
onChange={handleChange}
disabled={isLoading}
required
/>
</div>
)}
<div className={styles.formGroup}>
<label htmlFor="password">Password</label>
<input
type="password"
id="password"
name="password"
value={form.password}
onChange={handleChange}
disabled={isLoading}
required
/>
</div>
{error && <div className={styles.error}>{error}</div>}
<button
type="submit"
className={styles.submitButton}
disabled={isLoading}
>
{isLoading ? 'Processing...' : (isLogin ? 'Login' : 'Sign Up')}
</button>
</form>
</div>
);
};
export default Auth; |