"use client"; import { RiArrowLeftRightLine, RiFileExcel2Line, RiFlashlightFill, } from "@remixicon/react"; import { flexRender, getCoreRowModel, getPaginationRowModel, getSortedRowModel, type RowSelectionState, type SortingState, useReactTable, type VisibilityState, } from "@tanstack/react-table"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { type ReactNode, useMemo, useState } from "react"; import type { TransactionsExportContext, TransactionsPaginationState, } from "@/features/transactions/lib/export-types"; import { EmptyState } from "@/shared/components/feedback/empty-state"; import { Button } from "@/shared/components/ui/button"; import { Card, CardContent } from "@/shared/components/ui/card"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/shared/components/ui/table"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/shared/components/ui/tooltip"; import { cn } from "@/shared/utils/ui"; import { TransactionsExport } from "../transactions-export"; import type { AccountCardFilterOption, TransactionFilterOption, TransactionItem, } from "../types"; import { TransactionsBulkBar } from "./transactions-bulk-bar"; import { getTransactionColumns } from "./transactions-columns"; import { TransactionsFilters } from "./transactions-filters"; import { TransactionsPagination } from "./transactions-pagination"; type TransactionsTableProps = { data: TransactionItem[]; currentUserId: string; noteAsColumn?: boolean; columnOrder?: string[] | null; payerFilterOptions?: TransactionFilterOption[]; categoryFilterOptions?: TransactionFilterOption[]; accountCardFilterOptions?: AccountCardFilterOption[]; selectedPeriod?: string; pagination?: TransactionsPaginationState; exportContext?: TransactionsExportContext; createSlot?: ReactNode; onMassAdd?: () => void; onEdit?: (item: TransactionItem) => void; onCopy?: (item: TransactionItem) => void; onImport?: (item: TransactionItem) => void; onConfirmDelete?: (item: TransactionItem) => void; onBulkDelete?: (items: TransactionItem[]) => void; onBulkImport?: (items: TransactionItem[]) => void; onViewDetails?: (item: TransactionItem) => void; onRefund?: (item: TransactionItem) => void; onToggleSettlement?: (item: TransactionItem) => void; onAnticipate?: (item: TransactionItem) => void; onViewAnticipationHistory?: (item: TransactionItem) => void; isSettlementLoading?: (id: string) => boolean; showActions?: boolean; showFilters?: boolean; }; export function TransactionsTable({ data, currentUserId, noteAsColumn = false, columnOrder: columnOrderPreference = null, payerFilterOptions = [], categoryFilterOptions = [], accountCardFilterOptions = [], selectedPeriod, pagination: serverPagination, exportContext, createSlot, onMassAdd, onEdit, onCopy, onImport, onConfirmDelete, onBulkDelete, onBulkImport, onViewDetails, onRefund, onToggleSettlement, onAnticipate, onViewAnticipationHistory, isSettlementLoading, showActions = true, showFilters = true, }: TransactionsTableProps) { const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); const [sorting, setSorting] = useState([ { id: "purchaseDate", desc: true }, ]); const [columnVisibility] = useState({ purchaseDate: false, }); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 30, }); const [rowSelection, setRowSelection] = useState({}); const isServerPaginated = Boolean(serverPagination); const columns = useMemo( () => getTransactionColumns({ currentUserId, noteAsColumn, onEdit, onCopy, onImport, onConfirmDelete, onViewDetails, onRefund, onToggleSettlement, onAnticipate, onViewAnticipationHistory, isSettlementLoading: isSettlementLoading ?? (() => false), showActions, columnOrder: columnOrderPreference, }), [ currentUserId, noteAsColumn, columnOrderPreference, onEdit, onCopy, onImport, onConfirmDelete, onViewDetails, onRefund, onToggleSettlement, onAnticipate, onViewAnticipationHistory, isSettlementLoading, showActions, ], ); const table = useReactTable({ data, columns, state: isServerPaginated ? { sorting, columnVisibility, rowSelection } : { sorting, columnVisibility, pagination, rowSelection }, onSortingChange: setSorting, onPaginationChange: isServerPaginated ? undefined : setPagination, onRowSelectionChange: setRowSelection, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), getPaginationRowModel: isServerPaginated ? undefined : getPaginationRowModel(), manualPagination: isServerPaginated, pageCount: serverPagination?.totalPages, enableRowSelection: true, }); const rowModel = table.getRowModel(); const hasRows = rowModel.rows.length > 0; const totalRows = isServerPaginated ? (serverPagination?.totalItems ?? 0) : table.getCoreRowModel().rows.length; const selectedRows = table.getFilteredSelectedRowModel().rows; const selectedCount = selectedRows.length; const selectedTotal = selectedRows.reduce( (total, row) => total + (row.original.amount ?? 0), 0, ); const currentPage = isServerPaginated ? (serverPagination?.page ?? 1) : table.getState().pagination.pageIndex + 1; const currentPageSize = isServerPaginated ? (serverPagination?.pageSize ?? pagination.pageSize) : pagination.pageSize; const totalPages = isServerPaginated ? Math.max(serverPagination?.totalPages ?? 1, 1) : Math.max(table.getPageCount(), 1); const canPreviousPage = currentPage > 1; const canNextPage = currentPage < totalPages; const hasOtherUserData = data.some((item) => item.userId !== currentUserId); const handleBulkDelete = () => { if (onBulkDelete && selectedCount > 0) { onBulkDelete(selectedRows.map((row) => row.original)); setRowSelection({}); } }; const handleBulkImport = () => { if (onBulkImport && selectedCount > 0) { onBulkImport(selectedRows.map((row) => row.original)); setRowSelection({}); } }; const navigateToPage = (nextPage: number, nextPageSize = currentPageSize) => { const nextParams = new URLSearchParams(searchParams.toString()); if (nextPage <= 1) { nextParams.delete("page"); } else { nextParams.set("page", nextPage.toString()); } if (nextPageSize === 30) { nextParams.delete("pageSize"); } else { nextParams.set("pageSize", nextPageSize.toString()); } const target = nextParams.toString() ? `${pathname}?${nextParams.toString()}` : pathname; router.replace(target, { scroll: false }); setRowSelection({}); }; const handlePageChange = (nextPage: number) => { if (isServerPaginated) { navigateToPage(nextPage); } else { table.setPageIndex(nextPage - 1); } }; const handlePageSizeChange = (size: number) => { if (isServerPaginated) { navigateToPage(1, size); } else { table.setPageSize(size); } }; const showTopControls = Boolean(createSlot) || Boolean(onMassAdd) || showFilters; return ( {showTopControls ? (
{createSlot || onMassAdd ? (
{createSlot} {onMassAdd ? (

Adicionar múltiplos lançamentos

) : null}

Importar extrato

) : ( )} {showFilters ? ( ) : null } /> ) : null}
) : null} {selectedCount > 0 && onBulkDelete && selectedRows.every((row) => row.original.userId === currentUserId) ? ( ) : null} {selectedCount > 0 && onBulkImport && selectedRows.some((row) => row.original.userId !== currentUserId) ? ( ) : null} {hasRows ? ( <>
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {rowModel.rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ))} ))}
) : (
} title="Nenhum lançamento encontrado" description="Ajuste os filtros ou cadastre um novo lançamento para visualizar aqui." />
)}
); }