Uecko_ERP/modules/customer-invoices/src/web/pages/update/customer-invoices-update-page.tsx
2025-10-08 15:11:26 +02:00

183 lines
5.5 KiB
TypeScript

import { formHasAnyDirty, pickFormDirtyValues } from "@erp/core/client";
import {
FormCommitButtonGroup,
UnsavedChangesProvider,
useHookForm,
useUrlParamId,
} from "@erp/core/hooks";
import { ErrorAlert, NotFoundCard } from "@erp/customers/components";
import { AppBreadcrumb, AppContent, AppHeader, BackHistoryButton } from "@repo/rdx-ui/components";
import { showErrorToast, showSuccessToast, showWarningToast } from "@repo/rdx-ui/helpers";
import { FilePenIcon } from "lucide-react";
import { FieldErrors, FormProvider } from "react-hook-form";
import { useNavigate } from "react-router-dom";
import {
CustomerInvoiceEditForm,
CustomerInvoiceEditorSkeleton,
PageHeader,
} from "../../components";
import { useCustomerInvoiceQuery, useUpdateCustomerInvoice } from "../../hooks";
import { useTranslation } from "../../i18n";
import {
CustomerInvoiceFormData,
CustomerInvoiceFormSchema,
defaultCustomerInvoiceFormData
} from "../../schemas";
export const CustomerInvoiceUpdatePage = () => {
const invoiceId = useUrlParamId();
const { t } = useTranslation();
const navigate = useNavigate();
// 1) Estado de carga de la factura (query)
const {
data: invoiceData,
isLoading: isLoadingInvoice,
isError: isLoadError,
error: loadError,
} = useCustomerInvoiceQuery(invoiceId, { enabled: !!invoiceId });
// 2) Estado de actualización (mutación)
const {
mutate,
isPending: isUpdating,
isError: isUpdateError,
error: updateError,
} = useUpdateCustomerInvoice();
// 3) Form hook
const form = useHookForm<CustomerInvoiceFormData>({
resolverSchema: CustomerInvoiceFormSchema,
initialValues: (invoiceData as unknown as CustomerInvoiceFormData) ?? defaultCustomerInvoiceFormData,
disabled: isUpdating,
});
const handleSubmit = (formData: CustomerInvoiceFormData) => {
const { dirtyFields } = form.formState;
if (!formHasAnyDirty(dirtyFields)) {
showWarningToast("No hay cambios para guardar");
return;
}
const patchData = pickFormDirtyValues(formData, dirtyFields);
console.log(patchData);
mutate(
{ id: invoiceId!, data: patchData },
{
onSuccess(data) {
showSuccessToast(t("pages.update.successTitle"), t("pages.update.successMsg"));
// 🔹 limpiar el form e isDirty pasa a false
form.reset(data as unknown as CustomerInvoiceFormData);
},
onError(error) {
showErrorToast(t("pages.update.errorTitle"), error.message);
},
}
);
};
const handleReset = () =>
form.reset((invoiceData as unknown as CustomerInvoiceFormData) ?? defaultCustomerInvoiceFormData);
const handleBack = () => {
navigate(-1);
};
const handleError = (errors: FieldErrors<CustomerInvoiceFormData>) => {
console.error("Errores en el formulario:", errors);
// Aquí puedes manejar los errores, por ejemplo, mostrar un mensaje al usuario
};
if (isLoadingInvoice) {
return <CustomerInvoiceEditorSkeleton />;
}
if (isLoadError) {
return (
<>
<AppBreadcrumb />
<AppContent>
<ErrorAlert
title={t("pages.update.loadErrorTitle", "No se pudo cargar la factura")}
message={
(loadError as Error)?.message ??
t("pages.update.loadErrorMsg", "Inténtalo de nuevo más tarde.")
}
/>
<div className='flex items-center justify-end'>
<BackHistoryButton />
</div>
</AppContent>
</>
);
}
if (!invoiceData)
return (
<>
<AppBreadcrumb />
<AppContent>
<NotFoundCard
title={t("pages.update.notFoundTitle", "Factura de cliente no encontrada")}
message={t("pages.update.notFoundMsg", "Revisa el identificador o vuelve al listado.")}
/>
</AppContent>
</>
);
return (
<UnsavedChangesProvider isDirty={form.formState.isDirty}>
<AppHeader>
<AppBreadcrumb />
<PageHeader
status={invoiceData.status}
title={
<>
{t("pages.edit.title")} {invoiceData.invoice_number}
</>
}
description={t("pages.edit.description")}
icon={<FilePenIcon className='size-12 text-primary stroke-1' aria-hidden />}
rightSlot={
<FormCommitButtonGroup
isLoading={isUpdating}
disabled={isUpdating}
cancel={{ to: "/customer-invoices/list", disabled: isUpdating }}
submit={{ formId: "customer-invoice-update-form", disabled: isUpdating }}
onBack={handleBack}
onReset={handleReset}
/>
}
/>
</AppHeader>
<AppContent>
{/* Alerta de error de actualización (si ha fallado el último intento) */}
{isUpdateError && (
<ErrorAlert
title={t("pages.update.errorTitle", "No se pudo guardar los cambios")}
message={
(updateError as Error)?.message ??
t("pages.update.errorMsg", "Revisa los datos e inténtalo de nuevo.")
}
/>
)}
<FormProvider {...form}>
<CustomerInvoiceEditForm
formId={"customer-invoice-update-form"} // para que el botón del header pueda hacer submit
onSubmit={handleSubmit}
onError={handleError}
className='max-w-full'
/>
</FormProvider>
</AppContent>
</UnsavedChangesProvider>
);
};