diff --git a/package-lock.json b/package-lock.json index 4d02c62..99e913f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-select": "^2.2.6", - "@radix-ui/react-separator": "^1.1.7", + "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-tabs": "^1.1.13", @@ -2132,12 +2132,12 @@ } }, "node_modules/@radix-ui/react-separator": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", - "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz", + "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.3" + "@radix-ui/react-primitive": "2.1.4" }, "peerDependencies": { "@types/react": "*", @@ -2154,6 +2154,47 @@ } } }, + "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", diff --git a/package.json b/package.json index 534cfa0..f25f061 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-select": "^2.2.6", - "@radix-ui/react-separator": "^1.1.7", + "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-tabs": "^1.1.13", diff --git a/src/components/app-sidebar.tsx b/src/components/app-sidebar.tsx index dec69ef..4616710 100644 --- a/src/components/app-sidebar.tsx +++ b/src/components/app-sidebar.tsx @@ -5,6 +5,7 @@ import { Frame, GalleryVerticalEnd, HouseIcon, + SquareMousePointer, SquareTerminal, UsersIcon } from 'lucide-react'; @@ -46,7 +47,7 @@ const data = { { title: 'Servicos', url: '#', - icon: UsersIcon, + icon: SquareMousePointer, isActive: false, items: [ { diff --git a/src/components/ui/item.tsx b/src/components/ui/item.tsx new file mode 100644 index 0000000..d97de21 --- /dev/null +++ b/src/components/ui/item.tsx @@ -0,0 +1,193 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" +import { Separator } from "@/components/ui/separator" + +function ItemGroup({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function ItemSeparator({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +const itemVariants = cva( + "group/item flex items-center border border-transparent text-sm rounded-md transition-colors [a]:hover:bg-accent/50 [a]:transition-colors duration-100 flex-wrap outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", + { + variants: { + variant: { + default: "bg-transparent", + outline: "border-border", + muted: "bg-muted/50", + }, + size: { + default: "p-4 gap-4 ", + sm: "py-3 px-4 gap-2.5", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +function Item({ + className, + variant = "default", + size = "default", + asChild = false, + ...props +}: React.ComponentProps<"div"> & + VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot : "div" + return ( + + ) +} + +const itemMediaVariants = cva( + "flex shrink-0 items-center justify-center gap-2 group-has-[[data-slot=item-description]]/item:self-start [&_svg]:pointer-events-none group-has-[[data-slot=item-description]]/item:translate-y-0.5", + { + variants: { + variant: { + default: "bg-transparent", + icon: "size-8 border rounded-sm bg-muted [&_svg:not([class*='size-'])]:size-4", + image: + "size-10 rounded-sm overflow-hidden [&_img]:size-full [&_img]:object-cover", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function ItemMedia({ + className, + variant = "default", + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ) +} + +function ItemContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function ItemTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function ItemDescription({ className, ...props }: React.ComponentProps<"p">) { + return ( +

a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4", + className + )} + {...props} + /> + ) +} + +function ItemActions({ className, ...props }: React.ComponentProps<"div">) { + return ( +

+ ) +} + +function ItemHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function ItemFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { + Item, + ItemMedia, + ItemContent, + ItemActions, + ItemGroup, + ItemSeparator, + ItemTitle, + ItemDescription, + ItemHeader, + ItemFooter, +} diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx index 4e528b9..275381c 100644 --- a/src/components/ui/separator.tsx +++ b/src/components/ui/separator.tsx @@ -1,13 +1,13 @@ -'use client'; +"use client" -import * as React from 'react'; -import * as SeparatorPrimitive from '@radix-ui/react-separator'; +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" -import { cn } from '@/lib/utils'; +import { cn } from "@/lib/utils" function Separator({ className, - orientation = 'horizontal', + orientation = "horizontal", decorative = true, ...props }: React.ComponentProps) { @@ -17,12 +17,12 @@ function Separator({ decorative={decorative} orientation={orientation} className={cn( - 'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px', - className, + "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px", + className )} {...props} /> - ); + ) } -export { Separator }; +export { Separator } diff --git a/src/packages/administrativo/components/TPessoa/TPessoaTableFormColumnsDialog.tsx b/src/packages/administrativo/components/TPessoa/TPessoaTableFormColumnsDialog.tsx index 8b0ace3..0c13af2 100644 --- a/src/packages/administrativo/components/TPessoa/TPessoaTableFormColumnsDialog.tsx +++ b/src/packages/administrativo/components/TPessoa/TPessoaTableFormColumnsDialog.tsx @@ -2,6 +2,7 @@ import { ColumnDef } from '@tanstack/react-table'; import { ArrowUpDownIcon } from 'lucide-react'; import { Button } from '@/components/ui/button'; +import { Checkbox } from '@/components/ui/checkbox'; import { FormatCPF } from '@/shared/actions/CPF/FormatCPF'; import { FormatDateTime } from '@/shared/actions/dateTime/FormatDateTime'; import { FormatPhone } from '@/shared/actions/phone/FormatPhone'; @@ -13,8 +14,26 @@ import TPessoaInterface from '../../interfaces/TPessoa/TPessoaInterface'; /** * Função para criar a definição das colunas da tabela */ -export function TPessoaTableFormColumnsDialog(): ColumnDef[] { +export function TPessoaTableFormColumnsDialog(setSelectedTPessoa: React.Dispatch>): ColumnDef[] { return [ + { + id: 'select', + header: '', + cell: ({ row, table }) => ( + { + // Limpa todas as seleções antes de selecionar uma nova + table.resetRowSelection(); + row.toggleSelected(!!value); + setSelectedTPessoa(value ? row.original : null); + }} + aria-label="Select row" + /> + ), + enableSorting: false, + enableHiding: false, + }, // ID { accessorKey: 'pessoa_id', diff --git a/src/packages/administrativo/components/TPessoa/TPessoaTableFormDialog.tsx b/src/packages/administrativo/components/TPessoa/TPessoaTableFormDialog.tsx index 1b83d8d..a318a2f 100644 --- a/src/packages/administrativo/components/TPessoa/TPessoaTableFormDialog.tsx +++ b/src/packages/administrativo/components/TPessoa/TPessoaTableFormDialog.tsx @@ -10,19 +10,17 @@ import { DialogDescription, DialogFooter, DialogHeader, - DialogTitle, + DialogTitle } from '@/components/ui/dialog'; -import { Form } from '@/components/ui/form'; import { useTPessoaFisicaIndexHook } from '@/packages/administrativo/hooks/TPessoa/TPessoaFisica/useTPessoaFisicaIndexHook'; -import { useTPessoaRepresentanteFormHook } from '@/packages/administrativo/hooks/TPessoaRepresentante/useTPessoaRepresentanteFormHook'; +import { useTPessoaJuridicaIndexHook } from '@/packages/administrativo/hooks/TPessoa/TPessoaJuridica/useTPessoaJuridicaIndexHook'; +import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface'; import TPessoaTableFormInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaTableFormInterface'; import { DataTable } from '@/shared/components/dataTable/DataTable'; import LoadingButton from '@/shared/components/loadingButton/LoadingButton'; -import { useTPessoaJuridicaIndexHook } from '../../hooks/TPessoa/TPessoaJuridica/useTPessoaJuridicaIndexHook'; import { TPessoaTableFormColumnsDialog } from './TPessoaTableFormColumnsDialog'; - export default function TPessoaTableFormDialog({ isOpen, tipoPessoa, @@ -34,9 +32,9 @@ export default function TPessoaTableFormDialog({ const { tPessoaFisica, fetchTPessoaFisica } = useTPessoaFisicaIndexHook(); const { tPessoaJuridica, fetchTPessoaJuridica } = useTPessoaJuridicaIndexHook(); const [pessoas, setPessoas] = useState() + const [selectedTPessoa, setSelectedTPessoa] = useState(null); - const form = useTPessoaRepresentanteFormHook(); - + // Executa o Hook de Acordo com o tipo de pessoa informado const loadData = async (tipoPessoa: string) => { switch (tipoPessoa) { @@ -55,29 +53,34 @@ export default function TPessoaTableFormDialog({ }; + // Atualiza a variavel de pessoa quando tiver alteração na variavel de pessoas fisicas useEffect(() => { setPessoas(tPessoaFisica) }, [tPessoaFisica]) + // Atualiza a variavel de pessoa quando tiver alteração na variavel de pessoas juridicas useEffect(() => { setPessoas(tPessoaJuridica) }, [tPessoaJuridica]) + // Executa o hook correspondente ao tipo de pessoa, sempre que o tipo pessoa mudar useEffect(() => { + // Verifica se o tipo pessoa esta preenchido if (tipoPessoa) { + // Dispara o carregamento de informações loadData(tipoPessoa); } }, [tipoPessoa]); - const columns = TPessoaTableFormColumnsDialog(); + const columns = TPessoaTableFormColumnsDialog(setSelectedTPessoa); return ( Pessoa Busque a pessoa desejada -
- -
- -
- {/* Rodapé do Dialog */} - - - - - - -
- +
+ +
+ {/* Rodapé do Dialog */} + + + + + { onSave(selectedTPessoa); onClose(null, false); }} + /> +
); diff --git a/src/packages/administrativo/interfaces/TPessoa/TPessoaTableFormInterface.ts b/src/packages/administrativo/interfaces/TPessoa/TPessoaTableFormInterface.ts index 6df3555..e542ae5 100644 --- a/src/packages/administrativo/interfaces/TPessoa/TPessoaTableFormInterface.ts +++ b/src/packages/administrativo/interfaces/TPessoa/TPessoaTableFormInterface.ts @@ -1,9 +1,8 @@ -import { TPessoaRepresentanteFormValues } from '../../schemas/TPessoaRepresentante/TPessoaRepresentanteSchema'; export default interface TPessoaTableFormInterface { isOpen: boolean; tipoPessoa: string; onClose: (item: null, isFormStatus: boolean) => void; - onSave: (data: TPessoaRepresentanteFormValues) => void; + onSave: (data: any) => void; buttonIsLoading: boolean; } diff --git a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoFormColumns.tsx b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoFormColumns.tsx index 5064271..6ff1e4b 100644 --- a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoFormColumns.tsx +++ b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoFormColumns.tsx @@ -83,13 +83,10 @@ export default function TServicoItemPedidoFormColumns(): ColumnDef { if (updateData) updateData(row.index, 'quantidade', next); }; - const dec = () => setNext(Math.max(min, value - 1)); const inc = () => setNext(Math.min(max, value + 1)); diff --git a/src/packages/servicos/components/TServicoPedido/TServicoPedidoForm.tsx b/src/packages/servicos/components/TServicoPedido/TServicoPedidoForm.tsx index 67eba9b..f1b50d2 100644 --- a/src/packages/servicos/components/TServicoPedido/TServicoPedidoForm.tsx +++ b/src/packages/servicos/components/TServicoPedido/TServicoPedidoForm.tsx @@ -1,6 +1,6 @@ 'use client'; -import { CreditCard, Package, UserSquare2 } from 'lucide-react'; +import { CreditCard, Package, TrashIcon, UserSquare2 } from 'lucide-react'; import { useRouter } from 'next/navigation'; import * as React from 'react'; import { useCallback, useState } from 'react'; @@ -16,6 +16,7 @@ import { FormMessage } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; +import { Item, ItemActions, ItemContent, ItemDescription, ItemTitle } from '@/components/ui/item'; import GEmolumentoServicoSelect from '@/packages/administrativo/components/GEmolumento/GEmolumentoServicoSelect'; import GUsuarioSelect from '@/packages/administrativo/components/GUsuario/GUsuarioSelect'; import TPessoaTableFormDialog from '@/packages/administrativo/components/TPessoa/TPessoaTableFormDialog'; @@ -62,7 +63,6 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido * Fecha o formulário e limpa o andamento selecionado */ const handleCloseForm = useCallback(() => { - console.log('handleCloseForm'); setIsFormOpen(false); }, []); @@ -123,28 +123,101 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido const handleAddItem = async () => { + const servicoEEmolumento = { + + servico_tipo: servicoAtual, + emolumento: emolumentoAtual, + + }; + + // Adiciona o item remotamente (se for necessário) + const newItem = await addTServicoItemPedido(servicoEEmolumento); + + // Garante que o item seja adicionado no estado local (para a tabela renderizar) + if (newItem) localAddTServicoItemPedido(newItem); + + }; + + const handleAddItemAndTPessoa = async (selectedTPessoa: any) => { + // Monta o payload principal com serviço e emolumento + const servicoEEmolumento = { + servico_tipo: servicoAtual, + emolumento: emolumentoAtual, + }; + + // Adiciona o item remotamente (se for necessário) + const newItem = await addTServicoItemPedido(servicoEEmolumento); + + // Atribui dados principais da pessoa + newItem.pessoa_id = selectedTPessoa.pessoa_id; + + // Cria a subview (conteúdo dinâmico a ser renderizado abaixo da linha) + newItem.subview = ( + +
+ + + + + + + + {selectedTPessoa.cpf_cnpj} - {selectedTPessoa.nome} + + + + + + {selectedTPessoa.email} + + + + + + + + + + + + + +
+ + ); + + // Adiciona o item no estado local (para renderizar na tabela) + if (newItem) { + localAddTServicoItemPedido(newItem); + } + }; + + + const handleSelectTServicoTipo = async () => { + if (servicoAtual && emolumentoAtual) { - // const servicoEEmolumento = { + // Verifica se deve selecionar a pessoa + if (servicoAtual.tipo_pessoa) { - // servico_tipo: servicoAtual, - // emolumento: emolumentoAtual, + setServicoTipoPessoa(servicoAtual.tipo_pessoa) - // }; + setIsFormOpen(true); - // // Adiciona o item remotamente (se for necessário) - // const newItem = await addTServicoItemPedido(servicoEEmolumento); + } + else { - // // Garante que o item seja adicionado no estado local (para a tabela renderizar) - // if (newItem) localAddTServicoItemPedido(newItem); + handleAddItem() - setServicoTipoPessoa(servicoAtual.tipo_pessoa) - - setIsFormOpen(true); + } } - }; + } const sections: StepSection[] = [ { key: 'pedido', id: 'selectPedido', icon: , title: 'Pedido', description: 'Dados gerais do pedido.' }, @@ -368,7 +441,7 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido />
-
@@ -496,17 +569,17 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
+ {/* Formulário de criação/edição */} + {isFormOpen && ( + + )} - {/* Formulário de criação/edição */} - {isFormOpen && ( - - )}
); } \ No newline at end of file diff --git a/src/packages/servicos/schemas/TServicoPedido/TServicoPedidoSchema.ts b/src/packages/servicos/schemas/TServicoPedido/TServicoPedidoSchema.ts index 37f1d79..1e1267c 100644 --- a/src/packages/servicos/schemas/TServicoPedido/TServicoPedidoSchema.ts +++ b/src/packages/servicos/schemas/TServicoPedido/TServicoPedidoSchema.ts @@ -8,19 +8,19 @@ export const TServicoPedidoSchema = z.object({ valor_pedido: z.number().optional(), valor_pago: z.number().optional(), usuario_id: z.number().optional(), - data_pedido: z.string().optional(), + data_pedido: z.union([z.string(), z.null()]), mensalista_livrocaixa_id: z.union([z.number(), z.null()]), observacao: z.union([z.string(), z.null()]), escrevente_id: z.number(), situacao: z.string().optional(), - estornado: z.string().optional(), + estornado: z.union([z.string(), z.null()]), nfse_id: z.union([z.number(), z.null()]), apresentante: z.string().optional(), cpfcnpj_apresentante: z.string().optional(), selo_pessoa_nome: z.string().optional(), selo_pessoa_cpfcnpj: z.string().optional(), login: z.string().optional(), - funcao: z.string().optional(), + funcao: z.union([z.string(), z.null()]), itens: z.array(TServicoItemPedidoSchema).default([]), servico_tipo_id: z.object().optional(), emolumento_id: z.object().optional(), diff --git a/src/shared/components/dataTable/DataTable.tsx b/src/shared/components/dataTable/DataTable.tsx index 55d5ce8..498ccbc 100644 --- a/src/shared/components/dataTable/DataTable.tsx +++ b/src/shared/components/dataTable/DataTable.tsx @@ -35,7 +35,19 @@ import { import DataTableInterface from './interfaces/DataTableInterface'; -export function DataTable({ +/** + * DataTable genérico com suporte a subvisões dinâmicas (subtabelas ou detalhes). + * O conteúdo extra pode ser definido dinamicamente por linha, em `row.original.subview`. + * + * Exemplo de item: + * { + * id: 1, + * descricao: 'Item principal', + * valor: 100, + * subview: , + * } + */ +export function DataTable React.ReactNode) }>({ data, columns, filterColumn, @@ -44,7 +56,6 @@ export function DataTable({ onDelete, onRowClick, }: DataTableInterface) { - // Garante que data sempre seja array const safeData = Array.isArray(data) ? data : []; // Estados internos da tabela @@ -53,7 +64,7 @@ export function DataTable({ const [columnVisibility, setColumnVisibility] = React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); - // Configuração da tabela + // Cria a tabela const table = useReactTable({ data: safeData, columns: [ @@ -66,12 +77,20 @@ export function DataTable({ cell: ({ row }: any) => (
{onEdit && ( - )} {onDelete && ( - )} @@ -81,12 +100,7 @@ export function DataTable({ ] : []), ], - state: { - sorting, - columnFilters, - columnVisibility, - rowSelection, - }, + state: { sorting, columnFilters, columnVisibility, rowSelection }, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, onColumnVisibilityChange: setColumnVisibility, @@ -99,16 +113,22 @@ export function DataTable({ return (
- {/* Filtros e colunas */} + {/* 🔍 Filtros e colunas */}
{filterColumn && ( table.getColumn(filterColumn)?.setFilterValue(e.target.value)} + value={ + (table.getColumn(filterColumn)?.getFilterValue() as string) ?? '' + } + onChange={(e) => + table.getColumn(filterColumn)?.setFilterValue(e.target.value) + } className="w-full" /> )} + + {/* Menu de colunas visíveis */}
- {/* Tabela */} + + {/* 🧱 Tabela principal */}
+ {/* Cabeçalho */} {table.getHeaderGroups().map((headerGroup) => ( @@ -143,30 +165,64 @@ export function DataTable({ {header.isPlaceholder ? null - : flexRender(header.column.columnDef.header, header.getContext())} + : flexRender( + header.column.columnDef.header, + header.getContext(), + )} ))} ))} + + {/* Corpo */} {table.getRowModel().rows?.length ? ( - table.getRowModel().rows.map((row) => ( - onRowClick?.(row.original)} - > - {row.getVisibleCells().map((cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - - )) + table.getRowModel().rows.map((row) => { + const subview = + typeof row.original.subview === 'function' + ? row.original.subview() + : row.original.subview; + + return ( + + {/* Linha principal */} + onRowClick?.(row.original)} + > + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext(), + )} + + ))} + + + {/* Subview dinâmica (qualquer conteúdo) */} + {subview && ( + + + {subview} + + + )} + + ); + }) ) : ( - + Nenhum resultado encontrado. @@ -174,10 +230,12 @@ export function DataTable({
- {/* Paginação */} + + {/* 📄 Paginação */}
- Página {table.getState().pagination.pageIndex + 1} de {table.getPageCount()} + Página {table.getState().pagination.pageIndex + 1} de{' '} + {table.getPageCount()}