diff --git a/modules/core/src/web/components/form/simple-search-input.tsx b/modules/core/src/web/components/form/simple-search-input.tsx index 4e42f456..f13fcb3b 100644 --- a/modules/core/src/web/components/form/simple-search-input.tsx +++ b/modules/core/src/web/components/form/simple-search-input.tsx @@ -16,6 +16,9 @@ type SimpleSearchInputProps = { onSearchChange: (value: string) => void; loading?: boolean; maxHistory?: number; + + placeholder?: string; + autoFocus?: boolean; }; const SEARCH_HISTORY_KEY = "search_history"; @@ -27,6 +30,8 @@ export const SimpleSearchInput = ({ onSearchChange, loading = false, maxHistory = 8, + placeholder, + autoFocus = false, }: SimpleSearchInputProps) => { const { t } = useTranslation(); const [searchValue, setSearchValue] = useState(value); @@ -131,11 +136,14 @@ export const SimpleSearchInput = ({ history.length > 0 && setOpen(true)} onKeyDown={handleKeyDown} - placeholder={t("components.simple_search_input.search_placeholder", "Search...")} + placeholder={ + placeholder || t("components.simple_search_input.search_placeholder", "Search...") + } ref={inputRef} spellCheck={false} value={searchValue} diff --git a/modules/customer-invoices/src/web/proformas/update/adapters/index.ts b/modules/customer-invoices/src/web/proformas/update/adapters/index.ts index 197d88cc..b0e1ab13 100644 --- a/modules/customer-invoices/src/web/proformas/update/adapters/index.ts +++ b/modules/customer-invoices/src/web/proformas/update/adapters/index.ts @@ -1 +1,2 @@ export * from "./proforma-to-proforma-update-form.adapter"; +export * from "./proforma-to-selected-customer.adapter"; diff --git a/modules/customer-invoices/src/web/proformas/update/adapters/proforma-to-selected-customer.adapter.ts b/modules/customer-invoices/src/web/proformas/update/adapters/proforma-to-selected-customer.adapter.ts new file mode 100644 index 00000000..61f55528 --- /dev/null +++ b/modules/customer-invoices/src/web/proformas/update/adapters/proforma-to-selected-customer.adapter.ts @@ -0,0 +1,20 @@ +import type { CustomerSelectionOption } from "@erp/customers/common"; + +import type { Proforma } from "../../shared/entities"; + +export const mapProformaToSelectedCustomer = ( + proforma?: Proforma | null +): CustomerSelectionOption | null => { + if (!proforma?.customerId) { + return null; + } + + return { + id: proforma.customerId, + name: proforma.recipient.name ?? "", + tin: proforma.recipient.tin ?? "", + + languageCode: proforma.languageCode ?? "", + currencyCode: proforma.currencyCode ?? "", + }; +}; diff --git a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts index 5ca7e4ae..9238fe50 100644 --- a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts +++ b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts @@ -1,13 +1,14 @@ import { useHookForm } from "@erp/core/hooks"; +import type { CustomerSelectionOption } from "@erp/customers"; import { showErrorToast, showSuccessToast, showWarningToast } from "@repo/rdx-ui/helpers"; -import { useEffect, useId, useMemo } from "react"; +import { useEffect, useId, useMemo, useState } from "react"; import type { FieldErrors } from "react-hook-form"; import { useTranslation } from "../../../i18n"; import type { UpdateProformaByIdParams } from "../../shared"; import type { Proforma } from "../../shared/entities"; import { useProformaGetQuery, useProformaUpdateMutation } from "../../shared/hooks"; -import { mapProformaToProformaUpdateForm } from "../adapters"; +import { mapProformaToProformaUpdateForm, mapProformaToSelectedCustomer } from "../adapters"; import { type ProformaUpdateForm, ProformaUpdateFormSchema, @@ -63,6 +64,8 @@ export const useUpdateProformaController = ( disabled: isLoading || isUpdating, }); + const [selectedCustomer, setSelectedCustomer] = useState(null); + useEffect(() => { if (!proformaData) return; @@ -70,6 +73,8 @@ export const useUpdateProformaController = ( form.reset(mapProformaToProformaUpdateForm(proformaData), { keepDirty: false, // <-- importante: no marca el form como "dirty" al cargar los datos reales }); + + setSelectedCustomer(mapProformaToSelectedCustomer(proformaData)); }, [proformaData, form]); /** Handlers */ @@ -80,6 +85,27 @@ export const useUpdateProformaController = ( : defaultProformaUpdateForm; form.reset(initialData, { keepDirty: false }); + setSelectedCustomer(mapProformaToSelectedCustomer(proformaData)); + }; + + const setCustomer = (customer: CustomerSelectionOption) => { + setSelectedCustomer(customer); + + form.setValue("customerId", customer.id, { + shouldDirty: true, + shouldTouch: true, + shouldValidate: true, + }); + }; + + const clearCustomer = () => { + setSelectedCustomer(null); + + form.setValue("customerId", "", { + shouldDirty: true, + shouldTouch: true, + shouldValidate: true, + }); }; const submitHandler = form.handleSubmit( @@ -104,6 +130,8 @@ export const useUpdateProformaController = ( keepDirty: false, }); + setSelectedCustomer(mapProformaToSelectedCustomer(proformaData)); + if (options?.successToasts !== false) { showSuccessToast( t("proformas.update.success.title"), @@ -164,6 +192,10 @@ export const useUpdateProformaController = ( isUpdateError, updateError, + selectedCustomer, + setCustomer, + clearCustomer, + // No devolver FormProvider, así el controller es más // flexible y reusable (p.ej. para un modal) // FormProvider, diff --git a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-page-controller.ts b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-page-controller.ts index efa06674..9a3c4a8f 100644 --- a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-page-controller.ts +++ b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-page-controller.ts @@ -1,4 +1,5 @@ import { useUrlParamId } from "@erp/core/hooks"; +import { useCustomerSelectionFlow } from "@erp/customers/common"; import { useUpdateProformaController } from "./use-update-proforma-controller"; @@ -7,7 +8,18 @@ export const useUpdateProformaPageController = () => { const updateCtrl = useUpdateProformaController(proformaId); + const selectCustomerCtrl = useCustomerSelectionFlow({ + defaultLanguageCode: updateCtrl.form.watch("languageCode"), + defaultCurrencyCode: updateCtrl.form.watch("currencyCode"), + onCustomerSelected: (customer) => { + console.log(customer); + alert("cliente seleccionado"); + //updateCtrl.setCustomer(customer); + }, + }); + return { updateCtrl, + selectCustomerCtrl, }; }; diff --git a/modules/customer-invoices/src/web/proformas/update/ui/blocks/index.ts b/modules/customer-invoices/src/web/proformas/update/ui/blocks/index.ts index bded24a4..0472be58 100644 --- a/modules/customer-invoices/src/web/proformas/update/ui/blocks/index.ts +++ b/modules/customer-invoices/src/web/proformas/update/ui/blocks/index.ts @@ -1,4 +1,6 @@ +export * from "./proforma-basic-info-fields"; export * from "./proforma-form-field-shell"; export * from "./proforma-header-fields-card"; export * from "./proforma-header-form-grid"; export * from "./proforma-section-card"; +export * from "./selected-recipient-summary"; diff --git a/modules/customer-invoices/src/web/proformas/update/ui/blocks/selected-recipient-summary.tsx b/modules/customer-invoices/src/web/proformas/update/ui/blocks/selected-recipient-summary.tsx new file mode 100644 index 00000000..a9cbb0b0 --- /dev/null +++ b/modules/customer-invoices/src/web/proformas/update/ui/blocks/selected-recipient-summary.tsx @@ -0,0 +1,55 @@ +import type { CustomerSelectionOption } from "@erp/customers"; +import { Button } from "@repo/shadcn-ui/components"; + +import { useTranslation } from "../../../../i18n"; + +type SelectedRecipientSummaryProps = { + recipient?: CustomerSelectionOption | null; + onChangeClick: () => void; + onCreateClick?: () => void; +}; + +export const SelectedRecipientSummary = ({ + recipient, + onChangeClick, + onCreateClick, +}: SelectedRecipientSummaryProps) => { + const { t } = useTranslation(); + + return ( +
+
+
+

{t("customers.selected_customer.title", "Cliente")}

+ + {recipient ? ( +
+

{recipient.name}

+ {recipient.tin ? ( +

{recipient.tin}

+ ) : null} +
+ ) : ( +

+ {t("customers.selected_customer.empty", "No hay ningún cliente seleccionado")} +

+ )} +
+ +
+ {onCreateClick ? ( + + ) : null} + + +
+
+
+ ); +}; diff --git a/modules/customer-invoices/src/web/proformas/update/ui/editors/index.ts b/modules/customer-invoices/src/web/proformas/update/ui/editors/index.ts index 8f371dbf..270e132b 100644 --- a/modules/customer-invoices/src/web/proformas/update/ui/editors/index.ts +++ b/modules/customer-invoices/src/web/proformas/update/ui/editors/index.ts @@ -1,2 +1,2 @@ export * from "./proforma-update-editor-form"; -export * from "./proforma-update-header-editor"; +export * from "./proforma-update-recipient-editor"; diff --git a/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-editor-form.tsx b/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-editor-form.tsx index d4dd9cdf..2c5880ae 100644 --- a/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-editor-form.tsx +++ b/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-editor-form.tsx @@ -1,20 +1,28 @@ // modules/customer-invoices/src/web/proformas/update/ui/blocks/proforma-update-editor.tsx +import type { CustomerSelectionOption } from "@erp/customers"; import { Button } from "@repo/shadcn-ui/components"; import { cn } from "@repo/shadcn-ui/lib/utils"; -import { ProformaUpdateHeaderEditor } from "."; +import { ProformaUpdateRecipientEditor } from "."; import { useTranslation } from "../../../../i18n"; import type { Proforma } from "../../../shared/entities"; import { ProformaHeaderFieldsCard } from "../blocks/proforma-header-fields-card"; +import { ProformaUpdateHeaderEditor } from "./proforma-update-header-editor"; + type ProformaUpdateEditorProps = { formId: string; proforma?: Proforma; isSubmitting: boolean; onSubmit: React.FormEventHandler; onReset: () => void; + + selectedCustomer?: CustomerSelectionOption | null; + onChangeCustomerClick: () => void; + onCreateCustomerClick: () => void; + className?: string; }; @@ -23,6 +31,9 @@ export const ProformaUpdateEditorForm = ({ isSubmitting, onSubmit, onReset, + selectedCustomer, + onChangeCustomerClick, + onCreateCustomerClick, className, }: ProformaUpdateEditorProps) => { const { t } = useTranslation(); @@ -30,16 +41,13 @@ export const ProformaUpdateEditorForm = ({ return (
- + +
diff --git a/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-header-editor.tsx b/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-header-editor.tsx index 0369e115..632b62de 100644 --- a/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-header-editor.tsx +++ b/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-header-editor.tsx @@ -1,355 +1,63 @@ import { DatePickerField, SelectField, TextField } from "@repo/rdx-ui/components"; -import { - Input, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, - Textarea, -} from "@repo/shadcn-ui/components"; -import { Controller, useFormContext } from "react-hook-form"; import { useTranslation } from "../../../../i18n"; -import type { ProformaUpdateForm } from "../../entities"; -import { ProformaFormFieldShell, ProformaHeaderFormGrid, ProformaSectionCard } from "../blocks"; - -interface SelectOption { - value: string; - label: string; -} +import { ProformaHeaderFormGrid, ProformaSectionCard } from "../blocks"; interface ProformaUpdateHeaderEditorProps { - statusOptions: SelectOption[]; - serieOptions: SelectOption[]; - customerOptions: SelectOption[]; - currencyOptions: SelectOption[]; - paymentMethodOptions: SelectOption[]; - salesPersonOptions: SelectOption[]; - warehouseOptions: SelectOption[]; - priceListOptions: SelectOption[]; disabled?: boolean; readOnly?: boolean; } export const ProformaUpdateHeaderEditor = ({ - statusOptions, - serieOptions, - customerOptions, - currencyOptions, - paymentMethodOptions, - salesPersonOptions, - warehouseOptions, - priceListOptions, disabled = false, readOnly = false, }: ProformaUpdateHeaderEditorProps) => { const { t } = useTranslation(); - const { - register, - control, - formState: { errors }, - } = useFormContext(); - - const isFieldLocked = disabled || readOnly; - return ( -
- - - + + + - + - + - + - - - - - - - - ( - - )} - /> - - - - - - - - - - - - - - - - ( - - )} - /> - - - - ( - - )} - /> - - - - - - - - ( - - )} - /> - - - - ( - - )} - /> - - - - ( - - )} - /> - - - - - - - - - - - -