From 0e6ecaad229b0dcca39b9ffdfb1dca0c20ef4238 Mon Sep 17 00:00:00 2001 From: david Date: Fri, 18 Jul 2025 13:24:03 +0200 Subject: [PATCH] Facturas de cliente --- .../lib/data-source/build-text-filters.tsx | 13 +++++ modules/core/src/web/lib/data-source/index.ts | 1 + modules/customers/src/common/index.ts | 1 + .../src/web/components/client-selector.tsx | 55 +++++++------------ .../src/web/hooks/use-customers-query.tsx | 6 +- 5 files changed, 37 insertions(+), 39 deletions(-) create mode 100644 modules/core/src/web/lib/data-source/build-text-filters.tsx create mode 100644 modules/customers/src/common/index.ts diff --git a/modules/core/src/web/lib/data-source/build-text-filters.tsx b/modules/core/src/web/lib/data-source/build-text-filters.tsx new file mode 100644 index 00000000..c682dc96 --- /dev/null +++ b/modules/core/src/web/lib/data-source/build-text-filters.tsx @@ -0,0 +1,13 @@ +/** + * Utilidad para construir filtros de texto tipo CONTAINS + * para los campos especificados. + */ +export function buildTextFilters(fields: string[], value: string) { + if (!value.trim()) return []; + + return fields.map((field) => ({ + field, + operator: "CONTAINS" as const, + value, + })); +} diff --git a/modules/core/src/web/lib/data-source/index.ts b/modules/core/src/web/lib/data-source/index.ts index 660d38b6..bd310951 100644 --- a/modules/core/src/web/lib/data-source/index.ts +++ b/modules/core/src/web/lib/data-source/index.ts @@ -1,3 +1,4 @@ export * from "./axios"; +export * from "./build-text-filters"; export * from "./datasource-context"; export * from "./datasource.interface"; diff --git a/modules/customers/src/common/index.ts b/modules/customers/src/common/index.ts new file mode 100644 index 00000000..0392b1b4 --- /dev/null +++ b/modules/customers/src/common/index.ts @@ -0,0 +1 @@ +export * from "./dto"; diff --git a/modules/customers/src/web/components/client-selector.tsx b/modules/customers/src/web/components/client-selector.tsx index d9d2a8ab..d63ce994 100644 --- a/modules/customers/src/web/components/client-selector.tsx +++ b/modules/customers/src/web/components/client-selector.tsx @@ -2,6 +2,8 @@ import { LookupDialog } from "@repo/rdx-ui/components"; import DataTable, { TableColumn } from "react-data-table-component"; import { useDebounce } from "use-debounce"; +import { buildTextFilters } from "@erp/core/client"; +import { ListCustomersResultDTO } from "@erp/customer-invoices/common/dto"; import { Badge, Button, @@ -19,13 +21,7 @@ import { Building, Calendar, Mail, MapPin, Phone, Plus, User } from "lucide-reac import { useState } from "react"; import { useCustomersQuery } from "../hooks"; -type Customer = { - id: string; - name: string; - email: string; - company: string; - status: string; -}; +type Customer = ListCustomersResultDTO["items"][number]; const columns: TableColumn[] = [ { @@ -36,19 +32,17 @@ const columns: TableColumn[] = [ { name: "Email", selector: (row) => row.email, + sortable: true, }, { name: "Empresa", - selector: (row) => row.company, + selector: (row) => row.trade_name ?? row.metadata?.company_name ?? "-", + sortable: false, }, { name: "Estado", selector: (row) => row.status, - cell: (row) => ( - - {row.status} - - ), + sortable: false, }, ]; @@ -128,30 +122,19 @@ async function fetchClientes(search: string): Promise { } export const ClientSelector = () => { + const [isCreateOpen, setIsCreateOpen] = useState(false); const [open, setOpen] = useState(false); const [search, setSearch] = useState(""); const [pageNumber, setPageNumber] = useState(1); const [pageSize] = useState(10); - const [selectedCustomer, setSelectedCustomer] = useState(undefined); + const [selectedCustomer, setSelectedCustomer] = useState(undefined); const [debouncedSearch] = useDebounce(search, 400); - const paginated = filtered.slice((pageNumber - 1) * pageSize, pageNumber * pageSize); - const { data, isLoading, isError, error, refetch } = useCustomersQuery({ - filters: [ - { - field: "name", - operator: "CONTAINS", - value: debouncedSearch, - }, - { - field: "trade_name", - operator: "CONTAINS", - value: debouncedSearch, - }, - ], - pageNumber, + const { data, isLoading, isError, refetch } = useCustomersQuery({ + filters: buildTextFilters(["name", "email", "trade_name"], debouncedSearch), pageSize, + pageNumber, }); return ( @@ -189,13 +172,16 @@ export const ClientSelector = () => { open={open} onOpenChange={setOpen} items={data?.items ?? []} + totalItems={data?.total_items ?? 0} search={search} onSearchChange={setSearch} isLoading={isLoading} + isError={isError} + refetch={refetch} title='Seleccionar cliente' description='Busca un cliente por nombre, email o empresa' - onSelect={(item) => { - setSelectedCustomer(item); + onSelect={(customer) => { + setSelectedCustomer(customer); setOpen(false); }} onCreate={() => { @@ -203,9 +189,8 @@ export const ClientSelector = () => { console.log("Crear nuevo cliente"); }} page={pageNumber} - perPage={perPage} - totalItems={filtered.length} - onPageChange={setPage} + perPage={pageSize} + onPageChange={setPageNumber} renderItem={() => null} // No se usa con DataTable renderContainer={(items) => ( { pagination paginationServer paginationPerPage={perPage} - paginationTotalRows={filtered.length} + paginationTotalRows={data?.total ?? 0} onChangePage={(p) => setPage(p)} highlightOnHover pointerOnHover diff --git a/modules/customers/src/web/hooks/use-customers-query.tsx b/modules/customers/src/web/hooks/use-customers-query.tsx index f2f98441..720f29e6 100644 --- a/modules/customers/src/web/hooks/use-customers-query.tsx +++ b/modules/customers/src/web/hooks/use-customers-query.tsx @@ -1,12 +1,10 @@ import { useDataSource, useQueryKey } from "@erp/core/client"; -import { ListCustomersQueryDTO, ListCustomersResultDTO } from "@erp/customer-invoices/common/dto"; +import { ListCustomersQueryDTO, ListCustomersResultDTO } from "@erp/customers"; import { UseQueryResult, useQuery } from "@tanstack/react-query"; -type UseCustomersQueryParams = ListCustomersQueryDTO; - // Obtener clientes export const useCustomersQuery = ( - params: UseCustomersQueryParams + params: ListCustomersQueryDTO ): UseQueryResult => { const dataSource = useDataSource(); const keys = useQueryKey();