feat(forms): add PhoneInput and unify module form validation UX

This commit is contained in:
2026-06-23 16:28:28 +05:30
parent 27cf5c9d3f
commit 066374bebc
30 changed files with 1415 additions and 229 deletions

View File

@@ -1,10 +1,15 @@
'use client';
import type { ComponentProps } from 'react';
import type { FieldErrors, UseFormRegister } from 'react-hook-form';
import { useRef, type ComponentProps } from 'react';
import {
Controller,
type Control,
type FieldErrors,
type UseFormRegister,
} from 'react-hook-form';
import { Loader2 } from 'lucide-react';
import { FormField } from '@/components/form';
import { FormField, PhoneInput } from '@/components/form';
import { Button } from '@/components/ui/button';
import {
Dialog,
@@ -22,6 +27,7 @@ interface ClientSheetProps {
onOpenChange: (open: boolean) => void;
clientId?: number;
register: UseFormRegister<ClientFormValues>;
control: Control<ClientFormValues>;
errors: FieldErrors<ClientFormValues>;
isSubmitted: boolean;
onSubmit: ComponentProps<'form'>['onSubmit'];
@@ -34,12 +40,14 @@ export function ClientSheet({
onOpenChange,
clientId,
register,
control,
errors,
isSubmitted,
onSubmit,
canSubmit,
isSaving,
}: ClientSheetProps) {
const dropdownPortalRef = useRef<HTMLDivElement | null>(null);
const firstNameErrorMessage = isSubmitted
? errors.first_name?.message
: undefined;
@@ -201,11 +209,19 @@ export function ClientSheet({
required
error={contactPhoneErrorMessage}
>
<Input
id="contact-phone-number"
placeholder="Enter contact phone"
aria-invalid={!!contactPhoneErrorMessage}
{...register('contact_phone_number')}
<Controller
control={control}
name="contact_phone_number"
render={({ field }) => (
<PhoneInput
value={field.value}
onChange={field.onChange}
onBlur={field.onBlur}
placeholder="Enter contact phone"
aria-invalid={!!contactPhoneErrorMessage}
portalContainer={dropdownPortalRef}
/>
)}
/>
</FormField>
@@ -244,6 +260,8 @@ export function ClientSheet({
</Button>
</DialogFooter>
</form>
<div ref={dropdownPortalRef} />
</DialogContent>
</Dialog>
);