templates2.Admin.Next/components/AuthForm.tsx
w4c-templates c64f7ffa9e
Some checks failed
CI / quality (push) Has been cancelled
chore(template): publish Admin.Next
2026-10-11 23:25:34 +03:00

80 lines
2.9 KiB
TypeScript

'use client';
import { useState } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import Link from 'next/link';
import { Field } from '@/components/ui';
import { t } from '@/lib/i18n';
export function AuthForm({ mode }: { mode: 'login' | 'register' }) {
const router = useRouter();
const params = useSearchParams();
const next = params.get('next') || '/dashboard';
const [busy, setBusy] = useState(false);
const [error, setError] = useState<string | null>(null);
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setBusy(true);
setError(null);
const form = new FormData(e.currentTarget);
const body = Object.fromEntries(form.entries());
try {
const res = await fetch(`/api/auth/${mode}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (!res.ok) {
const data = (await res.json().catch(() => ({}))) as { error?: string };
throw new Error(data.error || `Request failed (${res.status})`);
}
router.push(next);
router.refresh();
} catch (err) {
setError(err instanceof Error ? err.message : 'Request failed');
setBusy(false);
}
}
const isRegister = mode === 'register';
return (
<div className="card">
<h1 className="text-xl font-semibold">{isRegister ? t('auth.registerTitle') : t('auth.loginTitle')}</h1>
<form className="mt-6 space-y-4" onSubmit={onSubmit} noValidate>
{isRegister && (
<Field label={t('auth.name')} htmlFor="name">
<input id="name" name="name" className="input" autoComplete="name" />
</Field>
)}
<Field label={t('auth.email')} htmlFor="email">
<input id="email" name="email" type="email" required className="input" autoComplete="email" />
</Field>
<Field label={t('auth.password')} htmlFor="password">
<input
id="password"
name="password"
type="password"
required
minLength={8}
className="input"
autoComplete={isRegister ? 'new-password' : 'current-password'}
/>
</Field>
{error && <p className="text-sm text-red-600">{error}</p>}
<button type="submit" className="btn-primary w-full" disabled={busy}>
{busy ? '…' : isRegister ? t('auth.submitRegister') : t('auth.submitLogin')}
</button>
</form>
<p className="muted mt-5 text-center text-sm">
{isRegister ? t('auth.hasAccount') : t('auth.noAccount')}{' '}
<Link href={isRegister ? '/login' : '/register'} className="font-medium text-brand-600 hover:underline">
{isRegister ? t('auth.submitLogin') : t('auth.submitRegister')}
</Link>
</p>
{!isRegister && <p className="muted mt-3 text-center text-xs">{t('auth.demoHint')}</p>}
</div>
);
}