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 (
);
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 && (
-
onEdit(row.original)}>
+ onEdit(row.original)}
+ >
Editar
)}
{onDelete && (
- onDelete(row.original)}>
+ onDelete(row.original)}
+ >
Excluir
)}
@@ -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 */}
@@ -133,9 +153,11 @@ export function DataTable({
- {/* 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()}
({
size="sm"
onClick={() => table.setPageIndex(0)}
disabled={!table.getCanPreviousPage()}
- aria-label="Primeira página"
- className="cursor-pointer"
type="button"
>
Primeira
@@ -196,8 +252,6 @@ export function DataTable({
size="sm"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
- aria-label="Página anterior"
- className="cursor-pointer"
type="button"
>
@@ -208,8 +262,6 @@ export function DataTable({
size="sm"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
- aria-label="Próxima página"
- className="cursor-pointer"
type="button"
>
Próxima
@@ -218,10 +270,10 @@ export function DataTable({
table.setPageIndex(table.getPageCount() - 1)}
+ onClick={() =>
+ table.setPageIndex(table.getPageCount() - 1)
+ }
disabled={!table.getCanNextPage()}
- aria-label="Última página"
- className="cursor-pointer"
type="button"
>
Última
diff --git a/src/shared/components/loadingButton/LoadingButton.tsx b/src/shared/components/loadingButton/LoadingButton.tsx
index 7a4504a..2f9702c 100644
--- a/src/shared/components/loadingButton/LoadingButton.tsx
+++ b/src/shared/components/loadingButton/LoadingButton.tsx
@@ -41,4 +41,4 @@ const LoadingButton = forwardRef(
LoadingButton.displayName = 'LoadingButton';
-export default LoadingButton;
+export default LoadingButton;
\ No newline at end of file