.
This commit is contained in:
parent
ff6905b845
commit
bcf719ed4f
@ -1,142 +0,0 @@
|
||||
import { formHasAnyDirty, pickFormDirtyValues } from "@erp/core/client";
|
||||
import { useHookForm } from "@erp/core/hooks";
|
||||
import { showErrorToast, showSuccessToast, showWarningToast } from "@repo/rdx-ui/helpers";
|
||||
import { useEffect, useId, useMemo } from "react";
|
||||
import { type FieldErrors, FormProvider } from "react-hook-form";
|
||||
|
||||
import { useTranslation } from "../../../i18n";
|
||||
import type { Proforma } from "../../api";
|
||||
import { type ProformaFormData, ProformaFormSchema, defaultProformaFormData } from "../types";
|
||||
|
||||
export interface UseProformaUpdateControllerOptions {
|
||||
onUpdated?(updated: Proforma): void;
|
||||
successToasts?: boolean; // mostrar o no toast automáticcamente
|
||||
|
||||
onError?(error: Error, patchData: ReturnType<typeof pickFormDirtyValues>): void;
|
||||
errorToasts?: boolean; // mostrar o no toast automáticcamente
|
||||
}
|
||||
|
||||
export const useProformaUpdateController = (
|
||||
proformaId?: string,
|
||||
options?: UseProformaUpdateControllerOptions
|
||||
) => {
|
||||
const { t } = useTranslation();
|
||||
const formId = useId(); // id único por instancia
|
||||
|
||||
// 1) Estado de carga del cliente (query)
|
||||
const {
|
||||
data: proformaData,
|
||||
isLoading,
|
||||
isError: isLoadError,
|
||||
error: loadError,
|
||||
} = useProformaGetQuery(proformaId, { enabled: Boolean(proformaId) });
|
||||
|
||||
// 2) Estado de creación (mutación)
|
||||
const {
|
||||
mutateAsync,
|
||||
isPending: isUpdating,
|
||||
isError: isUpdateError,
|
||||
error: updateError,
|
||||
} = useProformaUpdateMutation();
|
||||
|
||||
const initialValues = useMemo(() => proformaData ?? defaultProformaFormData, [proformaData]);
|
||||
|
||||
// 3) Form hook
|
||||
const form = useHookForm<ProformaFormData>({
|
||||
resolverSchema: ProformaFormSchema,
|
||||
initialValues,
|
||||
disabled: isLoading || isUpdating,
|
||||
});
|
||||
|
||||
/** Reiniciar el form al recibir datos */
|
||||
useEffect(() => {
|
||||
// keepDirty = false -> deja el formulario sin cambios sin tener que esperar al siguiente render.
|
||||
if (proformaData) form.reset(proformaData, { keepDirty: false });
|
||||
}, [proformaData, form]);
|
||||
|
||||
/** Handlers */
|
||||
|
||||
const resetForm = () => form.reset(proformaData ?? defaultProformaFormData);
|
||||
|
||||
// Versión sincronizada
|
||||
const submitHandler = form.handleSubmit(
|
||||
async (formData) => {
|
||||
if (!proformaId) {
|
||||
showErrorToast(t("pages.update.error.title"), "Falta el ID de la proforma");
|
||||
return;
|
||||
}
|
||||
|
||||
const { dirtyFields } = form.formState;
|
||||
if (!formHasAnyDirty(dirtyFields)) {
|
||||
showWarningToast(t("pages.update.error.no_changes"), "No hay cambios para guardar");
|
||||
return;
|
||||
}
|
||||
|
||||
const patchData = pickFormDirtyValues(formData, dirtyFields);
|
||||
const previousData = proformaData;
|
||||
|
||||
try {
|
||||
// Enviamos cambios al servidor
|
||||
const updated = await mutateAsync({ id: proformaId, data: patchData });
|
||||
|
||||
// Ha ido bien -> actualizamos form con datos reales
|
||||
// keepDirty = false -> deja el formulario sin cambios sin tener que esperar al siguiente render.
|
||||
form.reset(updated, { keepDirty: false });
|
||||
|
||||
if (options?.successToasts !== false) {
|
||||
showSuccessToast(
|
||||
t("pages.update.success.title", "Proforma modificada"),
|
||||
t("pages.update.success.message", "Se ha modificado correctamente.")
|
||||
);
|
||||
}
|
||||
options?.onUpdated?.(updated);
|
||||
} catch (error: any) {
|
||||
// Algo ha fallado -> revertimos cambios
|
||||
form.reset(previousData ?? defaultProformaFormData);
|
||||
if (options?.errorToasts !== false) {
|
||||
showErrorToast(t("pages.update.error.title"), error.message);
|
||||
}
|
||||
options?.onError?.(error, patchData);
|
||||
}
|
||||
},
|
||||
(errors: FieldErrors<ProformaFormData>) => {
|
||||
const firstKey = Object.keys(errors)[0] as keyof ProformaFormData | undefined;
|
||||
if (firstKey) document.querySelector<HTMLElement>(`[name="${String(firstKey)}"]`)?.focus();
|
||||
|
||||
showWarningToast(
|
||||
t("forms.validation.title", "Revisa los campos"),
|
||||
t("forms.validation.message", "Hay errores de validación en el formulario.")
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// Evento onSubmit ya preparado para el <form>
|
||||
const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.stopPropagation(); // <-- evita que el submit se propage por los padre en el árbol DOM
|
||||
submitHandler(event);
|
||||
};
|
||||
|
||||
return {
|
||||
// form
|
||||
form,
|
||||
formId,
|
||||
|
||||
// handlers del form
|
||||
onSubmit,
|
||||
resetForm,
|
||||
|
||||
// carga de datos
|
||||
proformaData,
|
||||
isLoading,
|
||||
isLoadError,
|
||||
loadError,
|
||||
|
||||
// mutation
|
||||
isUpdating,
|
||||
isUpdateError,
|
||||
updateError,
|
||||
|
||||
// Por comodidad
|
||||
FormProvider,
|
||||
};
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user