227 lines
6.2 KiB
TypeScript
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 >
|
|
);
|
|
};
|
|
*/ |