import { FormMoneyField, LoadingOverlay, SubmitButton } from "@/components"; import { calculateItemTotals } from "@/lib/calc"; import { useGetIdentity } from "@/lib/hooks"; import { useUrlId } from "@/lib/hooks/useUrlId"; import { Badge, Button, Form, Tabs, TabsContent, TabsList, TabsTrigger } from "@/ui"; import { IUpdateQuote_Request_DTO, MoneyValue } from "@shared/contexts"; import { t } from "i18next"; import { ChevronLeftIcon } from "lucide-react"; import { useEffect, useState } from "react"; import { SubmitHandler, useForm } from "react-hook-form"; import { QuoteDetailsCardEditor, QuoteGeneralCardEditor } from "./components/editors"; import { useQuotes } from "./hooks"; // simple typesafe helperfunction type EndsWith = T extends `${infer f}${b}` ? T : never; const endsWith = (str: T, prefix: b): str is EndsWith => str.endsWith(prefix); interface QuoteDataForm extends IUpdateQuote_Request_DTO { /*status: string; date: string; reference: string; customer_information: string; lang_code: string; currency_code: string; payment_method: string; notes: string; validity: string; discount: IPercentage; subtotal: IMoney; items: { quantity: IQuantity; description: string; retail_price: IMoney; price: IMoney; discount: IPercentage; total: IMoney; }[];*/ } // eslint-disable-next-line @typescript-eslint/no-unused-vars export const QuoteEdit = () => { const [loading, setLoading] = useState(false); const quoteId = useUrlId(); const { data: userIdentity } = useGetIdentity(); const { useOne, useUpdate } = useQuotes(); const { data, status } = useOne(quoteId); const { mutate } = useUpdate(quoteId); const form = useForm({ mode: "onBlur", values: data, defaultValues: { date: "", reference: "", customer_information: "", lang_code: "", currency_code: "", payment_method: "", notes: "", validity: "", subtotal: "", items: [], }, }); const onSubmit: SubmitHandler = async (data) => { console.debug(JSON.stringify(data)); try { setLoading(true); // Transformación del form -> typo de request mutate(data, { onError: (error) => { alert(error); }, //onSettled: () => {}, onSuccess: () => { alert("guardado"); }, }); } finally { setLoading(false); } }; const { watch, getValues, setValue } = form; useEffect(() => { const { unsubscribe } = watch((_, { name, type }) => { const value = getValues(); console.debug({ name, type }); if (name) { if (name === "items") { const { items } = value; let quoteSubtotal = MoneyValue.create().object; // Recálculo líneas items.map((item, index) => { const itemTotals = calculateItemTotals(item); quoteSubtotal = quoteSubtotal.add(itemTotals.total); setValue(`items.${index}.price`, itemTotals.price.toObject()); setValue(`items.${index}.total`, itemTotals.total.toObject()); }); console.log(quoteSubtotal.toFormat()); // Recálculo completo setValue("subtotal", quoteSubtotal.toObject()); } if ( endsWith(name, "quantity") || endsWith(name, "retail_price") || endsWith(name, "discount") ) { const { items } = value; const [, indexString, fieldName] = String(name).split("."); const index = parseInt(indexString); const itemTotals = calculateItemTotals(items[index]); setValue(`items.${index}.price`, itemTotals.price.toObject()); setValue(`items.${index}.total`, itemTotals.total.toObject()); // Recálculo completo } } }); return () => unsubscribe(); }, [watch, getValues, setValue]); if (status !== "success") { return ; } return (

{t("quotes.edit.title")}

{data.status}
{t("common.save")}
{t("quotes.create.tabs.general")} {t("quotes.create.tabs.items")} {t("quotes.create.tabs.history")}
); };