'use client' import * as React from 'react' import type { FieldErrors } from 'react-hook-form' import { authClient } from '@admin/auth/client' import { Button } from '@admin/components/ui/button' import { Card, CardContent } from '@admin/components/ui/card' import { Field, FieldGroup, FieldLabel } from '@admin/components/ui/field' import { Form } from '@admin/components/ui/form' import { Input } from '@admin/components/ui/input' import { Spinner } from '@admin/components/ui/spinner' import { cn } from '@admin/utils/shared/cn' import { standardSchemaResolver } from '@hookform/resolvers/standard-schema' import Image from 'next/image' import Link from 'next/link' import { useRouter } from 'next/navigation' import { createSerializer, parseAsString, parseAsStringLiteral, useQueryState } from 'nuqs' import { useForm } from 'react-hook-form' import { toast } from 'sonner' import { z } from 'zod/v3' const serializeLoginUrl = createSerializer({ reset: parseAsStringLiteral(['success']) }) const resetPasswordSchema = z .object({ newPassword: z.string().min(8, 'Password must be at least 8 characters'), confirmPassword: z.string().min(1, 'Confirm the new password') }) .refine((values) => values.newPassword === values.confirmPassword, { message: 'Passwords do not match', path: ['confirmPassword'] }) type ResetPasswordFormValues = z.infer export function ResetPasswordForm({ className, ...props }: React.ComponentProps<'div'>) { const router = useRouter() const [token] = useQueryState('token', parseAsString) const [isPending, startTransition] = React.useTransition() const form = useForm({ resolver: standardSchemaResolver(resetPasswordSchema), defaultValues: { newPassword: '', confirmPassword: '' }, mode: 'onChange', reValidateMode: 'onChange' }) if (!token) { return (

Invalid reset link

This password reset link is invalid or has expired. Please request a new one.

Request a new reset link
) } const handleSubmit = (values: ResetPasswordFormValues) => { startTransition(async () => { try { const { error } = await authClient.resetPassword({ newPassword: values.newPassword, token }) if (error) { toast.error(error.message || 'Failed to reset password') return } await authClient.getSession({ query: { disableCookieCache: true } }) router.push(serializeLoginUrl('/admin/login', { reset: 'success' })) } catch { toast.error('Failed to reset your password. Try again.') } }) } const handleInvalid = (errors: FieldErrors) => { const message = errors.newPassword?.message ?? errors.confirmPassword?.message toast.error(typeof message === 'string' ? message : 'Please check your new password.') } return (

Reset password

Enter your new password below

New Password Confirm Password
) }