FactuGES_ERP/modules/customer-invoices/src/web/pages/update/invoice-update-page.tsx
2025-10-12 20:36:33 +02:00

227 lines
6.2 KiB
TypeScript

import { SpainTaxCatalogProvider } from '@erp/core';
import {
useUrlParamId
} from "@erp/core/hooks";
import { ErrorAlert } from "@erp/customers/components";
import { AppContent, BackHistoryButton } from "@repo/rdx-ui/components";
import { useMemo } from 'react';
import {
CustomerInvoiceEditorSkeleton
} from "../../components";
import { InvoiceProvider } from '../../context';
import { useInvoiceQuery } from "../../hooks";
import { useTranslation } from "../../i18n";
import { InvoiceUpdateComp } from './invoice-update-comp';
export const InvoiceUpdatePage = () => {
const invoice_id = useUrlParamId();
const { t } = useTranslation();
const taxCatalog = useMemo(() => SpainTaxCatalogProvider(), []);
const invoiceQuery = useInvoiceQuery(invoice_id, { enabled: !!invoice_id });
const { data: invoiceData, isLoading, isError, error,
} = invoiceQuery;
console.log("InvoiceUpdatePage");
if (isLoading) {
return <CustomerInvoiceEditorSkeleton />;
}
if (isError || !invoiceData) {
return (
<AppContent>
<ErrorAlert
title={t("pages.update.loadErrorTitle")}
message={(error as Error)?.message || "Error al cargar la factura"}
/>
<BackHistoryButton />
</AppContent>
);
}
// Monta el contexto aquí, así todo lo que esté dentro puede usar hooks
return (
<InvoiceProvider
invoice_id={invoice_id!}
taxCatalog={taxCatalog}
company_id={invoiceData.company_id}
status={invoiceData.status}
language_code={invoiceData.language_code}
currency_code={invoiceData.currency_code}
>
<InvoiceUpdateComp invoice={invoiceData} />
</InvoiceProvider>
);
};
/*
const invoiceId = useUrlParamId();
const { t } = useTranslation();
const navigate = useNavigate();
const taxCatalog = useMemo(() => SpainTaxCatalogProvider(), [])
// 1) Estado de carga de la factura (query)
const {
data: invoiceData,
isLoading: isLoadingInvoice,
isError: isLoadError,
error: loadError,
} = useInvoiceQuery(invoiceId, { enabled: !!invoiceId });
// 2) Estado de actualización (mutación)
const {
mutate,
isPending: isUpdating,
isError: isUpdateError,
error: updateError,
} = useUpdateCustomerInvoice();
const context = useInvoiceContext();
// 3) Form hook
const form = useHookForm<InvoiceFormData>({
resolverSchema: InvoiceFormSchema,
defaultValues: defaultCustomerInvoiceFormData,
values: invoiceData ? invoiceDtoToFormAdapter.fromDto(invoiceData, taxCatalog) : undefined,
disabled: isUpdating,
});
// 4) Activa recálculo automático de los totales de la factura cuando hay algún cambio en importes
useInvoiceAutoRecalc(form, {
taxCatalog,
currency_code: invoiceData?.currency_code || 'EUR'
});
const handleSubmit = (formData: InvoiceFormData) => {
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 InvoiceFormData);
},
onError(error) {
showErrorToast(t("pages.update.errorTitle"), error.message);
},
}
);
};
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 (
<InvoiceProvider
taxCatalog={taxCatalog}
company_id={invoiceData.company_id}
status={invoiceData.status}
language_code={invoiceData.language_code}
currency_code={invoiceData.currency_code}
>
<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>
{
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 >
</InvoiceProvider >
);
};
*/