Facturas de cliente

This commit is contained in:
David Arranz 2025-07-18 13:24:03 +02:00
parent 0e59a18cbb
commit 0e6ecaad22
5 changed files with 37 additions and 39 deletions

View File

@ -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,
}));
}

View File

@ -1,3 +1,4 @@
export * from "./axios";
export * from "./build-text-filters";
export * from "./datasource-context";
export * from "./datasource.interface";

View File

@ -0,0 +1 @@
export * from "./dto";

View File

@ -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<Customer>[] = [
{
@ -36,19 +32,17 @@ const columns: TableColumn<Customer>[] = [
{
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) => (
<span className={row.status === "Activo" ? "text-green-600" : "text-gray-400"}>
{row.status}
</span>
),
sortable: false,
},
];
@ -128,30 +122,19 @@ async function fetchClientes(search: string): Promise<Customer[]> {
}
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<Customer | undefined>(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) => (
<DataTable
@ -218,7 +203,7 @@ export const ClientSelector = () => {
pagination
paginationServer
paginationPerPage={perPage}
paginationTotalRows={filtered.length}
paginationTotalRows={data?.total ?? 0}
onChangePage={(p) => setPage(p)}
highlightOnHover
pointerOnHover

View File

@ -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<ListCustomersResultDTO, Error> => {
const dataSource = useDataSource();
const keys = useQueryKey();