Scrum4Me/app/(auth)/reset-password/reset-form.tsx
Scrum4Me Agent a19ae89e37 feat(ST-l9kkxh2m): /reset-password pagina + resetPasswordAction + hashPassword
- lib/auth.ts: hashPassword(password) geëxporteerd (bcrypt, rounds=12)
- actions/auth.ts: resetPasswordAction met Zod-validatie (min 8, superRefine gelijkheid),
  prisma.user.update (password_hash + must_reset_password=false), redirect /dashboard
- app/(auth)/reset-password/page.tsx: server guard (userId check + must_reset_password check)
- app/(auth)/reset-password/reset-form.tsx: client form (nieuw wachtwoord + bevestiging)
- __tests__/actions/auth.test.ts: 3 tests voor resetPasswordAction
2026-05-05 14:30:59 +02:00

74 lines
2.2 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 { resetPasswordAction } from '@/actions/auth'
type ActionResult = { error: string | Record<string, string[]> } | undefined
function SubmitButton() {
const { pending } = useFormStatus()
return (
<Button type="submit" className="w-full" disabled={pending}>
{pending ? 'Even wachten…' : 'Wachtwoord opslaan'}
</Button>
)
}
function getErrorMessage(error: ActionResult): string | null {
if (!error) return null
if (typeof error.error === 'string') return error.error
const first = Object.values(error.error).flat()[0]
return first ?? null
}
export function ResetPasswordForm() {
const [state, formAction] = useActionState(resetPasswordAction, undefined)
const errorMessage = getErrorMessage(state)
return (
<form action={formAction} className="space-y-4">
<div className="space-y-2">
<label htmlFor="password" className="text-sm font-medium text-foreground">
Nieuw wachtwoord
</label>
<Input
id="password"
name="password"
type="password"
autoComplete="new-password"
required
minLength={8}
placeholder="••••••••"
className="bg-input-background border-border focus-visible:ring-primary"
/>
</div>
<div className="space-y-2">
<label htmlFor="confirm" className="text-sm font-medium text-foreground">
Bevestig wachtwoord
</label>
<Input
id="confirm"
name="confirm"
type="password"
autoComplete="new-password"
required
minLength={8}
placeholder="••••••••"
className="bg-input-background border-border focus-visible:ring-primary"
/>
</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 />
</form>
)
}