158 lines
4.9 KiB
TypeScript
158 lines
4.9 KiB
TypeScript
import { AppBreadcrumb, AppContent, BackHistoryButton } from "@repo/rdx-ui/components";
|
|
import { useNavigate } from "react-router-dom";
|
|
|
|
import { FormCommitButtonGroup, UnsavedChangesProvider, useUrlParamId } from "@erp/core/hooks";
|
|
import { showErrorToast, showSuccessToast } from "@repo/shadcn-ui/lib/utils";
|
|
import { useState } from "react";
|
|
import { FieldErrors } from "react-hook-form";
|
|
import {
|
|
CustomerEditForm,
|
|
CustomerEditorSkeleton,
|
|
ErrorAlert,
|
|
NotFoundCard,
|
|
} from "../../components";
|
|
import { useCustomerQuery, useUpdateCustomerMutation } from "../../hooks";
|
|
import { useTranslation } from "../../i18n";
|
|
import { CreateCustomerFormData } from "../../schemas";
|
|
|
|
export const CustomerUpdate = () => {
|
|
const customerId = useUrlParamId();
|
|
const { t } = useTranslation();
|
|
const navigate = useNavigate();
|
|
const [isDirty, setIsDirty] = useState(false);
|
|
|
|
// 1) Estado de carga del cliente (query)
|
|
const {
|
|
data: customerData,
|
|
isLoading: isLoadingCustomer,
|
|
isError: isLoadError,
|
|
error: loadError,
|
|
} = useCustomerQuery(customerId, { enabled: !!customerId });
|
|
|
|
// 2) Estado de actualización (mutación)
|
|
const {
|
|
mutate,
|
|
isPending: isUpdating,
|
|
isError: isUpdateError,
|
|
error: updateError,
|
|
} = useUpdateCustomerMutation();
|
|
|
|
// 3) Submit con navegación condicionada por éxito
|
|
const handleSubmit = (formData: CreateCustomerFormData) => {
|
|
mutate(
|
|
{ id: customerId!, data: formData },
|
|
{
|
|
onSuccess(data) {
|
|
setIsDirty(false);
|
|
showSuccessToast(t("pages.update.successTitle"), t("pages.update.successMsg"));
|
|
|
|
// El timeout es para que a React le dé tiempo a procesar
|
|
// el cambio de estado de isDirty / setIsDirty.
|
|
setTimeout(() => {
|
|
navigate("/customers/list", {
|
|
state: { customerId: data.id, isNew: true },
|
|
replace: true,
|
|
});
|
|
}, 0);
|
|
},
|
|
onError(error) {
|
|
showErrorToast(t("pages.update.errorTitle"), error.message);
|
|
},
|
|
}
|
|
);
|
|
};
|
|
|
|
const handleError = (errors: FieldErrors<CreateCustomerFormData>) => {
|
|
console.error("Errores en el formulario:", errors);
|
|
// Aquí puedes manejar los errores, por ejemplo, mostrar un mensaje al usuario
|
|
};
|
|
|
|
if (isLoadingCustomer) {
|
|
return <CustomerEditorSkeleton />;
|
|
}
|
|
|
|
if (isLoadError) {
|
|
return (
|
|
<>
|
|
<AppBreadcrumb />
|
|
<AppContent>
|
|
<ErrorAlert
|
|
title={t("pages.update.loadErrorTitle", "No se pudo cargar el cliente")}
|
|
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 (!customerData)
|
|
return (
|
|
<>
|
|
<AppBreadcrumb />
|
|
<AppContent>
|
|
<NotFoundCard
|
|
title={t("pages.update.notFoundTitle", "Cliente no encontrado")}
|
|
message={t("pages.update.notFoundMsg", "Revisa el identificador o vuelve al listado.")}
|
|
/>
|
|
</AppContent>
|
|
</>
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<AppBreadcrumb />
|
|
<AppContent>
|
|
<UnsavedChangesProvider isDirty={isDirty}>
|
|
<div className='flex items-center justify-between space-y-4 px-6'>
|
|
<div className='space-y-2'>
|
|
<h2 className='text-2xl font-bold tracking-tight text-balance scroll-m-2'>
|
|
{t("pages.update.title")}
|
|
</h2>
|
|
<p className='text-muted-foreground scroll-m-20 tracking-tight text-balance'>
|
|
{t("pages.update.description")}
|
|
</p>
|
|
</div>
|
|
<FormCommitButtonGroup
|
|
cancel={{
|
|
to: "/customers/list",
|
|
}}
|
|
submit={{
|
|
formId: "customer-create-form",
|
|
disabled: isUpdating,
|
|
isLoading: isUpdating,
|
|
}}
|
|
/>
|
|
</div>
|
|
{/* 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.")
|
|
}
|
|
/>
|
|
)}
|
|
|
|
<div className='flex flex-1 flex-col gap-4 p-4'>
|
|
<CustomerEditForm
|
|
formId={"customer-update-form"} // para que el botón del header pueda hacer submit
|
|
initialValues={customerData}
|
|
onSubmit={handleSubmit}
|
|
onError={handleError}
|
|
onDirtyChange={setIsDirty}
|
|
/>
|
|
</div>
|
|
</UnsavedChangesProvider>
|
|
</AppContent>
|
|
</>
|
|
);
|
|
};
|