Scrum4Me/components/auth/auth-form.tsx

82 lines
2.5 KiB
TypeScript

'use client'
import { useActionState } from 'react'
import { useFormStatus } from 'react-dom'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { debugProps } from '@/lib/debug'
type ActionResult = { error: string | Record<string, string[]> } | undefined
function SubmitButton({ label }: { label: string }) {
const { pending } = useFormStatus()
return (
<Button type="submit" className="w-full" disabled={pending} data-debug-id="auth-form__submit">
{pending ? 'Even wachten…' : label}
</Button>
)
}
function getErrorMessage(error: ActionResult): string | null {
if (!error) return null
if (typeof error.error === 'string') return error.error
// Field errors object — flatten to first message
const first = Object.values(error.error).flat()[0]
return first ?? null
}
interface AuthFormProps {
action: (_prevState: unknown, formData: FormData) => Promise<ActionResult>
submitLabel: string
}
export function AuthForm({ action, submitLabel }: AuthFormProps) {
const [state, formAction] = useActionState(action, undefined)
const errorMessage = getErrorMessage(state)
return (
<form action={formAction} className="space-y-4" {...debugProps('auth-form', 'AuthForm', 'components/auth/auth-form.tsx')}>
<div className="space-y-2">
<label htmlFor="username" className="text-sm font-medium text-foreground">
Gebruikersnaam
</label>
<Input
id="username"
name="username"
type="text"
autoComplete="username"
required
minLength={3}
placeholder="jouw-naam"
className="bg-input-background border-border focus-visible:ring-primary"
data-debug-id="auth-form__username"
/>
</div>
<div className="space-y-2">
<label htmlFor="password" className="text-sm font-medium text-foreground">
Wachtwoord
</label>
<Input
id="password"
name="password"
type="password"
autoComplete="current-password"
required
minLength={8}
placeholder="••••••••"
className="bg-input-background border-border focus-visible:ring-primary"
data-debug-id="auth-form__password"
/>
</div>
{errorMessage && (
<div className="bg-error-container text-error-container-foreground rounded-lg px-3 py-2 text-sm border-l-4 border-error">
{errorMessage}
</div>
)}
<SubmitButton label={submitLabel} />
</form>
)
}