2025-09-16 17:29:37 +00:00
|
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
2025-09-17 17:37:41 +00:00
|
|
|
import { FieldErrors, useForm } from "react-hook-form";
|
2025-09-16 17:29:37 +00:00
|
|
|
|
|
|
|
|
import { TaxesMultiSelectField } from "@erp/core/components";
|
|
|
|
|
import { SelectField, TextAreaField, TextField } from "@repo/rdx-ui/components";
|
|
|
|
|
import {
|
|
|
|
|
Button,
|
|
|
|
|
Card,
|
|
|
|
|
CardContent,
|
|
|
|
|
CardDescription,
|
|
|
|
|
CardHeader,
|
|
|
|
|
CardTitle,
|
|
|
|
|
Form,
|
|
|
|
|
FormControl,
|
|
|
|
|
FormField,
|
|
|
|
|
FormItem,
|
|
|
|
|
FormLabel,
|
|
|
|
|
FormMessage,
|
|
|
|
|
RadioGroup,
|
|
|
|
|
RadioGroupItem,
|
|
|
|
|
} from "@repo/shadcn-ui/components";
|
|
|
|
|
|
|
|
|
|
import { useUnsavedChangesNotifier } from "@erp/core/hooks";
|
2025-09-17 17:37:41 +00:00
|
|
|
import { COUNTRY_OPTIONS, LANGUAGE_OPTIONS } from "../../constants/customer.constants";
|
2025-09-16 17:29:37 +00:00
|
|
|
import { useTranslation } from "../../i18n";
|
2025-09-17 17:37:41 +00:00
|
|
|
import { CustomerData, CustomerUpdateData, CustomerUpdateSchema } from "../../schemas";
|
2025-09-16 17:29:37 +00:00
|
|
|
|
|
|
|
|
interface CustomerFormProps {
|
|
|
|
|
formId: string;
|
2025-09-17 17:37:41 +00:00
|
|
|
data?: CustomerData;
|
2025-09-16 17:29:37 +00:00
|
|
|
isPending?: boolean;
|
|
|
|
|
/**
|
|
|
|
|
* Callback function to handle form submission.
|
|
|
|
|
* @param data - The customer data submitted by the form.
|
|
|
|
|
*/
|
2025-09-17 17:37:41 +00:00
|
|
|
onSubmit?: (data: CustomerUpdateData) => void;
|
2025-09-16 17:29:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const CustomerEditForm = ({ formId, data, onSubmit, isPending }: CustomerFormProps) => {
|
|
|
|
|
const { t } = useTranslation();
|
|
|
|
|
|
2025-09-17 17:37:41 +00:00
|
|
|
const form = useForm<CustomerUpdateData>({
|
|
|
|
|
resolver: zodResolver(CustomerUpdateSchema),
|
2025-09-16 17:29:37 +00:00
|
|
|
defaultValues: data,
|
|
|
|
|
disabled: isPending,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
useUnsavedChangesNotifier({
|
|
|
|
|
isDirty: form.formState.isDirty,
|
|
|
|
|
});
|
|
|
|
|
|
2025-09-17 17:37:41 +00:00
|
|
|
const handleSubmit = (data: CustomerUpdateData) => {
|
2025-09-16 17:29:37 +00:00
|
|
|
console.log("Datos del formulario:", data);
|
|
|
|
|
onSubmit?.(data);
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-17 17:37:41 +00:00
|
|
|
const handleError = (errors: FieldErrors<CustomerUpdateData>) => {
|
2025-09-16 17:29:37 +00:00
|
|
|
console.error("Errores en el formulario:", errors);
|
|
|
|
|
// Aquí puedes manejar los errores, por ejemplo, mostrar un mensaje al usuario
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleCancel = () => {
|
|
|
|
|
form.reset(data);
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-17 17:37:41 +00:00
|
|
|
const {
|
|
|
|
|
formState: { isDirty, dirtyFields },
|
|
|
|
|
} = form;
|
|
|
|
|
|
2025-09-16 17:29:37 +00:00
|
|
|
return (
|
|
|
|
|
<Form {...form}>
|
2025-09-17 17:37:41 +00:00
|
|
|
<div className='mt-6 p-4 border rounded bg-gray-50'>
|
|
|
|
|
<p>
|
|
|
|
|
<strong>¿Formulario modificado?</strong> {isDirty ? "Sí" : "No"}
|
|
|
|
|
</p>
|
|
|
|
|
<p>
|
|
|
|
|
<strong>Campos modificados:</strong>{" "}
|
|
|
|
|
{Object.keys(dirtyFields).length > 0 ? Object.keys(dirtyFields).join(", ") : "Ninguno"}
|
|
|
|
|
</p>
|
|
|
|
|
</div>{" "}
|
2025-09-16 17:29:37 +00:00
|
|
|
<form id={formId} onSubmit={form.handleSubmit(handleSubmit, handleError)}>
|
|
|
|
|
<div className='w-full grid grid-cols-1 space-y-8 space-x-8 xl:grid-cols-2'>
|
|
|
|
|
{/* Información básica */}
|
|
|
|
|
<Card className='shadow-none'>
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<CardTitle>{t("form_groups.basic_info.title")}</CardTitle>
|
|
|
|
|
<CardDescription>{t("form_groups.basic_info.description")}</CardDescription>
|
|
|
|
|
</CardHeader>
|
|
|
|
|
<CardContent className='grid grid-cols-1 gap-y-8 gap-x-6 @xl:grid-cols-2'>
|
|
|
|
|
<FormField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='is_company'
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className='space-y-3'>
|
|
|
|
|
<FormLabel>{t("form_fields.customer_type.label")}</FormLabel>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<RadioGroup
|
2025-09-17 17:37:41 +00:00
|
|
|
onValueChange={(value) => field.onChange(value === "1")}
|
2025-09-16 17:29:37 +00:00
|
|
|
defaultValue={field.value ? "1" : "0"}
|
|
|
|
|
className='flex gap-6'
|
|
|
|
|
>
|
|
|
|
|
<FormItem className='flex items-center space-x-2'>
|
|
|
|
|
<FormControl>
|
2025-09-17 17:37:41 +00:00
|
|
|
<RadioGroupItem value='1' />
|
2025-09-16 17:29:37 +00:00
|
|
|
</FormControl>
|
|
|
|
|
<FormLabel className='font-normal'>
|
|
|
|
|
{t("form_fields.customer_type.company")}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
</FormItem>
|
|
|
|
|
|
|
|
|
|
<FormItem className='flex items-center space-x-2'>
|
|
|
|
|
<FormControl>
|
2025-09-17 17:37:41 +00:00
|
|
|
<RadioGroupItem value='0' />
|
2025-09-16 17:29:37 +00:00
|
|
|
</FormControl>
|
|
|
|
|
<FormLabel className='font-normal'>
|
|
|
|
|
{t("form_fields.customer_type.individual")}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
</FormItem>
|
|
|
|
|
</RadioGroup>
|
|
|
|
|
</FormControl>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='name'
|
|
|
|
|
required
|
|
|
|
|
label={t("form_fields.name.label")}
|
|
|
|
|
placeholder={t("form_fields.name.placeholder")}
|
|
|
|
|
description={t("form_fields.name.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='trade_name'
|
|
|
|
|
label={t("form_fields.trade_name.label")}
|
|
|
|
|
placeholder={t("form_fields.trade_name.placeholder")}
|
|
|
|
|
description={t("form_fields.trade_name.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='reference'
|
|
|
|
|
label={t("form_fields.reference.label")}
|
|
|
|
|
placeholder={t("form_fields.reference.placeholder")}
|
|
|
|
|
description={t("form_fields.reference.description")}
|
|
|
|
|
/>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
{/* Dirección */}
|
|
|
|
|
<Card className='shadow-none'>
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<CardTitle>{t("form_groups.address.title")}</CardTitle>
|
|
|
|
|
<CardDescription>{t("form_groups.address.description")}</CardDescription>
|
|
|
|
|
</CardHeader>
|
|
|
|
|
<CardContent className='grid grid-cols-1 gap-y-8 gap-x-6 @xl:grid-cols-2'>
|
|
|
|
|
<TextField
|
|
|
|
|
className='xl:col-span-2'
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='street'
|
|
|
|
|
required
|
|
|
|
|
label={t("form_fields.street.label")}
|
|
|
|
|
placeholder={t("form_fields.street.placeholder")}
|
|
|
|
|
description={t("form_fields.street.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='city'
|
|
|
|
|
required
|
|
|
|
|
label={t("form_fields.city.label")}
|
|
|
|
|
placeholder={t("form_fields.city.placeholder")}
|
|
|
|
|
description={t("form_fields.city.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='postal_code'
|
|
|
|
|
required
|
|
|
|
|
label={t("form_fields.postal_code.label")}
|
|
|
|
|
placeholder={t("form_fields.postal_code.placeholder")}
|
|
|
|
|
description={t("form_fields.postal_code.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='province'
|
|
|
|
|
required
|
|
|
|
|
label={t("form_fields.province.label")}
|
|
|
|
|
placeholder={t("form_fields.province.placeholder")}
|
|
|
|
|
description={t("form_fields.province.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<SelectField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='country'
|
|
|
|
|
required
|
|
|
|
|
label={t("form_fields.country.label")}
|
|
|
|
|
placeholder={t("form_fields.country.placeholder")}
|
|
|
|
|
description={t("form_fields.country.description")}
|
2025-09-17 17:37:41 +00:00
|
|
|
items={COUNTRY_OPTIONS}
|
2025-09-16 17:29:37 +00:00
|
|
|
/>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
{/* Contacto */}
|
|
|
|
|
<Card className='shadow-none'>
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<CardTitle>{t("form_groups.contact_info.title")}</CardTitle>
|
|
|
|
|
<CardDescription>{t("form_groups.contact_info.description")}</CardDescription>
|
|
|
|
|
</CardHeader>
|
|
|
|
|
<CardContent className='grid grid-cols-1 gap-y-8 gap-x-6 @xl:grid-cols-2'>
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='email_primary'
|
|
|
|
|
label={t("form_fields.email_primary.label")}
|
|
|
|
|
placeholder={t("form_fields.email_primary.placeholder")}
|
|
|
|
|
description={t("form_fields.email_primary.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='email_secondary'
|
|
|
|
|
label={t("form_fields.email_secondary.label")}
|
|
|
|
|
placeholder={t("form_fields.email_secondary.placeholder")}
|
|
|
|
|
description={t("form_fields.email_secondary.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='phone_primary'
|
|
|
|
|
label={t("form_fields.phone_primary.label")}
|
|
|
|
|
placeholder={t("form_fields.phone_primary.placeholder")}
|
|
|
|
|
description={t("form_fields.phone_primary.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='phone_secondary'
|
|
|
|
|
label={t("form_fields.phone_secondary.label")}
|
|
|
|
|
placeholder={t("form_fields.phone_secondary.placeholder")}
|
|
|
|
|
description={t("form_fields.phone_secondary.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='mobile_primary'
|
|
|
|
|
label={t("form_fields.mobile_primary.label")}
|
|
|
|
|
placeholder={t("form_fields.mobile_primary.placeholder")}
|
|
|
|
|
description={t("form_fields.mobile_primary.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='mobile_secondary'
|
|
|
|
|
label={t("form_fields.mobile_secondary.label")}
|
|
|
|
|
placeholder={t("form_fields.mobile_secondary.placeholder")}
|
|
|
|
|
description={t("form_fields.mobile_secondary.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='fax'
|
|
|
|
|
label={t("form_fields.fax.label")}
|
|
|
|
|
placeholder={t("form_fields.fax.placeholder")}
|
|
|
|
|
description={t("form_fields.fax.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextField
|
|
|
|
|
className='xl:col-span-2'
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='website'
|
|
|
|
|
label={t("form_fields.website.label")}
|
|
|
|
|
placeholder={t("form_fields.website.placeholder")}
|
|
|
|
|
description={t("form_fields.website.description")}
|
|
|
|
|
/>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
{/* Configuraciones Adicionales */}
|
|
|
|
|
<Card className='shadow-none'>
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<CardTitle>{t("form_groups.additional_config.title")}</CardTitle>
|
|
|
|
|
<CardDescription>{t("form_groups.additional_config.description")}</CardDescription>
|
|
|
|
|
</CardHeader>
|
|
|
|
|
<CardContent className='grid grid-cols-1 gap-y-8 gap-x-6 @xl:grid-cols-2'>
|
|
|
|
|
<TaxesMultiSelectField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='default_tax'
|
|
|
|
|
required
|
|
|
|
|
label={t("form_fields.default_tax.label")}
|
|
|
|
|
placeholder={t("form_fields.default_tax.placeholder")}
|
|
|
|
|
description={t("form_fields.default_tax.description")}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<SelectField
|
|
|
|
|
control={form.control}
|
2025-09-17 17:37:41 +00:00
|
|
|
name='language_code'
|
2025-09-16 17:29:37 +00:00
|
|
|
required
|
|
|
|
|
label={t("form_fields.lang_code.label")}
|
|
|
|
|
placeholder={t("form_fields.lang_code.placeholder")}
|
|
|
|
|
description={t("form_fields.lang_code.description")}
|
2025-09-17 17:37:41 +00:00
|
|
|
items={LANGUAGE_OPTIONS}
|
2025-09-16 17:29:37 +00:00
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<TextAreaField
|
|
|
|
|
className=''
|
|
|
|
|
control={form.control}
|
|
|
|
|
name='legal_record'
|
|
|
|
|
required
|
|
|
|
|
label={t("form_fields.legal_record.label")}
|
|
|
|
|
placeholder={t("form_fields.legal_record.placeholder")}
|
|
|
|
|
description={t("form_fields.legal_record.description")}
|
|
|
|
|
/>
|
|
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
</div>
|
2025-09-17 17:37:41 +00:00
|
|
|
<Button type='submit'>{t("pages.update.submit")}</Button>
|
2025-09-16 17:29:37 +00:00
|
|
|
</form>
|
|
|
|
|
</Form>
|
|
|
|
|
);
|
|
|
|
|
};
|