diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx index 751c0387..3b6e86a3 100644 --- a/src/app/(auth)/login/page.tsx +++ b/src/app/(auth)/login/page.tsx @@ -13,6 +13,8 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { BrandedAuthShell } from '@/components/shared/branded-auth-shell'; import { useAuthBranding } from '@/components/shared/auth-branding-provider'; +import { FormErrorSummary } from '@/components/forms/form-error-summary'; +import { useFormScrollToError } from '@/hooks/use-form-scroll-to-error'; // `identifier` accepts either an email address or a username (3–30 lowercase // letters / digits / dot / underscore / hyphen). The server endpoint @@ -75,6 +77,7 @@ export default function LoginPage() { } = useForm({ resolver: zodResolver(loginSchema), }); + const submitWithScroll = useFormScrollToError(handleSubmit, errors); async function onSubmit(data: LoginFormData) { setIsLoading(true); @@ -112,7 +115,11 @@ export default function LoginPage() {

Sign in to continue

-
+ +
({ resolver: zodResolver(resetSchema), }); + const submitWithScroll = useFormScrollToError(handleSubmit, errors); // If the user landed here from a stale email link that points to // `/reset-password?token=…` instead of `/set-password?token=…`, hand @@ -96,7 +99,8 @@ export default function ResetPasswordPage() {
) : ( - + +
({ resolver: zodResolver(passwordSchema), }); + const submitWithScroll = useFormScrollToError(handleSubmit, errors); async function onSubmit(data: SetPasswordFormData) { if (!token) { @@ -138,7 +141,11 @@ function SetPasswordInner() {

Choose a password for your CRM account

- + +
({ resolver: zodResolver(setupSchema), }); + const submitWithScroll = useFormScrollToError(handleSubmit, errors); useEffect(() => { let cancelled = false; @@ -119,7 +122,16 @@ export default function SetupPage() {

- + +
- + + {/* Step 1: Client Info */} {step === 1 && ( diff --git a/src/components/berths/berth-detail-header.tsx b/src/components/berths/berth-detail-header.tsx index d4c7066d..46d2a285 100644 --- a/src/components/berths/berth-detail-header.tsx +++ b/src/components/berths/berth-detail-header.tsx @@ -25,6 +25,8 @@ import { } from '@/components/ui/select'; import { Textarea } from '@/components/ui/textarea'; import { DetailHeaderStrip } from '@/components/shared/detail-header-strip'; +import { FormErrorSummary } from '@/components/forms/form-error-summary'; +import { useFormScrollToError } from '@/hooks/use-form-scroll-to-error'; import { PermissionGate } from '@/components/shared/permission-gate'; import { StatusPill, type StatusPillStatus } from '@/components/ui/status-pill'; import { BerthForm } from './berth-form'; @@ -128,11 +130,12 @@ function StatusChangeDialog({ setValue, watch, reset, - formState: { isSubmitting }, + formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(updateBerthStatusSchema), defaultValues: { status: currentStatus as (typeof BERTH_STATUSES)[number], reason: '' }, }); + const submitWithScroll = useFormScrollToError(handleSubmit, errors); const status = watch('status'); const interestId = watch('interestId'); @@ -180,7 +183,11 @@ function StatusChangeDialog({ Change Status - + +