diff --git a/modules/customer-invoices/src/web/customer-invoice-routes.tsx b/modules/customer-invoices/src/web/customer-invoice-routes.tsx index 956d1466..1ebfef71 100644 --- a/modules/customer-invoices/src/web/customer-invoice-routes.tsx +++ b/modules/customer-invoices/src/web/customer-invoice-routes.tsx @@ -15,7 +15,7 @@ const ProformasListPage = lazy(() => ); const IssuedInvoiceListPage = lazy(() => - import("./issued-invoices/pages").then((m) => ({ default: m.IssuedInvoiceListPage })) + import("./issued-invoices/list").then((m) => ({ default: m.IssuedInvoiceListPage })) ); /*const CustomerInvoiceAdd = lazy(() => diff --git a/modules/customer-invoices/src/web/issued-invoices/download-pdf/api/download-invoice-pdf.api.ts b/modules/customer-invoices/src/web/issued-invoices/download-pdf/api/download-invoice-pdf.api.ts new file mode 100644 index 00000000..ef728c68 --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/download-pdf/api/download-invoice-pdf.api.ts @@ -0,0 +1,14 @@ +import type { IDataSource } from "@erp/core/client"; + +export async function downloadInvoicePDFApi( + dataSource: IDataSource, + invoiceId: string, + params?: Record +): Promise { + return dataSource.custom({ + ...params, + path: `issued-invoices/${invoiceId}/report`, + method: "get", + responseType: "blob", + }); +} diff --git a/modules/customer-invoices/src/web/issued-invoices/download-pdf/api/index.ts b/modules/customer-invoices/src/web/issued-invoices/download-pdf/api/index.ts new file mode 100644 index 00000000..e7c5afdc --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/download-pdf/api/index.ts @@ -0,0 +1 @@ +export * from "./download-invoice-pdf.api"; diff --git a/modules/customer-invoices/src/web/issued-invoices/download-pdf/controller/index.ts b/modules/customer-invoices/src/web/issued-invoices/download-pdf/controller/index.ts new file mode 100644 index 00000000..a7d222a3 --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/download-pdf/controller/index.ts @@ -0,0 +1 @@ +export * from "./use-download-invoice-pdf.controller"; diff --git a/modules/customer-invoices/src/web/issued-invoices/download-pdf/controller/use-download-invoice-pdf.controller.ts b/modules/customer-invoices/src/web/issued-invoices/download-pdf/controller/use-download-invoice-pdf.controller.ts new file mode 100644 index 00000000..18e4bc8c --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/download-pdf/controller/use-download-invoice-pdf.controller.ts @@ -0,0 +1,53 @@ +import { showErrorToast, showSuccessToast } from "@repo/rdx-ui/helpers"; +import * as React from "react"; + +import { useDownloadInvoicePDFQuery } from "../hooks"; + +interface PendingDownload { + id: string; + invoice_number: string; +} + +export function useDownloadInvoicePDFController() { + const [pending, setPending] = React.useState(null); + + const { data, isFetching, refetch } = useDownloadInvoicePDFQuery(pending?.id); + + // Efecto: cuando hay blob + pending, disparamos la descarga + React.useEffect(() => { + if (!(pending && data)) return; + + const blob = data; + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = `invoice-${pending.invoice_number}.pdf`; + a.click(); + URL.revokeObjectURL(url); + + showSuccessToast( + "Descarga iniciada", + `La factura ${pending.invoice_number} se está descargando.` + ); + + setPending(null); + }, [data, pending]); + + const download = (id: string, invoice_number: string) => { + setPending({ id, invoice_number }); + + // refetch se dispara en un efecto, o aquí si prefieres: + refetch().catch((err) => { + showErrorToast( + "Error al descargar", + err instanceof Error ? err.message : "Error desconocido" + ); + setPending(null); + }); + }; + + return { + download, // (id, reference) => void + isLoading: isFetching, + }; +} diff --git a/modules/customer-invoices/src/web/issued-invoices/download-pdf/hooks/index.ts b/modules/customer-invoices/src/web/issued-invoices/download-pdf/hooks/index.ts new file mode 100644 index 00000000..fba7aefc --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/download-pdf/hooks/index.ts @@ -0,0 +1 @@ +export * from "./use-download-invoice-pdf-query"; diff --git a/modules/customer-invoices/src/web/issued-invoices/download-pdf/hooks/use-download-invoice-pdf-query.ts b/modules/customer-invoices/src/web/issued-invoices/download-pdf/hooks/use-download-invoice-pdf-query.ts new file mode 100644 index 00000000..0bef7f2d --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/download-pdf/hooks/use-download-invoice-pdf-query.ts @@ -0,0 +1,55 @@ +// features/invoices/view-pdf/hooks/use-download-invoice-pdf.ts + +import { useDataSource } from "@erp/core/hooks"; +import { type QueryKey, useQuery } from "@tanstack/react-query"; + +import { downloadInvoicePDFApi } from "../api"; + +export const ISSUED_INVOICE_QUERY_KEY = (id: string): QueryKey => ["issued_invoice", id] as const; + +type DownloadInvoicePDFOptions = { + enabled?: boolean; +}; + +export function useDownloadInvoicePDFQuery( + invoiceId?: string, + options?: DownloadInvoicePDFOptions +) { + const dataSource = useDataSource(); + const enabled = (options?.enabled ?? true) && !!invoiceId; + + return useQuery({ + queryKey: ISSUED_INVOICE_QUERY_KEY(invoiceId ?? "unknown"), + queryFn: async (context) => { + if (!invoiceId) throw new Error("invoiceId is required"); + + const { signal } = context; + return await downloadInvoicePDFApi(dataSource, invoiceId, { + signal, + }); + }, + enabled, + staleTime: 0, + refetchOnWindowFocus: false, + }); +} + +/* + export function useQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey + > + + TQueryFnData: the type returned from the queryFn. + TError: the type of Errors to expect from the queryFn. + TData: the type our data property will eventually have. + Only relevant if you use the select option, + because then the data property can be different + from what the queryFn returns. + Otherwise, it will default to whatever the queryFn returns. + TQueryKey: the type of our queryKey, only relevant + if you use the queryKey that is passed to your queryFn. + +*/ diff --git a/modules/customer-invoices/src/web/issued-invoices/adapters/index.ts b/modules/customer-invoices/src/web/issued-invoices/list/adapters/index.ts similarity index 100% rename from modules/customer-invoices/src/web/issued-invoices/adapters/index.ts rename to modules/customer-invoices/src/web/issued-invoices/list/adapters/index.ts diff --git a/modules/customer-invoices/src/web/issued-invoices/adapters/issued-invoice-summary-dto.adapter.ts b/modules/customer-invoices/src/web/issued-invoices/list/adapters/issued-invoice-summary-dto.adapter.ts similarity index 98% rename from modules/customer-invoices/src/web/issued-invoices/adapters/issued-invoice-summary-dto.adapter.ts rename to modules/customer-invoices/src/web/issued-invoices/list/adapters/issued-invoice-summary-dto.adapter.ts index a1356b7e..df2eb0a1 100644 --- a/modules/customer-invoices/src/web/issued-invoices/adapters/issued-invoice-summary-dto.adapter.ts +++ b/modules/customer-invoices/src/web/issued-invoices/list/adapters/issued-invoice-summary-dto.adapter.ts @@ -4,13 +4,14 @@ import type { IssuedInvoiceSummaryData, IssuedInvoiceSummaryPage, IssuedInvoiceSummaryPageData, -} from "../schema"; +} from "../../types"; /** * Convierte el DTO completo de API a datos numéricos para el formulario. */ export const IssuedInvoiceSummaryDtoAdapter = { fromDto(pageDto: IssuedInvoiceSummaryPage, context?: unknown): IssuedInvoiceSummaryPageData { + console.log(pageDto); return { ...pageDto, items: pageDto.items.map( diff --git a/modules/customer-invoices/src/web/issued-invoices/list/api/get-issued-invoice-list.api.ts b/modules/customer-invoices/src/web/issued-invoices/list/api/get-issued-invoice-list.api.ts new file mode 100644 index 00000000..c8f0ad6a --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/api/get-issued-invoice-list.api.ts @@ -0,0 +1,18 @@ +import type { CriteriaDTO } from "@erp/core"; +import type { IDataSource } from "@erp/core/client"; + +import type { IssuedInvoiceSummaryPage } from "../../types"; + +export async function getIssuedInvoiceListApi( + dataSource: IDataSource, + signal: AbortSignal, + criteria: CriteriaDTO +) { + const response = dataSource.getList("issued-invoices", { + signal, + ...criteria, + }); + + //return mapIssuedInvoiceList(raw); + return response; +} diff --git a/modules/customer-invoices/src/web/issued-invoices/list/api/index.ts b/modules/customer-invoices/src/web/issued-invoices/list/api/index.ts new file mode 100644 index 00000000..3a619aac --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/api/index.ts @@ -0,0 +1 @@ +export * from "./get-issued-invoice-list.api"; diff --git a/modules/customer-invoices/src/web/issued-invoices/list/controllers/index.ts b/modules/customer-invoices/src/web/issued-invoices/list/controllers/index.ts new file mode 100644 index 00000000..89256bbc --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/controllers/index.ts @@ -0,0 +1,2 @@ +export * from "./use-issued-invoice-list.controller"; +export * from "./use-issued-invoice-list-page.controller.ts"; diff --git a/modules/customer-invoices/src/web/issued-invoices/list/controllers/use-issued-invoice-list-page.controller.ts.ts b/modules/customer-invoices/src/web/issued-invoices/list/controllers/use-issued-invoice-list-page.controller.ts.ts new file mode 100644 index 00000000..ec6e8757 --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/controllers/use-issued-invoice-list-page.controller.ts.ts @@ -0,0 +1,24 @@ +import React from "react"; + +import { useDownloadInvoicePDFController } from "../../download-pdf/controller"; +import type { IssuedInvoiceSummaryData } from "../../types"; + +import { useIssuedInvoiceListController } from "./use-issued-invoice-list.controller"; + +export function useIssuedInvoiceListPageController() { + const listCtrl = useIssuedInvoiceListController(); + const downloadPDFCtrl = useDownloadInvoicePDFController(); + + const handleDownloadPDF = React.useCallback( + (issuedInvoice: IssuedInvoiceSummaryData) => { + downloadPDFCtrl.download(issuedInvoice.id, issuedInvoice.invoice_number); + }, + [downloadPDFCtrl] + ); + + return { + listCtrl, + + handleDownloadPDF, + }; +} diff --git a/modules/customer-invoices/src/web/issued-invoices/list/controllers/use-issued-invoice-list.controller.ts b/modules/customer-invoices/src/web/issued-invoices/list/controllers/use-issued-invoice-list.controller.ts new file mode 100644 index 00000000..843701f9 --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/controllers/use-issued-invoice-list.controller.ts @@ -0,0 +1,51 @@ +import type { CriteriaDTO } from "@erp/core"; +import { useDebounce } from "@repo/rdx-ui/components"; +import { useMemo, useState } from "react"; + +import { IssuedInvoiceSummaryDtoAdapter } from "../adapters"; +import { useIssuedInvoiceListQuery } from "../hooks"; + +export const useIssuedInvoiceListController = () => { + const [pageIndex, setPageIndex] = useState(0); + const [pageSize, setPageSize] = useState(10); + const [search, setSearch] = useState(""); + const [status, setStatus] = useState("all"); + + const debouncedQ = useDebounce(search, 300); + + const criteria = useMemo(() => { + const baseFilters = + status !== "all" ? [{ field: "status", operator: "CONTAINS", value: status }] : []; + + return { + q: debouncedQ || "", + pageSize, + pageNumber: pageIndex, + order: "desc", + orderBy: "invoice_date", + filters: baseFilters, + }; + }, [pageSize, pageIndex, debouncedQ, status]); + + const query = useIssuedInvoiceListQuery({ criteria }); + const data = useMemo( + () => (query.data ? IssuedInvoiceSummaryDtoAdapter.fromDto(query.data) : undefined), + [query.data] + ); + + const setSearchValue = (value: string) => setSearch(value.trim().replace(/\s+/g, " ")); + + const setStatusFilter = (newStatus: string) => setStatus(newStatus); + + return { + ...query, + data, + pageIndex, + pageSize, + search, + setPageIndex, + setPageSize, + setSearchValue, + setStatusFilter, + }; +}; diff --git a/modules/customer-invoices/src/web/issued-invoices/list/hooks/index.ts b/modules/customer-invoices/src/web/issued-invoices/list/hooks/index.ts new file mode 100644 index 00000000..6903c330 --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/hooks/index.ts @@ -0,0 +1 @@ +export * from "./use-issued-invoice-list-query"; diff --git a/modules/customer-invoices/src/web/issued-invoices/list/hooks/use-issued-invoice-list-query.ts b/modules/customer-invoices/src/web/issued-invoices/list/hooks/use-issued-invoice-list-query.ts new file mode 100644 index 00000000..a7ec9c2f --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/hooks/use-issued-invoice-list-query.ts @@ -0,0 +1,38 @@ +import type { CriteriaDTO } from "@erp/core"; +import { useDataSource } from "@erp/core/hooks"; +import { INITIAL_PAGE_INDEX, INITIAL_PAGE_SIZE } from "@repo/rdx-criteria"; +import { type DefaultError, type QueryKey, useQuery } from "@tanstack/react-query"; + +import type { IssuedInvoiceSummaryPage } from "../../types"; +import { getIssuedInvoiceListApi } from "../api"; + +export const ISSUED_INVOICES_QUERY_KEY = (criteria?: CriteriaDTO): QueryKey => [ + "issued_invoices", + { + pageNumber: criteria?.pageNumber ?? INITIAL_PAGE_INDEX, + pageSize: criteria?.pageSize ?? INITIAL_PAGE_SIZE, + q: criteria?.q ?? "", + filters: criteria?.filters ?? [], + orderBy: criteria?.orderBy ?? "", + order: criteria?.order ?? "", + }, +]; + +type IssuedInvoicesQueryOptions = { + enabled?: boolean; + criteria?: CriteriaDTO; +}; + +// Obtener todas las facturas +export const useIssuedInvoiceListQuery = (options?: IssuedInvoicesQueryOptions) => { + const dataSource = useDataSource(); + const enabled = options?.enabled ?? true; + const criteria = options?.criteria ?? {}; + + return useQuery({ + queryKey: ISSUED_INVOICES_QUERY_KEY(criteria), + queryFn: async ({ signal }) => getIssuedInvoiceListApi(dataSource, signal, criteria), + enabled, + placeholderData: (previousData, _previousQuery) => previousData, // Mantener datos previos mientras se carga nueva datos (antiguo `keepPreviousData`) + }); +}; diff --git a/modules/customer-invoices/src/web/issued-invoices/list/index.ts b/modules/customer-invoices/src/web/issued-invoices/list/index.ts new file mode 100644 index 00000000..4aedf593 --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/index.ts @@ -0,0 +1 @@ +export * from "./ui"; diff --git a/modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/index.ts b/modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/index.ts new file mode 100644 index 00000000..096a6e62 --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/index.ts @@ -0,0 +1 @@ +export * from "./issued-invoices-grid"; diff --git a/modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/issued-invoices-grid/index.ts b/modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/issued-invoices-grid/index.ts new file mode 100644 index 00000000..fdf84969 --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/issued-invoices-grid/index.ts @@ -0,0 +1,2 @@ +export * from "./issued-invoices-grid"; +export * from "./use-issued-invoices-grid-columns"; diff --git a/modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/issued-invoices-grid/issued-invoices-grid.tsx b/modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/issued-invoices-grid/issued-invoices-grid.tsx new file mode 100644 index 00000000..eb997bac --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/issued-invoices-grid/issued-invoices-grid.tsx @@ -0,0 +1,125 @@ +import { DataTable, SkeletonDataTable } from "@repo/rdx-ui/components"; +import type { ColumnDef } from "@tanstack/react-table"; +import { useNavigate } from "react-router-dom"; + +import { useTranslation } from "../../../../../i18n"; +import type { IssuedInvoiceSummaryData, IssuedInvoiceSummaryPageData } from "../../../../types"; + +export type InvoiceUpdateCompProps = { + data: IssuedInvoiceSummaryPageData; + loading?: boolean; + + columns: ColumnDef[]; + + pageIndex: number; + pageSize: number; + onPageChange?: (pageNumber: number) => void; + onPageSizeChange?: (pageSize: number) => void; + + onRowClick?: ( + row: IssuedInvoiceSummaryPageData, + index: number, + event: React.MouseEvent + ) => void; +}; + +// Create new GridExample component +export const IssuedInvoicesGrid = ({ + data, + loading, + columns, + pageIndex, + pageSize, + onPageChange, + onPageSizeChange, + onRowClick, +}: InvoiceUpdateCompProps) => { + const { t } = useTranslation(); + const navigate = useNavigate(); + const { items, total_items } = data; + + // Navegación accesible (click o teclado) + /* const goToRow = useCallback( + (id: string, newTab = false) => { + const url = `/customer-invoices/${id}/edit`; + newTab ? window.open(url, "_blank", "noopener,noreferrer") : navigate(url); + }, + [navigate] + ); + + const onRowClicked = useCallback( + (e: RowClickedEvent) => { + if (!e.data) return; + const newTab = e.event instanceof MouseEvent && (e.event.metaKey || e.event.ctrlKey); + goToRow(e.data.id, newTab); + }, + [goToRow] + ); + + const onCellKeyDown = useCallback( + (e: CellKeyDownEvent) => { + if (!e.data) return; + + const ev = e.event; + if (!(ev && ev instanceof KeyboardEvent)) return; + + const key = ev.key; + if (key === "Enter" || key === " ") { + ev.preventDefault(); + goToRow(e.data.id); + } + if ((ev.ctrlKey || ev.metaKey) && key === "Enter") { + ev.preventDefault(); + goToRow(e.data.id, true); + } + }, + [goToRow] + ); + + const handleRowClick = useCallback( + (invoice: IssuedInvoiceSummaryPageData, _i: number, e: React.MouseEvent) => { + const url = `/customer-invoices/${invoice.id}/edit`; + if (e.metaKey || e.ctrlKey) { + window.open(url, "_blank", "noopener,noreferrer"); + return; + } + preview.open(invoice); + }, + [preview] + ); */ + + if (loading) { + return ( +
+ +
+ ); + } + + // Render principal + return ( + <> + {/*
*/} + + {/*
*/} + + ); +}; diff --git a/modules/customer-invoices/src/web/issued-invoices/pages/list/hooks/use-issued-invoices-grid-columns.tsx b/modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/issued-invoices-grid/use-issued-invoices-grid-columns.tsx similarity index 93% rename from modules/customer-invoices/src/web/issued-invoices/pages/list/hooks/use-issued-invoices-grid-columns.tsx rename to modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/issued-invoices-grid/use-issued-invoices-grid-columns.tsx index af0962e4..00f4295c 100644 --- a/modules/customer-invoices/src/web/issued-invoices/pages/list/hooks/use-issued-invoices-grid-columns.tsx +++ b/modules/customer-invoices/src/web/issued-invoices/list/ui/blocks/issued-invoices-grid/use-issued-invoices-grid-columns.tsx @@ -14,21 +14,20 @@ import { import type { ColumnDef } from "@tanstack/react-table"; import { DownloadIcon, MailIcon, MoreVerticalIcon, QrCodeIcon } from "lucide-react"; import * as React from "react"; -import QRCode from "react-qr-code"; +import QrCode from "react-qr-code"; -import { useTranslation } from "../../../../i18n"; -import type { IssuedInvoiceSummaryData } from "../../../schema"; +import { useTranslation } from "../../../../../i18n"; +import type { IssuedInvoiceSummaryData } from "../../../../types"; type GridActionHandlers = { - onDownloadPdf?: (proforma: IssuedInvoiceSummaryData) => void; - onSendEmail?: (proforma: IssuedInvoiceSummaryData) => void; + onDownloadPdf?: (issuedInvoice: IssuedInvoiceSummaryData) => void; + onSendEmail?: (issuedInvoice: IssuedInvoiceSummaryData) => void; }; export function useIssuedInvoicesGridColumns( actionHandlers: GridActionHandlers = {} ): ColumnDef[] { const { t } = useTranslation(); - const { onDownloadPdf, onSendEmail } = actionHandlers; return React.useMemo[]>( () => [ @@ -101,7 +100,7 @@ export function useIssuedInvoicesGridColumns( - + )} @@ -132,15 +131,15 @@ export function useIssuedInvoicesGridColumns( size: 140, minSize: 120, cell: ({ row }) => { - const c = row.original.recipient; + const r = row.original.recipient; return (
- {c.name} + {r.name}
- {c.tin && {c.tin}} + {r.tin && {r.tin}}
@@ -321,7 +320,7 @@ export function useIssuedInvoicesGridColumns( size: 64, minSize: 64, cell: ({ row }) => { - const proforma = row.original; + const issuedInvoice = row.original; const stop = (e: React.MouseEvent | React.KeyboardEvent) => e.stopPropagation(); return ( @@ -333,8 +332,8 @@ export function useIssuedInvoicesGridColumns( aria-label={t("common.download_pdf")} className="cursor-pointer text-muted-foreground hover:text-primary" onClick={(e) => { - e.stopPropagation(); - onDownloadPdf?.(proforma); + stop(e); + actionHandlers.onDownloadPdf?.(issuedInvoice); }} size="icon-sm" type="button" @@ -366,14 +365,14 @@ export function useIssuedInvoicesGridColumns( onDownloadPdf?.(proforma)} + onClick={() => actionHandlers.onDownloadPdf?.(issuedInvoice)} > {t("common.download_pdf")} onSendEmail?.(proforma)} + onClick={() => actionHandlers.onSendEmail?.(issuedInvoice)} > {t("common.send_email")} @@ -389,6 +388,6 @@ export function useIssuedInvoicesGridColumns( }, }, ], - [t, onDownloadPdf, onSendEmail] + [t, actionHandlers] ); } diff --git a/modules/customer-invoices/src/web/issued-invoices/list/ui/index.ts b/modules/customer-invoices/src/web/issued-invoices/list/ui/index.ts new file mode 100644 index 00000000..c4e34b27 --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/ui/index.ts @@ -0,0 +1 @@ +export * from "./pages"; diff --git a/modules/customer-invoices/src/web/issued-invoices/list/ui/pages/index.ts b/modules/customer-invoices/src/web/issued-invoices/list/ui/pages/index.ts new file mode 100644 index 00000000..77624ddb --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/ui/pages/index.ts @@ -0,0 +1 @@ +export * from "./issued-invoice-list-page"; diff --git a/modules/customer-invoices/src/web/issued-invoices/list/ui/pages/issued-invoice-list-page.tsx b/modules/customer-invoices/src/web/issued-invoices/list/ui/pages/issued-invoice-list-page.tsx new file mode 100644 index 00000000..c48849e7 --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/list/ui/pages/issued-invoice-list-page.tsx @@ -0,0 +1,123 @@ +import { PageHeader, SimpleSearchInput } from "@erp/core/components"; +import { ErrorAlert } from "@erp/customers/components"; +import { AppContent, AppHeader, BackHistoryButton } from "@repo/rdx-ui/components"; +import { + Alert, + AlertDescription, + AlertTitle, + Button, + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@repo/shadcn-ui/components"; +import { FilterIcon, LockIcon, PlusIcon } from "lucide-react"; +import { useNavigate } from "react-router-dom"; + +import { useTranslation } from "../../../../i18n"; +import { useIssuedInvoiceListPageController } from "../../controllers"; +import { IssuedInvoicesGrid, useIssuedInvoicesGridColumns } from "../blocks"; + +export const IssuedInvoiceListPage = () => { + const { t } = useTranslation(); + const navigate = useNavigate(); + const { listCtrl, handleDownloadPDF } = useIssuedInvoiceListPageController(); + + const columns = useIssuedInvoicesGridColumns({ + onDownloadPdf: handleDownloadPDF, + onSendEmail: () => null, + }); + + // Hook con Sheet de shadcn + /*const preview = usePinnedPreviewSheet({ + persistKey: "invoice-preview-pin", + widthClass: "w-[500px]", + });*/ + + if (listCtrl.isError || !listCtrl.data) { + return ( + + + + + ); + } + + return ( + <> + + navigate("/issued-invoices/create")} + > + + {t("pages.issued_invoices.create.title")} + + } + title={t("pages.issued_invoices.list.title")} + /> + + + + + ¡Atención! + + Las facturas de esta pantalla son de solo lectura. Se generan automáticamente al emitir + una proforma aprobada y no se pueden modificar ni eliminar. Solo puedes descargar el PDF + de cada factura. + + + + {/* Search and filters */} +
+ + + +
+ + navigate(`/issuedInvoices/${id}`)} + pageIndex={listCtrl.pageIndex} + pageSize={listCtrl.pageSize} + /> +
+ + ); +}; diff --git a/modules/customer-invoices/src/web/issued-invoices/pages/list/hooks/index.ts b/modules/customer-invoices/src/web/issued-invoices/pages/list/hooks/index.ts index abc4de9d..b7d6b472 100644 --- a/modules/customer-invoices/src/web/issued-invoices/pages/list/hooks/index.ts +++ b/modules/customer-invoices/src/web/issued-invoices/pages/list/hooks/index.ts @@ -1,2 +1,3 @@ -export * from "./use-issued-invoices-grid-columns"; +export * from "../../../list/ui/blocks/issued-invoices-grid/use-issued-invoices-grid-columns"; + export * from "./use-issued-invoices-list"; diff --git a/modules/customer-invoices/src/web/issued-invoices/pages/list/issued-invoice-list-page.tsx b/modules/customer-invoices/src/web/issued-invoices/pages/list/issued-invoice-list-page.tsx deleted file mode 100644 index 41d2a58b..00000000 --- a/modules/customer-invoices/src/web/issued-invoices/pages/list/issued-invoice-list-page.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { PageHeader } from "@erp/core/components"; -import { ErrorAlert } from "@erp/customers/components"; -import { AppContent, AppHeader, BackHistoryButton } from "@repo/rdx-ui/components"; -import { Button } from "@repo/shadcn-ui/components"; -import { PlusIcon } from "lucide-react"; -import { useNavigate } from "react-router-dom"; - -import { useTranslation } from "../../../i18n"; - -import { useIssuedInvoicesList } from "./hooks"; -import { IssuedInvoicesGrid } from "./ui/issued-invoices-grid"; - -export const IssuedInvoiceListPage = () => { - const { t } = useTranslation(); - const navigate = useNavigate(); - const list = useIssuedInvoicesList(); - - if (list.isError || !list.data) { - return ( - - - - - ); - } - - return ( - <> - - navigate("/issued-invoices/create")} - > - - {t("pages.issued_invoices.create.title")} - - } - title={t("pages.issued_invoices.list.title")} - /> - - - - - - ); -}; diff --git a/modules/customer-invoices/src/web/issued-invoices/schema/index.ts b/modules/customer-invoices/src/web/issued-invoices/types/index.ts similarity index 100% rename from modules/customer-invoices/src/web/issued-invoices/schema/index.ts rename to modules/customer-invoices/src/web/issued-invoices/types/index.ts diff --git a/modules/customer-invoices/src/web/issued-invoices/schema/issued-invoice-summary.web.schema.ts b/modules/customer-invoices/src/web/issued-invoices/types/issued-invoice-summary.web.schema.ts similarity index 100% rename from modules/customer-invoices/src/web/issued-invoices/schema/issued-invoice-summary.web.schema.ts rename to modules/customer-invoices/src/web/issued-invoices/types/issued-invoice-summary.web.schema.ts diff --git a/modules/customer-invoices/src/web/issued-invoices/schema/issued-invoice.api.schema.ts b/modules/customer-invoices/src/web/issued-invoices/types/issued-invoice.api.schema.ts similarity index 100% rename from modules/customer-invoices/src/web/issued-invoices/schema/issued-invoice.api.schema.ts rename to modules/customer-invoices/src/web/issued-invoices/types/issued-invoice.api.schema.ts diff --git a/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.tsx b/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.tsx index c56d790f..60a879fd 100644 --- a/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.tsx +++ b/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.tsx @@ -138,7 +138,7 @@ export function useProformasGridColumns( return (