143 lines
3.9 KiB
TypeScript
143 lines
3.9 KiB
TypeScript
'use client';
|
|
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
import { useCallback } from 'react';
|
|
import { useForm, useWatch } from 'react-hook-form';
|
|
import { toast } from 'sonner';
|
|
import { z } from 'zod';
|
|
|
|
import type { Client } from '@/types';
|
|
import { useSaveClientMutation } from './useClientMutations';
|
|
|
|
const phoneSchema = z
|
|
.string()
|
|
.trim()
|
|
.min(1, 'Phone number is required')
|
|
.regex(/^\+(?:[0-9] ?|-){6,18}[0-9]$/, 'Please enter a valid phone number');
|
|
|
|
const optionalTaxIdSchema = z.string().trim();
|
|
|
|
const clientFormSchema = z.object({
|
|
id: z.number().optional(),
|
|
name: z.string().trim().min(1, 'Client name is required'),
|
|
email: z.string().trim().min(1, 'Email is required').email('Invalid email'),
|
|
landline_number: phoneSchema,
|
|
address: z.string().trim().min(1, 'Address is required'),
|
|
gst: optionalTaxIdSchema,
|
|
pan: optionalTaxIdSchema,
|
|
tan: optionalTaxIdSchema,
|
|
contact_name: z.string().trim().min(1, 'Contact name is required'),
|
|
contact_phone_number: phoneSchema,
|
|
contact_email: z
|
|
.string()
|
|
.trim()
|
|
.min(1, 'Contact email is required')
|
|
.email('Invalid contact email'),
|
|
is_active: z.boolean(),
|
|
});
|
|
|
|
export type ClientFormValues = z.infer<typeof clientFormSchema>;
|
|
|
|
const defaultValues: ClientFormValues = {
|
|
name: '',
|
|
email: '',
|
|
landline_number: '',
|
|
address: '',
|
|
gst: '',
|
|
pan: '',
|
|
tan: '',
|
|
contact_name: '',
|
|
contact_phone_number: '',
|
|
contact_email: '',
|
|
is_active: true,
|
|
};
|
|
|
|
export function useClientForm({ onSaved }: { onSaved: () => void }) {
|
|
const {
|
|
register,
|
|
handleSubmit: submitForm,
|
|
reset,
|
|
control,
|
|
formState: { isSubmitting, errors, isSubmitted },
|
|
} = useForm<ClientFormValues>({
|
|
defaultValues,
|
|
mode: 'onSubmit',
|
|
reValidateMode: 'onChange',
|
|
resolver: zodResolver(clientFormSchema),
|
|
});
|
|
const saveMutation = useSaveClientMutation({
|
|
onSaved: () => {
|
|
reset(defaultValues);
|
|
onSaved();
|
|
},
|
|
});
|
|
|
|
const clientId = useWatch({ control, name: 'id' });
|
|
const name = useWatch({ control, name: 'name' }) || '';
|
|
const email = useWatch({ control, name: 'email' }) || '';
|
|
const landlineNumber = useWatch({ control, name: 'landline_number' }) || '';
|
|
const address = useWatch({ control, name: 'address' }) || '';
|
|
const contactName = useWatch({ control, name: 'contact_name' }) || '';
|
|
const contactPhoneNumber =
|
|
useWatch({ control, name: 'contact_phone_number' }) || '';
|
|
const contactEmail = useWatch({ control, name: 'contact_email' }) || '';
|
|
const canSubmit =
|
|
name.trim().length > 0 &&
|
|
email.trim().length > 0 &&
|
|
landlineNumber.trim().length > 0 &&
|
|
address.trim().length > 0 &&
|
|
contactName.trim().length > 0 &&
|
|
contactPhoneNumber.trim().length > 0 &&
|
|
contactEmail.trim().length > 0;
|
|
|
|
const handleSubmit = submitForm(
|
|
(values) => saveMutation.mutate(values),
|
|
(formErrors) => {
|
|
const firstError = Object.values(formErrors).find(
|
|
(error) => error?.message,
|
|
);
|
|
|
|
if (firstError?.message) {
|
|
toast.error(firstError.message);
|
|
}
|
|
},
|
|
);
|
|
|
|
const openCreate = useCallback(() => {
|
|
reset(defaultValues);
|
|
}, [reset]);
|
|
|
|
const openEdit = useCallback(
|
|
(client: Client) => {
|
|
reset({
|
|
id: client.id,
|
|
name: client.name || '',
|
|
email: client.email || '',
|
|
landline_number: client.landline_number || '',
|
|
address: client.address || '',
|
|
gst: client.gst || '',
|
|
pan: client.pan || '',
|
|
tan: client.tan || '',
|
|
contact_name: client.contact_name || '',
|
|
contact_phone_number: client.contact_phone_number || '',
|
|
contact_email: client.contact_email || '',
|
|
is_active: client.is_active,
|
|
});
|
|
},
|
|
[reset],
|
|
);
|
|
|
|
return {
|
|
register,
|
|
handleSubmit,
|
|
reset,
|
|
openCreate,
|
|
openEdit,
|
|
clientId,
|
|
errors,
|
|
isSubmitted,
|
|
canSubmit,
|
|
isSaving: isSubmitting || saveMutation.isPending,
|
|
};
|
|
}
|