Commit b8e34e6e authored by BangNSK's avatar BangNSK

fix: keep verification resend action visible

parent 673afd42
......@@ -11,15 +11,15 @@ export const Login: React.FC = () => {
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [submitting, setSubmitting] = useState(false);
const [canResendVerification, setCanResendVerification] = useState(false);
const [resending, setResending] = useState(false);
const [resendMessage, setResendMessage] = useState('');
const [resendStatus, setResendStatus] = useState<'success' | 'error' | null>(null);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
setResendMessage('');
setCanResendVerification(false);
setResendStatus(null);
setSubmitting(true);
try {
await login(email, password);
......@@ -27,9 +27,11 @@ export const Login: React.FC = () => {
} catch (err: any) {
console.error(err);
const code = err.response?.data?.code;
setCanResendVerification(code === 'USER_INACTIVE');
const isInactiveAccount = code === 'USER_INACTIVE' || err.response?.status === 403;
setError(
code === 'INVALID_CREDENTIALS'
isInactiveAccount
? 'Tài khoản chưa được xác thực hoặc đã bị khóa. Bạn có thể gửi lại email xác thực bên dưới.'
: code === 'INVALID_CREDENTIALS'
? 'Tài khoản hoặc mật khẩu không chính xác.'
: err.response?.data?.message || 'Đăng nhập thất bại. Vui lòng kiểm tra lại thông tin.',
);
......@@ -39,14 +41,23 @@ export const Login: React.FC = () => {
};
const handleResendVerification = async () => {
if (!email.trim()) {
setResendStatus('error');
setResendMessage('Vui lòng nhập địa chỉ email trước khi gửi lại email xác thực.');
return;
}
setResending(true);
setResendMessage('');
setResendStatus(null);
try {
const response = await api.post('/auth/resend-verification', { email });
setResendStatus('success');
setResendMessage(
response.data.message || 'Nếu tài khoản chưa được xác thực, email xác thực đã được gửi lại.',
);
} catch (err: any) {
setResendStatus('error');
setResendMessage(err.response?.data?.message || 'Không thể gửi lại email xác thực. Vui lòng thử lại sau.');
} finally {
setResending(false);
......@@ -71,21 +82,18 @@ export const Login: React.FC = () => {
{error && (
<div className="rounded-lg bg-rose-50 p-4 text-sm text-rose-700 border border-rose-100" role="alert">
<p>{error}</p>
{canResendVerification && (
<button
type="button"
onClick={() => void handleResendVerification()}
disabled={resending}
className="mt-3 inline-flex min-h-11 items-center font-semibold text-indigo-700 hover:text-indigo-900 disabled:opacity-60"
>
{resending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Gửi lại email xác thực
</button>
)}
</div>
)}
{resendMessage && (
<div className="rounded-lg border border-emerald-100 bg-emerald-50 p-4 text-sm text-emerald-700" aria-live="polite">
<div
className={`rounded-lg border p-4 text-sm ${
resendStatus === 'error'
? 'border-rose-100 bg-rose-50 text-rose-700'
: 'border-emerald-100 bg-emerald-50 text-emerald-700'
}`}
role={resendStatus === 'error' ? 'alert' : undefined}
aria-live="polite"
>
{resendMessage}
</div>
)}
......@@ -157,6 +165,19 @@ export const Login: React.FC = () => {
</div>
</form>
<div className="text-center text-sm text-slate-500">
<span>Chưa nhận được email xác thực? </span>
<button
type="button"
onClick={() => void handleResendVerification()}
disabled={resending}
className="inline-flex min-h-11 items-center font-semibold text-indigo-600 hover:text-indigo-500 disabled:cursor-not-allowed disabled:opacity-60"
>
{resending && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
Gửi lại email xác thực
</button>
</div>
<div className="text-center text-sm text-slate-500">
Chưa có tài khoản?{' '}
<Link to="/register" className="font-medium text-indigo-600 hover:text-indigo-500 transition-colors">
......
......@@ -20,6 +20,10 @@ test('login puts forgot-password below the password field and localizes invalid
);
assert.match(login, /Tài khoản hoặc mật khẩu không chính xác/);
assert.match(login, /Gửi lại email xác thực/);
assert.ok(
login.indexOf('</form>') < login.indexOf('Gửi lại email xác thực'),
'resend verification must always be visible below the login form',
);
});
test('all requested password forms expose visibility controls', () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment