Merge branch 'MVPTN-99' into release(MVP/Sprint6)
This commit is contained in:
commit
b3dc6c87f2
90 changed files with 4487 additions and 614 deletions
BIN
public/images/favicon.ico
Normal file
BIN
public/images/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
BIN
public/images/logo-abb.png
Normal file
BIN
public/images/logo-abb.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
20
src/actions/CEP/FormatCEP.ts
Normal file
20
src/actions/CEP/FormatCEP.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Formata um número de CEP no padrão 99999-999
|
||||
*
|
||||
* @param value - CEP em string ou number
|
||||
* @returns CEP formatado ou string vazia se inválido
|
||||
*/
|
||||
export function FormatCEP(value: string | number): string {
|
||||
if (!value) return '';
|
||||
|
||||
// Converte para string e remove tudo que não seja número
|
||||
const digits = String(value).replace(/\D/g, '');
|
||||
|
||||
// Garante que tenha no máximo 8 dígitos
|
||||
const cleanValue = digits.slice(0, 8);
|
||||
|
||||
// Retorna formatado ou valor limpo se não tiver tamanho suficiente
|
||||
if (cleanValue.length !== 8) return cleanValue;
|
||||
|
||||
return cleanValue.replace(/(\d{5})(\d{3})/, '$1-$2');
|
||||
}
|
||||
15
src/actions/form/ResetFormIfData.ts
Normal file
15
src/actions/form/ResetFormIfData.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { UseFormReturn, FieldValues } from "react-hook-form";
|
||||
|
||||
/**
|
||||
* Reseta o formulário com os dados recebidos (se existirem)
|
||||
* @param form - Instância do react-hook-form
|
||||
* @param data - Dados para popular o formulário
|
||||
*/
|
||||
export function ResetFormIfData<T extends FieldValues>(
|
||||
form: UseFormReturn<T>,
|
||||
data: T | null
|
||||
) {
|
||||
if (data) {
|
||||
form.reset(data);
|
||||
}
|
||||
}
|
||||
6
src/actions/form/parseNumberInput.ts
Normal file
6
src/actions/form/parseNumberInput.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/**
|
||||
* Converte o valor do input para número, enviando undefined se estiver vazio
|
||||
*/
|
||||
export function parseNumberInput(e: React.ChangeEvent<HTMLInputElement>): number | undefined {
|
||||
return e.target.value ? Number(e.target.value) : undefined;
|
||||
}
|
||||
|
|
@ -3,17 +3,17 @@
|
|||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
|
||||
import Loading from '@/app/_components/loading/loading';
|
||||
import TPessoaTable from '../../../_components/t_pessoa/TPessoaTable';
|
||||
import TPessoaForm from '../../../_components/t_pessoa/TPessoaForm';
|
||||
import TPessoaTable from '@/packages/administrativo/components/TPessoa/TPessoaFisica/TPessoaFisicaTable';
|
||||
import TPessoaForm from '@/packages/administrativo/components/TPessoa/TPessoaFisica/TPessoaFisicaForm';
|
||||
|
||||
import { useTPessoaIndexHook } from '../../../_hooks/t_pessoa/useTPessoaIndexHook';
|
||||
import { useTPessoaSaveHook } from '../../../_hooks/t_pessoa/useTPessoaSaveHook';
|
||||
import { useTPessoaDeleteHook } from '../../../_hooks/t_pessoa/useTPessoaDeleteHook';
|
||||
import { useTPessoaIndexHook } from '@/packages/administrativo/hooks/t_pessoa/useTPessoaIndexHook';
|
||||
import { useTPessoaSaveHook } from '@/packages/administrativo/hooks/t_pessoa/useTPessoaSaveHook';
|
||||
import { useTPessoaDeleteHook } from '@/packages/administrativo/hooks/t_pessoa/useTPessoaDeleteHook';
|
||||
|
||||
import ConfirmDialog from '@/app/_components/confirm_dialog/ConfirmDialog';
|
||||
import { useConfirmDialog } from '@/app/_components/confirm_dialog/useConfirmDialog';
|
||||
|
||||
import TPessoaInterface from '../../../_interfaces/TPessoaInterface';
|
||||
import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface';
|
||||
import Header from '@/app/_components/structure/Header';
|
||||
|
||||
export default function TPessoaFisica() {
|
||||
|
|
@ -4,17 +4,17 @@ import React, { useEffect, useState, useCallback } from 'react';
|
|||
|
||||
import Loading from '@/app/_components/loading/loading';
|
||||
|
||||
import { useTPessoaSaveHook } from '../../../_hooks/t_pessoa/useTPessoaSaveHook';
|
||||
import { useTPessoaDeleteHook } from '../../../_hooks/t_pessoa/useTPessoaDeleteHook';
|
||||
import { useTPessoaSaveHook } from '@/packages/administrativo/hooks/t_pessoa/useTPessoaSaveHook';
|
||||
import { useTPessoaDeleteHook } from '@/packages/administrativo/hooks/t_pessoa/useTPessoaDeleteHook';
|
||||
|
||||
import ConfirmDialog from '@/app/_components/confirm_dialog/ConfirmDialog';
|
||||
import { useConfirmDialog } from '@/app/_components/confirm_dialog/useConfirmDialog';
|
||||
|
||||
import TPessoaInterface from '../../../_interfaces/TPessoaInterface';
|
||||
import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface';
|
||||
import Header from '@/app/_components/structure/Header';
|
||||
import TPessoaJuridicaTable from '../../../_components/t_pessoa/juridica/TPessoaJuridicaTable';
|
||||
import { useTPessoaJuridicaIndexHook } from '../../../_hooks/t_pessoa/juridica/useTPessoaJuridicaIndexHook';
|
||||
import TPessoaJuridicaForm from '../../../_components/t_pessoa/juridica/TPessoaJuridicaForm';
|
||||
import TPessoaJuridicaTable from '@/packages/administrativo/components/TPessoa/TPessoaJuridica/TPessoaJuridicaTable';
|
||||
import { useTPessoaJuridicaIndexHook } from '@/packages/administrativo/hooks/t_pessoa/juridica/useTPessoaJuridicaIndexHook';
|
||||
import TPessoaJuridicaForm from '@/packages/administrativo/components/TPessoa/TPessoaJuridica/TPessoaJuridicaForm';
|
||||
|
||||
export default function TPessoaFisica() {
|
||||
// Controle de estado do botão
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useState, useCallback } from 'react';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
|
||||
import Loading from '@/app/_components/loading/loading';
|
||||
import TImovelTable from '@/packages/administrativo/components/t_imovel/TImovelTable';
|
||||
import TImovelForm from '@/packages/administrativo/components/t_imovel/TImovelForm';
|
||||
|
||||
import { useTImovelIndexHook } from '@/packages/administrativo/hooks/t_imovel/useTImovelIndexHook';
|
||||
import { useTImovelSaveHook } from '@/packages/administrativo/hooks/t_imovel/useTImovelSaveHook';
|
||||
import { useTImovelDeleteHook } from '@/packages/administrativo/hooks/t_imovel/useTImovelDeleteHook';
|
||||
|
||||
import ConfirmDialog from '@/app/_components/confirm_dialog/ConfirmDialog';
|
||||
import { useConfirmDialog } from '@/app/_components/confirm_dialog/useConfirmDialog';
|
||||
|
||||
import TImovelInterface from '@/packages/administrativo/interfaces/TImovelInterface';
|
||||
import Header from '@/app/_components/structure/Header';
|
||||
|
||||
export default function TTBAndamentoServico() {
|
||||
// Controle de estado do botão
|
||||
const [buttonIsLoading, setButtonIsLoading] = useState(false);
|
||||
|
||||
// Hooks para leitura e salvamento
|
||||
const { tImovel, indexTImovel } = useTImovelIndexHook();
|
||||
const { saveTImovel } = useTImovelSaveHook();
|
||||
const { deleteTImovel } = useTImovelDeleteHook();
|
||||
|
||||
// Estados
|
||||
const [selectedAndamento, setSelectedAndamento] = useState<TImovelInterface | null>(null);
|
||||
const [isFormOpen, setIsFormOpen] = useState(false);
|
||||
|
||||
// Estado para saber qual item será deletado
|
||||
const [itemToDelete, setItemToDelete] = useState<TImovelInterface | null>(null);
|
||||
|
||||
/**
|
||||
* Hook do modal de confirmação
|
||||
*/
|
||||
const {
|
||||
isOpen: isConfirmOpen,
|
||||
openDialog: openConfirmDialog,
|
||||
handleConfirm,
|
||||
handleCancel,
|
||||
} = useConfirmDialog();
|
||||
|
||||
/**
|
||||
* Abre o formulário no modo de edição ou criação
|
||||
*/
|
||||
const handleOpenForm = useCallback((data: TImovelInterface | null) => {
|
||||
setSelectedAndamento(data);
|
||||
setIsFormOpen(true);
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Fecha o formulário e limpa o andamento selecionado
|
||||
*/
|
||||
const handleCloseForm = useCallback(() => {
|
||||
setSelectedAndamento(null);
|
||||
setIsFormOpen(false);
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Salva os dados do formulário
|
||||
*/
|
||||
const handleSave = useCallback(
|
||||
async (formData: TImovelInterface) => {
|
||||
// Coloca o botão em estado de loading
|
||||
setButtonIsLoading(true);
|
||||
|
||||
// Aguarda salvar o registro
|
||||
await saveTImovel(formData);
|
||||
|
||||
// Remove o botão em estado de loading
|
||||
setButtonIsLoading(false);
|
||||
|
||||
// Atualiza a lista de dados
|
||||
indexTImovel();
|
||||
},
|
||||
[saveTImovel, indexTImovel, handleCloseForm],
|
||||
);
|
||||
|
||||
/**
|
||||
* Quando o usuário clica em "remover" na tabela
|
||||
*/
|
||||
const handleConfirmDelete = useCallback(
|
||||
(item: TImovelInterface) => {
|
||||
// Define o item atual para remoção
|
||||
setItemToDelete(item);
|
||||
|
||||
// Abre o modal de confirmação
|
||||
openConfirmDialog();
|
||||
},
|
||||
[openConfirmDialog],
|
||||
);
|
||||
|
||||
/**
|
||||
* Executa a exclusão de fato quando o usuário confirma
|
||||
*/
|
||||
const handleDelete = useCallback(async () => {
|
||||
// Protege contra null
|
||||
if (!itemToDelete) return;
|
||||
|
||||
// Executa o Hook de remoção
|
||||
await deleteTImovel(itemToDelete);
|
||||
|
||||
// Atualiza a lista
|
||||
await indexTImovel();
|
||||
|
||||
// Limpa o item selecionado
|
||||
setItemToDelete(null);
|
||||
|
||||
// Fecha o modal
|
||||
handleCancel();
|
||||
}, [itemToDelete, indexTImovel, handleCancel]);
|
||||
|
||||
/**
|
||||
* Busca inicial dos dados
|
||||
*/
|
||||
useEffect(() => {
|
||||
indexTImovel();
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Tela de loading enquanto carrega os dados
|
||||
*/
|
||||
if (tImovel?.length == 0) {
|
||||
return <Loading type={2} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* Cabeçalho */}
|
||||
<Header
|
||||
title={'Imóveis Urbanos'}
|
||||
description={'Gerenciamento de imóveis urbanos'}
|
||||
buttonText={'Novo imóvel'}
|
||||
buttonAction={() => {
|
||||
handleOpenForm(null);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Tabela de andamentos */}
|
||||
<TImovelTable
|
||||
data={tImovel}
|
||||
onEdit={handleOpenForm}
|
||||
onDelete={handleConfirmDelete} />
|
||||
|
||||
{/* Modal de confirmação */}
|
||||
<ConfirmDialog
|
||||
isOpen={isConfirmOpen}
|
||||
title="Confirmar exclusão"
|
||||
description="Atenção"
|
||||
message={`Deseja realmente excluir o imóvel "${itemToDelete?.cidade}"?`}
|
||||
confirmText="Sim, excluir"
|
||||
cancelText="Cancelar"
|
||||
onConfirm={handleDelete}
|
||||
onCancel={handleCancel}
|
||||
/>
|
||||
|
||||
{/* Formulário de criação/edição */}
|
||||
<TImovelForm
|
||||
isOpen={isFormOpen}
|
||||
data={selectedAndamento}
|
||||
onClose={handleCloseForm}
|
||||
onSave={handleSave}
|
||||
buttonIsLoading={buttonIsLoading}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
4;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
|
||||
import z from 'zod';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
|
||||
|
|
@ -73,10 +73,13 @@ export default function GTBBairroForm({
|
|||
>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Bairro</DialogTitle>
|
||||
<DialogDescription>Crie ou edite um bairro</DialogDescription>
|
||||
<DialogTitle>
|
||||
Bairro
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Crie ou edite um bairro
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSave)} className="space-y-6">
|
||||
{/* Descrição */}
|
||||
|
|
@ -93,7 +96,6 @@ export default function GTBBairroForm({
|
|||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Situação */}
|
||||
<Controller
|
||||
name="situacao"
|
||||
|
|
@ -108,7 +110,6 @@ export default function GTBBairroForm({
|
|||
</div>
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Rodapé do Dialog */}
|
||||
<DialogFooter className="mt-4">
|
||||
<DialogClose asChild>
|
||||
|
|
|
|||
|
|
@ -1,205 +0,0 @@
|
|||
'use client';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
|
||||
import { ArrowUpDownIcon, EllipsisIcon, PencilIcon, Trash2Icon } from 'lucide-react';
|
||||
import { ColumnDef } from '@tanstack/react-table';
|
||||
|
||||
import GetNameInitials from '@/actions/text/GetNameInitials';
|
||||
import { DataTable } from '@/app/_components/dataTable/DataTable';
|
||||
|
||||
import TPessoaInterface from '../../../_interfaces/TPessoaInterface';
|
||||
import { FormatCPF } from '@/actions/CPF/FormatCPF';
|
||||
import { FormatPhone } from '@/actions/phone/FormatPhone';
|
||||
import { FormatDateTime } from '@/actions/dateTime/FormatDateTime';
|
||||
import empty from '@/actions/validations/empty';
|
||||
import { FormatCNPJ } from '@/actions/CNPJ/FormatCNPJ';
|
||||
|
||||
// Tipagem das props
|
||||
interface TPessoaJuridicaTableProps {
|
||||
data: TPessoaInterface[];
|
||||
onEdit: (item: TPessoaInterface, isEditingFormStatus: boolean) => void;
|
||||
onDelete: (item: TPessoaInterface, isEditingFormStatus: boolean) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Função para criar a definição das colunas da tabela
|
||||
*/
|
||||
function createPessoaColumns(
|
||||
onEdit: (item: TPessoaInterface, isEditingFormStatus: boolean) => void,
|
||||
onDelete: (item: TPessoaInterface, isEditingFormStatus: boolean) => void,
|
||||
): ColumnDef<TPessoaInterface>[] {
|
||||
return [
|
||||
// ID
|
||||
{
|
||||
accessorKey: 'pessoa_id',
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
# <ArrowUpDownIcon className="ml-1 h-4 w-4" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => Number(row.getValue('pessoa_id')),
|
||||
enableSorting: false,
|
||||
},
|
||||
|
||||
// Nome / Email / Foto
|
||||
{
|
||||
id: 'nome_completo',
|
||||
accessorFn: (row) => row,
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
Nome / Email <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
const pessoa = row.original;
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Nome e Email */}
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 capitalize">{pessoa.nome || '-'}</div>
|
||||
<div className="text-sm text-gray-500">
|
||||
{empty(pessoa.email) ? 'Email não informado' : pessoa.email}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
sortingFn: (a, b) =>
|
||||
(a.original.nome?.toLowerCase() || '').localeCompare(b.original.nome?.toLowerCase() || ''),
|
||||
},
|
||||
|
||||
// CPF
|
||||
{
|
||||
accessorKey: 'cpf_cnpj',
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
CNPJ <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => FormatCNPJ(row.getValue('cpf_cnpj')),
|
||||
},
|
||||
|
||||
// Telefone
|
||||
{
|
||||
accessorKey: 'telefone',
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
Telefone <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => FormatPhone(row.getValue('telefone')),
|
||||
},
|
||||
|
||||
// Cidade / UF
|
||||
{
|
||||
id: 'cidade_uf',
|
||||
accessorFn: (row) => `${row.cidade}/${row.uf}`,
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
Cidade/UF <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => <span>{row.getValue('cidade_uf') || '-'}</span>,
|
||||
sortingFn: (a, b) =>
|
||||
`${a.original.cidade}/${a.original.uf}`
|
||||
.toLowerCase()
|
||||
.localeCompare(`${b.original.cidade}/${b.original.uf}`.toLowerCase()),
|
||||
},
|
||||
|
||||
// Data de cadastro
|
||||
{
|
||||
accessorKey: 'data_cadastro',
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
Cadastro <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => FormatDateTime(row.getValue('data_cadastro')),
|
||||
sortingFn: 'datetime',
|
||||
},
|
||||
|
||||
// Ações
|
||||
{
|
||||
id: 'actions',
|
||||
header: 'Ações',
|
||||
cell: ({ row }) => {
|
||||
const pessoa = row.original;
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="cursor-pointer">
|
||||
<EllipsisIcon />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent side="left" align="start">
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem className="cursor-pointer" onSelect={() => onEdit(pessoa, true)}>
|
||||
<PencilIcon className="mr-2 h-4 w-4" />
|
||||
Editar
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer text-red-600"
|
||||
onSelect={() => onDelete(pessoa, true)}
|
||||
>
|
||||
<Trash2Icon className="mr-2 h-4 w-4" />
|
||||
Remover
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Componente principal da tabela
|
||||
*/
|
||||
export default function TPessoaJuridicaTable({
|
||||
data,
|
||||
onEdit,
|
||||
onDelete,
|
||||
}: TPessoaJuridicaTableProps) {
|
||||
const columns = createPessoaColumns(onEdit, onDelete);
|
||||
return (
|
||||
<div>
|
||||
<DataTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
filterColumn="nome_completo"
|
||||
filterPlaceholder="Buscar por nome ou email..."
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
export default interface TPessoaInterface {
|
||||
pessoa_id?: number;
|
||||
pessoa_tipo?: string;
|
||||
nome?: string;
|
||||
nacionalidade?: string;
|
||||
documento?: string;
|
||||
tb_documentotipo_id?: number;
|
||||
tb_profissao_id?: number;
|
||||
tb_estadocivil_id?: number;
|
||||
nome_pai?: string;
|
||||
nome_mae?: string;
|
||||
data_cadastro?: string; // ou Date
|
||||
naturalidade?: string;
|
||||
telefone?: string;
|
||||
endereco?: string;
|
||||
cidade?: string;
|
||||
uf?: string;
|
||||
data_nascimento?: string; // ou Date
|
||||
sexo?: string;
|
||||
tb_regimecomunhao_id?: number;
|
||||
pessoa_conjuge_id?: number;
|
||||
email?: string;
|
||||
documento_numero?: string;
|
||||
bairro?: string;
|
||||
cep?: string;
|
||||
documento_expedicao?: string; // ou Date
|
||||
documento_validade?: string; // ou Date
|
||||
observacao?: string;
|
||||
cpf_cnpj?: string;
|
||||
cpf_terceiro?: string;
|
||||
nome_fantasia?: string;
|
||||
texto?: string;
|
||||
ddd?: number;
|
||||
cert_casamento_numero?: string;
|
||||
cert_casamento_folha?: string;
|
||||
cert_casamento_livro?: string;
|
||||
cert_casamento_cartorio?: string;
|
||||
cert_casamento_data?: string; // ou Date
|
||||
cert_casamento_lei?: string;
|
||||
pessoa_conjuge_nome?: string;
|
||||
estrangeiro_nat?: string;
|
||||
estrangeiro_nat_tb_pais_id?: number;
|
||||
estrangeiro_res_tb_pais_id?: number;
|
||||
estrangeiro_res?: string;
|
||||
municipio_id?: number;
|
||||
documento_orgao?: string;
|
||||
documento_uf?: string;
|
||||
uf_residencia?: string;
|
||||
inscricao_municipal?: string;
|
||||
enviado_cnncnb?: boolean;
|
||||
data_auteracao?: string; // ou Date
|
||||
data_envioccn?: string; // ou Date
|
||||
ccnregistros_id?: number;
|
||||
observacao_envioccn?: string;
|
||||
observacao_envio_ccn?: string;
|
||||
deficiencias?: string;
|
||||
grau_instrucao?: string;
|
||||
cidade_nat_id?: number;
|
||||
tb_tipologradouro_id?: number;
|
||||
unidade?: string;
|
||||
numero_end?: string;
|
||||
foto?: string;
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
export default interface TPessoaJuridicaInterface {
|
||||
pessoa_id?: number;
|
||||
pessoa_tipo?: string;
|
||||
nome?: string;
|
||||
nacionalidade?: string;
|
||||
documento?: string;
|
||||
tb_documentotipo_id?: number;
|
||||
tb_profissao_id?: number;
|
||||
tb_estadocivil_id?: number;
|
||||
nome_pai?: string;
|
||||
nome_mae?: string;
|
||||
data_cadastro?: string; // ou Date
|
||||
naturalidade?: string;
|
||||
telefone?: string;
|
||||
endereco?: string;
|
||||
cidade?: string;
|
||||
uf?: string;
|
||||
data_nascimento?: string; // ou Date
|
||||
sexo?: string;
|
||||
tb_regimecomunhao_id?: number;
|
||||
pessoa_conjuge_id?: number;
|
||||
email?: string;
|
||||
documento_numero?: string;
|
||||
bairro?: string;
|
||||
cep?: string;
|
||||
documento_expedicao?: string; // ou Date
|
||||
documento_validade?: string; // ou Date
|
||||
observacao?: string;
|
||||
cpf_cnpj?: string;
|
||||
cpf_terceiro?: string;
|
||||
nome_fantasia?: string;
|
||||
texto?: string;
|
||||
ddd?: number;
|
||||
cert_casamento_numero?: string;
|
||||
cert_casamento_folha?: string;
|
||||
cert_casamento_livro?: string;
|
||||
cert_casamento_cartorio?: string;
|
||||
cert_casamento_data?: string; // ou Date
|
||||
cert_casamento_lei?: string;
|
||||
pessoa_conjuge_nome?: string;
|
||||
estrangeiro_nat?: string;
|
||||
estrangeiro_nat_tb_pais_id?: number;
|
||||
estrangeiro_res_tb_pais_id?: number;
|
||||
estrangeiro_res?: string;
|
||||
municipio_id?: number;
|
||||
documento_orgao?: string;
|
||||
documento_uf?: string;
|
||||
uf_residencia?: string;
|
||||
inscricao_municipal?: string;
|
||||
enviado_cnncnb?: boolean;
|
||||
data_auteracao?: string; // ou Date
|
||||
data_envioccn?: string; // ou Date
|
||||
ccnregistros_id?: number;
|
||||
observacao_envioccn?: string;
|
||||
observacao_envio_ccn?: string;
|
||||
deficiencias?: string;
|
||||
grau_instrucao?: string;
|
||||
cidade_nat_id?: number;
|
||||
tb_tipologradouro_id?: number;
|
||||
unidade?: string;
|
||||
numero_end?: string;
|
||||
foto?: string;
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
export default interface TPessoaJuridicaInterface {
|
||||
pessoa_representante_id: number;
|
||||
nome: string;
|
||||
tipo: string;
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
import z from 'zod';
|
||||
|
||||
export const TPessoaSchema = z.object({
|
||||
pessoa_id: z.number().optional(),
|
||||
pessoa_tipo: z.string().optional(),
|
||||
nome: z.string().min(1, 'O campo deve ser preenchido').max(120, 'O nome excede 120 caracteres'),
|
||||
nacionalidade: z.string().optional(),
|
||||
documento: z.string().optional(),
|
||||
tb_documentotipo_id: z.number().optional(),
|
||||
tb_profissao_id: z.number().optional(),
|
||||
tb_estadocivil_id: z.number().optional(),
|
||||
nome_pai: z.string().optional(),
|
||||
nome_mae: z.string().optional(),
|
||||
data_cadastro: z.string().optional(), // ou z.string().datetime()
|
||||
naturalidade: z.string().optional(),
|
||||
telefone: z.string().optional(),
|
||||
endereco: z.string().optional(),
|
||||
cidade: z.string().optional(),
|
||||
uf: z.string().optional(),
|
||||
data_nascimento: z.string().optional(), // ou z.string().datetime()
|
||||
sexo: z.string().optional(),
|
||||
tb_regimecomunhao_id: z.number().optional(),
|
||||
pessoa_conjuge_id: z.number().optional(),
|
||||
email: z.string().email().optional(),
|
||||
documento_numero: z.string().optional(),
|
||||
bairro: z.string().optional(),
|
||||
cep: z.string().optional(),
|
||||
documento_expedicao: z.string().optional(), // ou z.string().datetime()
|
||||
documento_validade: z.string().optional(), // ou z.string().datetime()
|
||||
observacao: z.string().optional(),
|
||||
cpf_cnpj: z.string().optional(),
|
||||
cpf_terceiro: z.string().optional(),
|
||||
nome_fantasia: z.string().optional(),
|
||||
texto: z.string().optional(),
|
||||
ddd: z.number().optional(),
|
||||
cert_casamento_numero: z.string().optional(),
|
||||
cert_casamento_folha: z.string().optional(),
|
||||
cert_casamento_livro: z.string().optional(),
|
||||
cert_casamento_cartorio: z.string().optional(),
|
||||
cert_casamento_data: z.string().optional(), // ou z.string().datetime()
|
||||
cert_casamento_lei: z.string().optional(),
|
||||
pessoa_conjuge_nome: z.string().optional(),
|
||||
estrangeiro_nat: z.string().optional(),
|
||||
estrangeiro_nat_tb_pais_id: z.number().optional(),
|
||||
estrangeiro_res_tb_pais_id: z.number().optional(),
|
||||
estrangeiro_res: z.string().optional(),
|
||||
municipio_id: z.number().optional(),
|
||||
documento_orgao: z.string().optional(),
|
||||
documento_uf: z.string().optional(),
|
||||
uf_residencia: z.string().optional(),
|
||||
inscricao_municipal: z.string().optional(),
|
||||
enviado_cnncnb: z.boolean().optional(),
|
||||
data_auteracao: z.string().optional(), // ou z.string().datetime()
|
||||
data_envioccn: z.string().optional(), // ou z.string().datetime()
|
||||
ccnregistros_id: z.number().optional(),
|
||||
observacao_envioccn: z.string().optional(),
|
||||
observacao_envio_ccn: z.string().optional(),
|
||||
deficiencias: z.string().optional(),
|
||||
grau_instrucao: z.string().optional(),
|
||||
cidade_nat_id: z.number().optional(),
|
||||
tb_tipologradouro_id: z.number().optional(),
|
||||
unidade: z.string().optional(),
|
||||
numero_end: z.string().optional(),
|
||||
});
|
||||
|
|
@ -28,8 +28,11 @@ const geistMono = Geist_Mono({
|
|||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Create Next App',
|
||||
description: 'Generated by create next app',
|
||||
title: 'SAAS - Orius Tecnologia',
|
||||
description: 'Evolução tecnológica com toque humano',
|
||||
icons: {
|
||||
icon: '/images/favicon.ico',
|
||||
},
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
|
|
@ -53,11 +56,15 @@ export default function RootLayout({
|
|||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem className="hidden md:block">
|
||||
<BreadcrumbLink href="#">Building Your Application</BreadcrumbLink>
|
||||
<BreadcrumbLink href="#">
|
||||
Building Your Application
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator className="hidden md:block" />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
|
||||
<BreadcrumbPage>
|
||||
Data Fetching
|
||||
</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
|
|
|
|||
12
src/app/_components/dataTable/SortableHeader.tsx
Normal file
12
src/app/_components/dataTable/SortableHeader.tsx
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { ArrowUpDownIcon } from "lucide-react";
|
||||
|
||||
export const SortableHeader = (label: string, column: any) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
||||
>
|
||||
{label}
|
||||
<ArrowUpDownIcon className="ml-1 h-4 w-4" />
|
||||
</Button>
|
||||
);
|
||||
|
|
@ -31,16 +31,21 @@ import {
|
|||
TableHeader,
|
||||
TableRow,
|
||||
} from '@/components/ui/table';
|
||||
import { ChevronLeftIcon, ChevronRightIcon, EyeIcon } from 'lucide-react';
|
||||
import {
|
||||
ChevronLeftIcon,
|
||||
ChevronRightIcon,
|
||||
EyeIcon,
|
||||
} from 'lucide-react';
|
||||
|
||||
// Tipagem genérica
|
||||
export interface DataTableProps<TData> {
|
||||
data: TData[];
|
||||
data?: TData[] | null;
|
||||
columns: ColumnDef<TData, any>[];
|
||||
filterColumn?: string; // Define qual coluna será usada para filtro
|
||||
filterPlaceholder?: string;
|
||||
onEdit?: (item: TData) => void;
|
||||
onDelete?: (item: TData) => void;
|
||||
onRowClick?: (item: TData) => void;
|
||||
}
|
||||
|
||||
export function DataTable<TData>({
|
||||
|
|
@ -50,7 +55,11 @@ export function DataTable<TData>({
|
|||
filterPlaceholder = 'Buscar...',
|
||||
onEdit,
|
||||
onDelete,
|
||||
onRowClick,
|
||||
}: DataTableProps<TData>) {
|
||||
// Garante que data sempre seja array
|
||||
const safeData = Array.isArray(data) ? data : [];
|
||||
|
||||
// Estados internos da tabela
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
|
||||
|
|
@ -59,8 +68,40 @@ export function DataTable<TData>({
|
|||
|
||||
// Configuração da tabela
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns,
|
||||
data: safeData,
|
||||
columns: [
|
||||
...columns,
|
||||
...(onEdit || onDelete
|
||||
? [
|
||||
{
|
||||
id: 'actions',
|
||||
header: 'Ações',
|
||||
cell: ({ row }: any) => (
|
||||
<div className="flex gap-2">
|
||||
{onEdit && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => onEdit(row.original)}
|
||||
>
|
||||
Editar
|
||||
</Button>
|
||||
)}
|
||||
{onDelete && (
|
||||
<Button
|
||||
variant="destructive"
|
||||
size="sm"
|
||||
onClick={() => onDelete(row.original)}
|
||||
>
|
||||
Excluir
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
} as ColumnDef<TData, any>,
|
||||
]
|
||||
: []),
|
||||
],
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
|
|
@ -84,9 +125,9 @@ export function DataTable<TData>({
|
|||
{filterColumn && (
|
||||
<Input
|
||||
placeholder={filterPlaceholder}
|
||||
value={(table.getColumn(filterColumn as string)?.getFilterValue() as string) ?? ''}
|
||||
value={(table.getColumn(filterColumn)?.getFilterValue() as string) ?? ''}
|
||||
onChange={(e) =>
|
||||
table.getColumn(filterColumn as string)?.setFilterValue(e.target.value)
|
||||
table.getColumn(filterColumn)?.setFilterValue(e.target.value)
|
||||
}
|
||||
className="w-full"
|
||||
/>
|
||||
|
|
@ -95,7 +136,8 @@ export function DataTable<TData>({
|
|||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" className="ml-auto cursor-pointer">
|
||||
<EyeIcon /> Colunas visíveis
|
||||
<EyeIcon className="mr-2 h-4 w-4" />
|
||||
Colunas visíveis
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
|
|
@ -133,9 +175,13 @@ export function DataTable<TData>({
|
|||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows.length ? (
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow key={row.id} className="cursor-pointer">
|
||||
<TableRow
|
||||
key={row.id}
|
||||
className={onRowClick ? 'cursor-pointer hover:bg-muted/50' : ''}
|
||||
onClick={() => onRowClick?.(row.original)}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
|
|
@ -145,7 +191,10 @@ export function DataTable<TData>({
|
|||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
<TableCell
|
||||
colSpan={table.getAllColumns().length}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
Nenhum resultado encontrado.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
|
@ -155,27 +204,55 @@ export function DataTable<TData>({
|
|||
</div>
|
||||
|
||||
{/* Paginação */}
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<Button
|
||||
className="cursor-pointer"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
>
|
||||
<ChevronLeftIcon />
|
||||
Anterior
|
||||
</Button>
|
||||
<Button
|
||||
className="cursor-pointer"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
>
|
||||
Próxima
|
||||
<ChevronRightIcon />
|
||||
</Button>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Página {table.getState().pagination.pageIndex + 1} de {table.getPageCount()}
|
||||
</span>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.setPageIndex(0)}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
aria-label="Primeira página"
|
||||
className='cursor-pointer'
|
||||
>
|
||||
Primeira
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
aria-label="Página anterior"
|
||||
className='cursor-pointer'
|
||||
>
|
||||
<ChevronLeftIcon className="h-4 w-4" />
|
||||
Anterior
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
aria-label="Próxima página"
|
||||
className='cursor-pointer'
|
||||
>
|
||||
Próxima
|
||||
<ChevronRightIcon className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
|
||||
disabled={!table.getCanNextPage()}
|
||||
aria-label="Última página"
|
||||
className='cursor-pointer'
|
||||
>
|
||||
Última
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import {
|
|||
} from '@/components/ui/sidebar';
|
||||
|
||||
import useGUsuarioGetJWTHook from '@/hooks/auth/useGUsuarioGetJWTHook';
|
||||
import Image from 'next/image';
|
||||
|
||||
// This is sample data.
|
||||
const data = {
|
||||
|
|
@ -75,6 +76,22 @@ const data = {
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Pessoas',
|
||||
url: '#',
|
||||
icon: SquareTerminal,
|
||||
isActive: false,
|
||||
items: [
|
||||
{
|
||||
title: 'Físicas',
|
||||
url: '/administrativo/pessoas/fisicas',
|
||||
},
|
||||
{
|
||||
title: 'Jurídicas',
|
||||
url: '/administrativo/pessoas/fisicas',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Cadastros',
|
||||
url: '#',
|
||||
|
|
@ -149,12 +166,8 @@ const data = {
|
|||
url: '/cadastros/censec/',
|
||||
},
|
||||
{
|
||||
title: 'Pessoas/Físicas',
|
||||
url: '/cadastros/pessoa/fisica',
|
||||
},
|
||||
{
|
||||
title: 'Pessoas/Jurídica',
|
||||
url: '/cadastros/pessoa/juridica',
|
||||
title: 'Imovel/Urbano',
|
||||
url: '/cadastros/imoveis/urbanos',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -226,7 +239,6 @@ const data = {
|
|||
|
||||
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
||||
const { userAuthenticated } = useGUsuarioGetJWTHook();
|
||||
|
||||
return (
|
||||
<Sidebar collapsible="icon" {...props}>
|
||||
<SidebarHeader>
|
||||
|
|
@ -236,28 +248,34 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
|||
<a href="#">
|
||||
<div className="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg">
|
||||
<GalleryVerticalEnd className="size-4" />
|
||||
<Image
|
||||
src="/images/logo-abb.png"
|
||||
alt="Logo do site"
|
||||
width={100}
|
||||
height={100}
|
||||
className='rounded-lg'
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-0.5 leading-none">
|
||||
<span className="font-semibold">Orius Tecnologia</span>
|
||||
|
||||
<span className="">25.9.1</span>
|
||||
<span className="font-semibold">
|
||||
Orius Tecnologia
|
||||
</span>
|
||||
<span className="">
|
||||
25.9.1
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarHeader>
|
||||
|
||||
<SidebarContent>
|
||||
<NavMain items={data.navMain} />
|
||||
<NavProjects projects={data.projects} />
|
||||
</SidebarContent>
|
||||
|
||||
<SidebarFooter>
|
||||
{userAuthenticated?.data ? <NavUser user={userAuthenticated.data} /> : 'Carregando...'}
|
||||
</SidebarFooter>
|
||||
|
||||
<SidebarRail />
|
||||
</Sidebar>
|
||||
);
|
||||
|
|
|
|||
5
src/enums/ImovelConstrucaoEnum.ts
Normal file
5
src/enums/ImovelConstrucaoEnum.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export const ImovelConstrucaoEnum: { [key: number]: string } = {
|
||||
0: 'Construção averbada',
|
||||
1: 'Em construção',
|
||||
2: 'Não se aplica',
|
||||
};
|
||||
4
src/enums/ImovelTipoClasseEnum.ts
Normal file
4
src/enums/ImovelTipoClasseEnum.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export const ImovelTipoClasseEnum: { [key: number]: string } = {
|
||||
1: 'Urbano',
|
||||
3: 'Rural',
|
||||
};
|
||||
22
src/enums/ImovelTipoEnum.ts
Normal file
22
src/enums/ImovelTipoEnum.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
export const ImovelTipoEnum: { [key: number]: string } = {
|
||||
15: 'Loja',
|
||||
31: 'Galpão',
|
||||
65: 'Apartamento',
|
||||
67: 'Casa',
|
||||
69: 'Fazenda / Sítio / Chácara',
|
||||
71: 'Terreno / Fração',
|
||||
89: 'Outros',
|
||||
90: 'Sala',
|
||||
91: 'Conjunto de salas',
|
||||
92: 'Sobreloja',
|
||||
17: 'Sala / Conjunto',
|
||||
33: 'Prédio Comercial',
|
||||
35: 'Prédio Residencial',
|
||||
73: 'Sala ou Loja',
|
||||
85: 'Construções',
|
||||
87: 'Desmembramento',
|
||||
93: 'Vaga de Garagem',
|
||||
94: 'Laje',
|
||||
95: 'Estacionamento',
|
||||
96: 'Barraco'
|
||||
};
|
||||
5
src/enums/ImovelTipoRegistro.ts
Normal file
5
src/enums/ImovelTipoRegistro.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export enum ImovelTipoRegistro {
|
||||
M = 'Matrícula',
|
||||
T = 'Transcrição',
|
||||
I = 'Inscrição',
|
||||
}
|
||||
|
|
@ -1,41 +1,21 @@
|
|||
'use client';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
|
||||
import { ArrowUpDownIcon, EllipsisIcon, PencilIcon, Trash2Icon } from 'lucide-react';
|
||||
import { ColumnDef } from '@tanstack/react-table';
|
||||
|
||||
import GetNameInitials from '@/actions/text/GetNameInitials';
|
||||
import { DataTable } from '@/app/_components/dataTable/DataTable';
|
||||
|
||||
import TPessoaInterface from '../../_interfaces/TPessoaInterface';
|
||||
import { FormatCPF } from '@/actions/CPF/FormatCPF';
|
||||
import { FormatPhone } from '@/actions/phone/FormatPhone';
|
||||
import { FormatDateTime } from '@/actions/dateTime/FormatDateTime';
|
||||
import empty from '@/actions/validations/empty';
|
||||
|
||||
// Tipagem das props
|
||||
interface TPessoaTableProps {
|
||||
data: TPessoaInterface[];
|
||||
onEdit: (item: TPessoaInterface, isEditingFormStatus: boolean) => void;
|
||||
onDelete: (item: TPessoaInterface, isEditingFormStatus: boolean) => void;
|
||||
}
|
||||
import { FormatCPF } from "@/actions/CPF/FormatCPF";
|
||||
import { FormatDateTime } from "@/actions/dateTime/FormatDateTime";
|
||||
import { FormatPhone } from "@/actions/phone/FormatPhone";
|
||||
import GetNameInitials from "@/actions/text/GetNameInitials";
|
||||
import empty from "@/actions/validations/empty";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import TPessoaFisicaInterface from "@/packages/administrativo/interfaces/TPessoa/TPessoaFisica/TPessoaFisicaInterface";
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import { ArrowUpDownIcon, EllipsisIcon, PencilIcon, Trash2Icon } from "lucide-react";
|
||||
|
||||
/**
|
||||
* Função para criar a definição das colunas da tabela
|
||||
*/
|
||||
function createPessoaColumns(
|
||||
onEdit: (item: TPessoaInterface, isEditingFormStatus: boolean) => void,
|
||||
onDelete: (item: TPessoaInterface, isEditingFormStatus: boolean) => void,
|
||||
): ColumnDef<TPessoaInterface>[] {
|
||||
export function TPessoaFisicaColumns(
|
||||
onEdit: (item: TPessoaFisicaInterface, isEditingFormStatus: boolean) => void,
|
||||
onDelete: (item: TPessoaFisicaInterface, isEditingFormStatus: boolean) => void,
|
||||
): ColumnDef<TPessoaFisicaInterface>[] {
|
||||
return [
|
||||
// ID
|
||||
{
|
||||
|
|
@ -197,20 +177,3 @@ function createPessoaColumns(
|
|||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Componente principal da tabela
|
||||
*/
|
||||
export default function TPessoaTable({ data, onEdit, onDelete }: TPessoaTableProps) {
|
||||
const columns = createPessoaColumns(onEdit, onDelete);
|
||||
return (
|
||||
<div>
|
||||
<DataTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
filterColumn="nome_completo"
|
||||
filterPlaceholder="Buscar por nome ou email..."
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import z from 'zod';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
|
|
@ -25,7 +22,6 @@ import {
|
|||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
|
||||
import { TPessoaSchema } from '../../_schemas/TPessoaSchema';
|
||||
import LoadingButton from '@/app/_components/loadingButton/LoadingButton';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import {
|
||||
|
|
@ -33,14 +29,13 @@ import {
|
|||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { CheckIcon, ChevronsUpDownIcon, HouseIcon, IdCardIcon, UserIcon } from 'lucide-react';
|
||||
import { Sexo } from '@/enums/SexoEnum';
|
||||
import { useGTBEstadoCivilReadHook } from '../../_hooks/g_tb_estadocivil/useGTBEstadoCivilReadHook';
|
||||
import { useGTBEstadoCivilReadHook } from '../../../../../app/(protected)/(cadastros)/cadastros/_hooks/g_tb_estadocivil/useGTBEstadoCivilReadHook';
|
||||
import GetCapitalize from '@/actions/text/GetCapitalize';
|
||||
import { useGTBRegimeComunhaoReadHook } from '../../_hooks/g_tb_regimecomunhao/useGTBRegimeComunhaoReadHook';
|
||||
import { useGTBProfissaoReadHook } from '../../_hooks/g_tb_profissao/useGTBProfissaoReadHook';
|
||||
import { useGTBRegimeComunhaoReadHook } from '../../../../../app/(protected)/(cadastros)/cadastros/_hooks/g_tb_regimecomunhao/useGTBRegimeComunhaoReadHook';
|
||||
import { useGTBProfissaoReadHook } from '../../../../../app/(protected)/(cadastros)/cadastros/_hooks/g_tb_profissao/useGTBProfissaoReadHook';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||
import {
|
||||
Command,
|
||||
|
|
@ -51,50 +46,36 @@ import {
|
|||
CommandList,
|
||||
} from '@/components/ui/command';
|
||||
import { cn } from '@/lib/utils';
|
||||
import TPessoaFisicaFormInterface from '../../../interfaces/TPessoa/TPessoaFisica/TPessoaFisicaFormInterface';
|
||||
import { ResetFormIfData } from '@/actions/form/ResetFormIfData';
|
||||
import { useTPessoaForm } from '@/packages/administrativo/hooks/t_pessoa/fisica/usetTPessoaFormHook';
|
||||
|
||||
type FormValues = z.infer<typeof TPessoaSchema>;
|
||||
|
||||
interface TPessoaFormProps {
|
||||
isOpen: boolean;
|
||||
data: FormValues | null;
|
||||
onClose: (item: null, isFormStatus: boolean) => void;
|
||||
onSave: (data: FormValues) => void;
|
||||
buttonIsLoading: boolean;
|
||||
}
|
||||
|
||||
export default function TCensecForm({
|
||||
export default function TPessoaFisicaForm({
|
||||
isOpen,
|
||||
data,
|
||||
onClose,
|
||||
onSave,
|
||||
buttonIsLoading,
|
||||
}: TPessoaFormProps) {
|
||||
}: TPessoaFisicaFormInterface) {
|
||||
|
||||
const { gTBProfissao, fetchGTBProfissao } = useGTBProfissaoReadHook();
|
||||
const { gTBEstadoCivil, fetchGTBEstadoCivil } = useGTBEstadoCivilReadHook();
|
||||
const { gTBRegimeComunhao, fetchGTBRegimeComunhao } = useGTBRegimeComunhaoReadHook();
|
||||
|
||||
// Inicializa o react-hook-form com schema zod
|
||||
const form = useForm<FormValues>({
|
||||
resolver: zodResolver(TPessoaSchema),
|
||||
defaultValues: {
|
||||
nome: '',
|
||||
pessoa_id: 0,
|
||||
},
|
||||
});
|
||||
const form = useTPessoaForm({});
|
||||
|
||||
// Atualiza o formulário quando recebe dados para edição
|
||||
useEffect(() => {
|
||||
// Função para carregar os dados de forma sincrona
|
||||
const loadData = async () => {
|
||||
// Se existir dados, reseta o formulário com os dados informados
|
||||
if (data) form.reset(data);
|
||||
|
||||
ResetFormIfData(form, data)
|
||||
// Aguarda a busca terminar
|
||||
await fetchGTBProfissao();
|
||||
await fetchGTBEstadoCivil();
|
||||
await fetchGTBRegimeComunhao();
|
||||
};
|
||||
|
||||
// Dispara a função
|
||||
loadData();
|
||||
}, [data, form]);
|
||||
|
|
@ -108,10 +89,13 @@ export default function TCensecForm({
|
|||
>
|
||||
<DialogContent className="w-full max-w-full p-6 sm:max-w-3xl md:max-w-4xl lg:max-w-5xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Pessoa</DialogTitle>
|
||||
<DialogDescription>Preencha os dados da pessoa</DialogDescription>
|
||||
<DialogTitle>
|
||||
Pessoa Física
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Preencha os dados da pessoa
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSave)} className="space-y-6">
|
||||
{/* Tabs */}
|
||||
|
|
@ -128,7 +112,6 @@ export default function TCensecForm({
|
|||
<IdCardIcon /> Documentos
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
{/* Dados Pessoais */}
|
||||
<TabsContent value="dadosPessoais" className="space-y-4">
|
||||
<div className="grid w-full grid-cols-12 gap-4">
|
||||
|
|
@ -312,10 +295,10 @@ export default function TCensecForm({
|
|||
className="justify-between"
|
||||
>
|
||||
{field.value
|
||||
? gTBEstadoCivil.find(
|
||||
(item) =>
|
||||
String(item.tb_estadocivil_id) === String(field.value),
|
||||
)?.descricao
|
||||
? gTBEstadoCivil?.find(
|
||||
(item) =>
|
||||
String(item.tb_estadocivil_id) === String(field.value),
|
||||
)?.descricao
|
||||
: 'Escolha o estado civil'}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
|
|
@ -378,11 +361,11 @@ export default function TCensecForm({
|
|||
className="justify-between"
|
||||
>
|
||||
{field.value
|
||||
? gTBRegimeComunhao.find(
|
||||
(item) =>
|
||||
String(item.tb_regimecomunhao_id) ===
|
||||
String(field.value),
|
||||
)?.descricao
|
||||
? gTBRegimeComunhao?.find(
|
||||
(item) =>
|
||||
String(item.tb_regimecomunhao_id) ===
|
||||
String(field.value),
|
||||
)?.descricao
|
||||
: 'Escolha o regime'}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
|
|
@ -446,10 +429,10 @@ export default function TCensecForm({
|
|||
className="justify-between"
|
||||
>
|
||||
{field.value
|
||||
? gTBProfissao.find(
|
||||
(item) =>
|
||||
String(item.tb_profissao_id) === String(field.value),
|
||||
)?.descricao
|
||||
? gTBProfissao?.find(
|
||||
(item) =>
|
||||
String(item.tb_profissao_id) === String(field.value),
|
||||
)?.descricao
|
||||
: 'Escolha a profissão'}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
|
|
@ -534,7 +517,6 @@ export default function TCensecForm({
|
|||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
{/* Endereço */}
|
||||
<TabsContent value="endereco" className="space-y-4">
|
||||
<div className="grid w-full grid-cols-12 gap-4">
|
||||
|
|
@ -700,7 +682,6 @@ export default function TCensecForm({
|
|||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
{/* Documentos */}
|
||||
<TabsContent value="documentos" className="space-y-4">
|
||||
<div className="grid w-full grid-cols-12 gap-4">
|
||||
|
|
@ -720,7 +701,6 @@ export default function TCensecForm({
|
|||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Número */}
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-5">
|
||||
<FormField
|
||||
|
|
@ -737,7 +717,6 @@ export default function TCensecForm({
|
|||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* CPF */}
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-4">
|
||||
<FormField
|
||||
|
|
@ -754,7 +733,6 @@ export default function TCensecForm({
|
|||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Órgão Emissor */}
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-4">
|
||||
<FormField
|
||||
|
|
@ -775,7 +753,6 @@ export default function TCensecForm({
|
|||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* UF */}
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-2">
|
||||
<FormField
|
||||
|
|
@ -792,7 +769,6 @@ export default function TCensecForm({
|
|||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Data de Expedição */}
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-3">
|
||||
<FormField
|
||||
|
|
@ -809,7 +785,6 @@ export default function TCensecForm({
|
|||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Validade */}
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-3">
|
||||
<FormField
|
||||
|
|
@ -829,7 +804,6 @@ export default function TCensecForm({
|
|||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
{/* Rodapé do Dialog */}
|
||||
<DialogFooter className="mt-4">
|
||||
<DialogClose asChild>
|
||||
|
|
@ -849,7 +823,6 @@ export default function TCensecForm({
|
|||
loading={buttonIsLoading}
|
||||
/>
|
||||
</DialogFooter>
|
||||
|
||||
{/* Campo oculto */}
|
||||
<input type="hidden" {...form.register('pessoa_id')} />
|
||||
</form>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
'use client';
|
||||
|
||||
import { DataTable } from '@/app/_components/dataTable/DataTable';
|
||||
import TPessoaFisicaTableInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaFisica/TPessoaFisicaTableInterface';
|
||||
import { TPessoaFisicaColumns } from './TPessoaFisicaColumns';
|
||||
|
||||
/**
|
||||
* Componente principal da tabela
|
||||
*/
|
||||
export default function TPessoaFisicaTable({ data, onEdit, onDelete }: TPessoaFisicaTableInterface) {
|
||||
const columns = TPessoaFisicaColumns(onEdit, onDelete);
|
||||
return (
|
||||
<div>
|
||||
<DataTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
filterColumn="nome_completo"
|
||||
filterPlaceholder="Buscar por nome ou email..."
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
import { FormatCNPJ } from "@/actions/CNPJ/FormatCNPJ";
|
||||
import { FormatDateTime } from "@/actions/dateTime/FormatDateTime";
|
||||
import { FormatPhone } from "@/actions/phone/FormatPhone";
|
||||
import empty from "@/actions/validations/empty";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import TPessoaJuridicaInterface from "@/packages/administrativo/interfaces/TPessoa/TPessoaJuridica/TPessoaJuridicaInterface";
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import { ArrowUpDownIcon, EllipsisIcon, PencilIcon, Trash2Icon } from "lucide-react";
|
||||
|
||||
export default function TPessoaJuridicaColumns(
|
||||
onEdit: (item: TPessoaJuridicaInterface, isEditingFormStatus: boolean) => void,
|
||||
onDelete: (item: TPessoaJuridicaInterface, isEditingFormStatus: boolean) => void,
|
||||
): ColumnDef<TPessoaJuridicaInterface>[] {
|
||||
return [
|
||||
// ID
|
||||
{
|
||||
accessorKey: 'pessoa_id',
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
# <ArrowUpDownIcon className="ml-1 h-4 w-4" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => Number(row.getValue('pessoa_id')),
|
||||
enableSorting: false,
|
||||
},
|
||||
|
||||
// Nome / Email / Foto
|
||||
{
|
||||
id: 'nome_completo',
|
||||
accessorFn: (row) => row,
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
Nome / Email <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
const pessoa = row.original;
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
{/* Nome e Email */}
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 capitalize">{pessoa.nome || '-'}</div>
|
||||
<div className="text-sm text-gray-500">
|
||||
{empty(pessoa.email) ? 'Email não informado' : pessoa.email}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
sortingFn: (a, b) =>
|
||||
(a.original.nome?.toLowerCase() || '').localeCompare(b.original.nome?.toLowerCase() || ''),
|
||||
},
|
||||
|
||||
// CPF
|
||||
{
|
||||
accessorKey: 'cpf_cnpj',
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
CNPJ <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => FormatCNPJ(row.getValue('cpf_cnpj')),
|
||||
},
|
||||
|
||||
// Telefone
|
||||
{
|
||||
accessorKey: 'telefone',
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
Telefone <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => FormatPhone(row.getValue('telefone')),
|
||||
},
|
||||
|
||||
// Cidade / UF
|
||||
{
|
||||
id: 'cidade_uf',
|
||||
accessorFn: (row) => `${row.cidade}/${row.uf}`,
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
Cidade/UF <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => <span>{row.getValue('cidade_uf') || '-'}</span>,
|
||||
sortingFn: (a, b) =>
|
||||
`${a.original.cidade}/${a.original.uf}`
|
||||
.toLowerCase()
|
||||
.localeCompare(`${b.original.cidade}/${b.original.uf}`.toLowerCase()),
|
||||
},
|
||||
|
||||
// Data de cadastro
|
||||
{
|
||||
accessorKey: 'data_cadastro',
|
||||
header: ({ column }) => (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
|
||||
>
|
||||
Cadastro <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
|
||||
</Button>
|
||||
),
|
||||
cell: ({ row }) => FormatDateTime(row.getValue('data_cadastro')),
|
||||
sortingFn: 'datetime',
|
||||
},
|
||||
|
||||
// Ações
|
||||
{
|
||||
id: 'actions',
|
||||
header: 'Ações',
|
||||
cell: ({ row }) => {
|
||||
const pessoa = row.original;
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="cursor-pointer">
|
||||
<EllipsisIcon />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent side="left" align="start">
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem className="cursor-pointer" onSelect={() => onEdit(pessoa, true)}>
|
||||
<PencilIcon className="mr-2 h-4 w-4" />
|
||||
Editar
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
className="cursor-pointer text-red-600"
|
||||
onSelect={() => onDelete(pessoa, true)}
|
||||
>
|
||||
<Trash2Icon className="mr-2 h-4 w-4" />
|
||||
Remover
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
|
@ -25,12 +25,12 @@ import {
|
|||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
|
||||
import { TPessoaSchema } from '../../../_schemas/TPessoaSchema';
|
||||
import { TPessoaSchema } from '../../../schemas/TPessoa/TPessoaSchema';
|
||||
import LoadingButton from '@/app/_components/loadingButton/LoadingButton';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { HouseIcon, IdCardIcon, UserIcon } from 'lucide-react';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { useTPessoaRepresentanteIndexHook } from '../../../_hooks/t_pessoa_representante/useTPessoaRepresentanteIndexHook';
|
||||
import { useTPessoaRepresentanteIndexHook } from '../../../hooks/t_pessoa_representante/useTPessoaRepresentanteIndexHook';
|
||||
import TPessoaRepresentantePage from '../../t_pessoa_representante/TPessoaRepresentantePage';
|
||||
|
||||
type FormValues = z.infer<typeof TPessoaSchema>;
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
'use client';
|
||||
|
||||
import { DataTable } from '@/app/_components/dataTable/DataTable';
|
||||
|
||||
import TPessoaJuridicaColumns from './TPessoaJuridicaColumns';
|
||||
import TPessoaJuridicaTableInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaJuridica/TPessoaJuridicaTableInterface';
|
||||
|
||||
/**
|
||||
* Componente principal da tabela
|
||||
*/
|
||||
export default function TPessoaJuridicaTable({
|
||||
data,
|
||||
onEdit,
|
||||
onDelete,
|
||||
}: TPessoaJuridicaTableInterface) {
|
||||
const columns = TPessoaJuridicaColumns(onEdit, onDelete);
|
||||
return (
|
||||
<div>
|
||||
<DataTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
filterColumn="nome_completo"
|
||||
filterPlaceholder="Buscar por nome ou email..."
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import TImovelInterface from "../../interfaces/TImovelInterface";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
EllipsisIcon,
|
||||
PencilIcon,
|
||||
Trash2Icon,
|
||||
} from "lucide-react";
|
||||
import { FormatDateTime } from "@/actions/dateTime/FormatDateTime";
|
||||
import { FormatCEP } from "@/actions/CEP/FormatCEP";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { ImovelTipoRegistro } from "@/enums/ImovelTipoRegistro";
|
||||
import { SortableHeader } from "@/app/_components/dataTable/SortableHeader";
|
||||
|
||||
export default function TImovelColumns(
|
||||
onEdit: (item: TImovelInterface, isEditingFormStatus: boolean) => void,
|
||||
onDelete: (item: TImovelInterface, isEditingFormStatus: boolean) => void
|
||||
): ColumnDef<TImovelInterface>[] {
|
||||
return [
|
||||
// ID
|
||||
{
|
||||
accessorKey: "imovel_id",
|
||||
header: ({ column }) => SortableHeader("#", column),
|
||||
cell: ({ row }) => Number(row.getValue("imovel_id")),
|
||||
enableSorting: false,
|
||||
},
|
||||
|
||||
// Tipo Registro
|
||||
{
|
||||
accessorKey: "tipo_registro",
|
||||
header: ({ column }) => SortableHeader("Tipo Registro", column),
|
||||
cell: ({ row }) => {
|
||||
const value = row.getValue("tipo_registro") as keyof typeof ImovelTipoRegistro;
|
||||
return ImovelTipoRegistro[value] ?? value;
|
||||
},
|
||||
},
|
||||
|
||||
// Número
|
||||
{
|
||||
accessorKey: "numero",
|
||||
header: ({ column }) => SortableHeader("Número", column),
|
||||
cell: ({ row }) => row.getValue("numero"),
|
||||
},
|
||||
|
||||
// UF / Cidade / Bairro
|
||||
{
|
||||
id: "uf_cidade_bairro",
|
||||
accessorFn: (row) => row,
|
||||
header: ({ column }) => SortableHeader("Cidade / UF / Bairro", column),
|
||||
cell: ({ row }) => {
|
||||
const imovel = row.original;
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<span className="font-semibold text-gray-900 capitalize">
|
||||
{imovel.cidade}/{imovel.uf}
|
||||
</span>
|
||||
<span className="text-sm text-gray-500">{imovel.gtb_descricao}</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
sortingFn: (a, b) =>
|
||||
(a.original.cartorio?.toLowerCase() || "").localeCompare(
|
||||
b.original.cartorio?.toLowerCase() || ""
|
||||
),
|
||||
},
|
||||
|
||||
// CEP
|
||||
{
|
||||
accessorKey: "cep",
|
||||
header: ({ column }) => SortableHeader("CEP", column),
|
||||
cell: ({ row }) => FormatCEP(row.getValue("cep")),
|
||||
},
|
||||
|
||||
// Data de Registro
|
||||
{
|
||||
accessorKey: "data_registro",
|
||||
header: ({ column }) => SortableHeader("Cadastro", column),
|
||||
cell: ({ row }) => FormatDateTime(row.getValue("data_registro")),
|
||||
sortingFn: "datetime",
|
||||
},
|
||||
|
||||
// Ações
|
||||
{
|
||||
id: "actions",
|
||||
header: "Ações",
|
||||
cell: ({ row }) => {
|
||||
const imovel = row.original;
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon">
|
||||
<EllipsisIcon />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent side="left" align="start">
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem onSelect={() => onEdit(imovel, true)}>
|
||||
<PencilIcon className="mr-2 h-4 w-4" />
|
||||
Editar
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
className="text-red-600"
|
||||
onSelect={() => onDelete(imovel, true)}
|
||||
>
|
||||
<Trash2Icon className="mr-2 h-4 w-4" />
|
||||
Remover
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
},
|
||||
];
|
||||
}
|
||||
386
src/packages/administrativo/components/t_imovel/TImovelForm.tsx
Normal file
386
src/packages/administrativo/components/t_imovel/TImovelForm.tsx
Normal file
|
|
@ -0,0 +1,386 @@
|
|||
'use client';
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
|
||||
import { TImovelFormValues, TImovelSchema } from '../../schemas/TImovelSchema';
|
||||
import LoadingButton from '@/app/_components/loadingButton/LoadingButton';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { CheckIcon, ChevronsUpDownIcon, HouseIcon, IdCardIcon } from 'lucide-react';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/ui/select';
|
||||
import TImovelUnidadePage from '../t_imovel_unidade/TImovelUnidadePage';
|
||||
import { ImovelTipoRegistro } from '@/enums/ImovelTipoRegistro';
|
||||
import { ImovelTipoClasseEnum } from '@/enums/ImovelTipoClasseEnum';
|
||||
import { ResetFormIfData } from '@/actions/form/ResetFormIfData';
|
||||
import { TImovelFormProps } from './TImovelFormProps';
|
||||
import { useGTBBairroReadHook } from '../../../../app/(protected)/(cadastros)/cadastros/_hooks/g_tb_bairro/useGTBBairroReadHook';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/components/ui/command';
|
||||
import { cn } from '@/lib/utils';
|
||||
import GetCapitalize from '@/actions/text/GetCapitalize';
|
||||
|
||||
export default function TImovelForm({ isOpen, data, onClose, onSave, buttonIsLoading }: TImovelFormProps) {
|
||||
|
||||
const { gTBBairro, fetchGTBBairro } = useGTBBairroReadHook();
|
||||
|
||||
// Inicializa o react-hook-form com schema zod
|
||||
const form = useForm<TImovelFormValues>({
|
||||
resolver: zodResolver(TImovelSchema),
|
||||
defaultValues: {},
|
||||
});
|
||||
|
||||
// Atualiza o formulário quando recebe dados para edição
|
||||
useEffect(() => {
|
||||
|
||||
// Se existir dados, reseta o formulário com os mesmos
|
||||
ResetFormIfData(form, data);
|
||||
|
||||
// Função sincrona para carregamento de dados
|
||||
async function loadData() {
|
||||
|
||||
// Busca os bairros
|
||||
await fetchGTBBairro();
|
||||
|
||||
}
|
||||
|
||||
// Executa a função
|
||||
loadData();
|
||||
|
||||
}, [data, form]);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) onClose(null, false);
|
||||
}}
|
||||
>
|
||||
<DialogContent className="w-full max-w-full p-6 sm:max-w-3xl md:max-w-4xl lg:max-w-5xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
Imóvel Urbano
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Cadastro de imóvel urbano
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSave)} className="space-y-6">
|
||||
{/* Tabs */}
|
||||
<Tabs defaultValue="dadosDoImovel" className="space-y-4">
|
||||
<TabsList className="flex w-full">
|
||||
<TabsTrigger className="flex-1 text-center cursor-pointer" value="dadosDoImovel">
|
||||
<HouseIcon className="me-1 inline" />
|
||||
Dados do Imóvel
|
||||
</TabsTrigger>
|
||||
<TabsTrigger className="flex-1 text-center cursor-pointer" value="unidades">
|
||||
<IdCardIcon className="inline" />
|
||||
Unidades
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
{/* Dados do Imóvel */}
|
||||
<TabsContent value="dadosDoImovel" className="space-y-4">
|
||||
<div className="grid w-full grid-cols-12 gap-4">
|
||||
{/* UF */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-2">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="uf"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>UF</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} type='text' placeholder="UF" maxLength={2} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* CEP */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="cep"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>CEP</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} type='text' placeholder="Digite o CEP" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Cidade */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="cidade"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Cidade</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} type="text" placeholder="Digite a cidade" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Bairro */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="tb_bairro_id"
|
||||
render={({ field }) => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Bairro</FormLabel>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl className="w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className="justify-between"
|
||||
>
|
||||
{field.value
|
||||
? gTBBairro.find(
|
||||
(item) =>
|
||||
String(item.tb_bairro_id) === String(field.value),
|
||||
)?.descricao
|
||||
: 'Selecione...'}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Buscar tipo logradouro..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{gTBBairro?.map((item) => (
|
||||
<CommandItem
|
||||
key={item.tb_bairro_id}
|
||||
value={(item.descricao ?? '').toLowerCase()}
|
||||
onSelect={() => {
|
||||
field.onChange(Number(item.tb_bairro_id));
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
'mr-2 h-4 w-4',
|
||||
String(field.value) === String(item.descricao)
|
||||
? 'opacity-100'
|
||||
: 'opacity-0',
|
||||
)}
|
||||
/>
|
||||
{GetCapitalize(item.descricao)}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/* Cartório */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-2">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="cartorio"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Cartório</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} type='number' placeholder="Digite o cartório" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* CNS */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-5">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="cns"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>CNS</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} type="number" placeholder="Digite o CNS" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Livro */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-5">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="livro"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Livro</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} type='text' placeholder="Digite o livro" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Tipo Registro */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="tipo_registro"
|
||||
render={({ field }) => (
|
||||
<FormItem className="w-full">
|
||||
<FormLabel>Tipo Registro</FormLabel>
|
||||
<FormControl>
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<SelectTrigger className="w-full">
|
||||
{field.value
|
||||
? ImovelTipoRegistro[field.value as keyof typeof ImovelTipoRegistro]
|
||||
: "Selecione"}
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{Object.entries(ImovelTipoRegistro).map(([key, label]) => (
|
||||
<SelectItem key={key} value={key} className="cursor-pointer">
|
||||
{label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Número */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="numero"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Número</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} type="number" placeholder="Digite o número" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Número Letra */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="numero_letra"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Número Letra</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} type='text' placeholder="Digite a letra" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Tipo Registro */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="tipo_classe"
|
||||
render={({ field }) => (
|
||||
<FormItem className="w-full">
|
||||
<FormLabel>Tipo Classe</FormLabel>
|
||||
<FormControl>
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<SelectTrigger className="w-full">
|
||||
{field.value
|
||||
? ImovelTipoClasseEnum[field.value as keyof typeof ImovelTipoClasseEnum]
|
||||
: "Selecione"}
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{Object.entries(ImovelTipoClasseEnum).map(([key, label]) => (
|
||||
<SelectItem key={key} value={key} className="cursor-pointer">
|
||||
{label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
{/* Unidades */}
|
||||
<TabsContent value="unidades" className="space-y-4">
|
||||
{/* Conteúdo das unidades */}
|
||||
< TImovelUnidadePage />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
{/* Rodapé do Dialog */}
|
||||
<DialogFooter className="mt-4 flex flex-col sm:flex-row gap-2 justify-end">
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" type="button" onClick={() => onClose(null, false)}>
|
||||
Cancelar
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<LoadingButton
|
||||
text="Salvar"
|
||||
textLoading="Aguarde..."
|
||||
type="submit"
|
||||
loading={buttonIsLoading}
|
||||
/>
|
||||
</DialogFooter>
|
||||
{/* Campo oculto */}
|
||||
<input type="hidden" {...form.register("imovel_id")} />
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
export interface TImovelFormProps {
|
||||
isOpen: boolean;
|
||||
data: FormValues | null;
|
||||
onClose: (item: null, isFormStatus: boolean) => void;
|
||||
onSave: (data: FormValues) => void;
|
||||
buttonIsLoading: boolean;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
'use client';
|
||||
|
||||
import { DataTable } from '@/app/_components/dataTable/DataTable';
|
||||
import TImovelColumns from './TImovelColumns';
|
||||
import TImovelInterface from '../../interfaces/TImovelInterface';
|
||||
|
||||
interface TImovelTableProps {
|
||||
data?: TImovelInterface[];
|
||||
onEdit: (item: TImovelInterface, isEditingFormStatus: boolean) => void;
|
||||
onDelete: (item: TImovelInterface, isEditingFormStatus: boolean) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Componente principal da tabela
|
||||
*/
|
||||
export default function TPessoaTable({ data, onEdit, onDelete }: TImovelTableProps) {
|
||||
const columns = TImovelColumns(onEdit, onDelete);
|
||||
return (
|
||||
<div>
|
||||
<DataTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
filterColumn="numero"
|
||||
filterPlaceholder="Buscar pelo numero de transcrição, matricula etc..."
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import TImovelUnidadeInterface from "../../interfaces/TImovelUnidadeInterface";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
EllipsisIcon,
|
||||
PencilIcon,
|
||||
Trash2Icon,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { SortableHeader } from "@/app/_components/dataTable/SortableHeader";
|
||||
|
||||
export default function TImovelUnidadeColumns(
|
||||
onEdit: (item: TImovelUnidadeInterface, isEditingFormStatus: boolean) => void,
|
||||
onDelete: (item: TImovelUnidadeInterface, isEditingFormStatus: boolean) => void
|
||||
): ColumnDef<TImovelUnidadeInterface>[] {
|
||||
return [
|
||||
// ID
|
||||
{
|
||||
accessorKey: "imovel_unidade_id",
|
||||
header: ({ column }) => SortableHeader("#", column),
|
||||
cell: ({ row }) => Number(row.getValue("imovel_unidade_id")),
|
||||
},
|
||||
// Número da Unidade
|
||||
{
|
||||
accessorKey: "numero_unidade",
|
||||
header: ({ column }) => SortableHeader("Número da Unidade", column),
|
||||
cell: ({ row }) => row.getValue("numero_unidade"),
|
||||
},
|
||||
// Quadra
|
||||
{
|
||||
accessorKey: "quadra",
|
||||
header: ({ column }) => SortableHeader("Quadra", column),
|
||||
cell: ({ row }) => row.getValue("quadra"),
|
||||
},
|
||||
// Area
|
||||
{
|
||||
accessorKey: "area",
|
||||
header: ({ column }) => SortableHeader("Área", column),
|
||||
cell: ({ row }) => row.getValue("area"),
|
||||
},
|
||||
// Logradouros
|
||||
{
|
||||
accessorKey: "logradouro",
|
||||
header: ({ column }) => SortableHeader("Logradouro", column),
|
||||
cell: ({ row }) => row.getValue("logradouro"),
|
||||
},
|
||||
// Ações
|
||||
{
|
||||
id: "actions",
|
||||
header: "Ações",
|
||||
cell: ({ row }) => {
|
||||
const imovel = row.original;
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon">
|
||||
<EllipsisIcon />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent side="left" align="start">
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem onSelect={() => onEdit(imovel, true)}>
|
||||
<PencilIcon className="mr-2 h-4 w-4" />
|
||||
Editar
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
className="text-red-600"
|
||||
onSelect={() => onDelete(imovel, true)}
|
||||
>
|
||||
<Trash2Icon className="mr-2 h-4 w-4" />
|
||||
Remover
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1,545 @@
|
|||
'use client';
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
|
||||
import LoadingButton from '@/app/_components/loadingButton/LoadingButton';
|
||||
import { TImovelUnidadeFormValues, TImovelUnidadeSchema } from '../../schemas/TImovelUnidadeSchema';
|
||||
import TImovelUnidadeProps from './TImovelUnidadeFormProps';
|
||||
import { useGTBTipoLogradouroReadHook } from '../../../../app/(protected)/(cadastros)/cadastros/_hooks/g_tb_tipologradouro/useGTBTipoLogradouroReadHook';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||
import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react';
|
||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/components/ui/command';
|
||||
import { cn } from '@/lib/utils';
|
||||
import GetCapitalize from '@/actions/text/GetCapitalize';
|
||||
import { ResetFormIfData } from '@/actions/form/ResetFormIfData';
|
||||
import { parseNumberInput } from '@/actions/form/parseNumberInput';
|
||||
import { ImovelTipoEnum } from '@/enums/ImovelTipoEnum';
|
||||
import { ImovelConstrucaoEnum } from '@/enums/ImovelConstrucaoEnum';
|
||||
|
||||
export default function TImovelUnidadeForm({ isOpen, data, onClose, onSave, buttonIsLoading }: TImovelUnidadeProps) {
|
||||
|
||||
const { gTBTipoLogradouro, fetchGTBTipoLogradouro } = useGTBTipoLogradouroReadHook();
|
||||
|
||||
// Inicializa o react-hook-form com schema zod
|
||||
const form = useForm<TImovelUnidadeFormValues>({
|
||||
resolver: zodResolver(TImovelUnidadeSchema),
|
||||
defaultValues: {
|
||||
imovel_id: 1,
|
||||
},
|
||||
});
|
||||
|
||||
// Atualiza o formulário quando recebe dados para edição
|
||||
useEffect(() => {
|
||||
|
||||
// Se existir dados, reseta o formulário com os mesmos
|
||||
ResetFormIfData(form, data);
|
||||
|
||||
// Carregamento de dados iniciais
|
||||
async function loadData() {
|
||||
|
||||
// Carrega o tipo de logradouro
|
||||
await fetchGTBTipoLogradouro();
|
||||
|
||||
}
|
||||
|
||||
// Executa a função
|
||||
loadData();
|
||||
|
||||
}, [data, form]);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) onClose(null, false);
|
||||
}}
|
||||
>
|
||||
<DialogContent className="w-full max-w-full p-6 sm:max-w-2xl md:max-w-2xl lg:max-w-3xl max-h-[60vh] overflow-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>
|
||||
Unidades do Imóvel
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
Cadastro de unidades do imóvel
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSave)} className="space-y-6">
|
||||
<div className="grid grid-cols-12 sm:grid-cols-12 lg:grid-cols-12 gap-4">
|
||||
{/* Quadra */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="quadra"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Quadra</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Lote */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="lote"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Lote</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Area */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="area"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Área(m2)</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field}
|
||||
type='number'
|
||||
onChange={e => field.onChange(parseNumberInput(e))}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Inscrição Municipal */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="inscricao_municipal"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Inscrição Municipal</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Tipo Logradouro */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="tb_tipologradouro_id"
|
||||
render={({ field }) => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Tipo logradouro</FormLabel>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl className="w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className="justify-between"
|
||||
>
|
||||
{field.value
|
||||
? gTBTipoLogradouro.find(
|
||||
(item) =>
|
||||
String(item.tb_tipologradouro_id) === String(field.value),
|
||||
)?.descricao
|
||||
: 'Selecione...'}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Buscar tipo logradouro..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{gTBTipoLogradouro?.map((item) => (
|
||||
<CommandItem
|
||||
key={item.tb_tipologradouro_id}
|
||||
value={(item.descricao ?? '').toLowerCase()}
|
||||
onSelect={() => {
|
||||
field.onChange(Number(item.tb_tipologradouro_id));
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
'mr-2 h-4 w-4',
|
||||
String(field.value) === String(item.descricao)
|
||||
? 'opacity-100'
|
||||
: 'opacity-0',
|
||||
)}
|
||||
/>
|
||||
{GetCapitalize(item.descricao)}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/* Logradouro */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="logradouro"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Logradouro</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Tipo Imóvel */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="tipo_imovel"
|
||||
render={({ field }) => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
// transforma o objeto em um array [{value, label}]
|
||||
const options = Object.entries(ImovelTipoEnum).map(([id, label]) => ({
|
||||
value: Number(id),
|
||||
label,
|
||||
}));
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Tipo Imóvel</FormLabel>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl className="w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className="justify-between"
|
||||
>
|
||||
{field.value
|
||||
? options.find((item) => item.value === field.value)?.label
|
||||
: "Selecione..."}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Buscar tipo imóvel..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{options.map((item) => (
|
||||
<CommandItem
|
||||
key={item.value}
|
||||
value={item.label.toLowerCase()}
|
||||
onSelect={() => {
|
||||
field.onChange(item.value); // salva o número (id)
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
field.value === item.value
|
||||
? "opacity-100"
|
||||
: "opacity-0"
|
||||
)}
|
||||
/>
|
||||
{item.label}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/* Construção */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="tipo_construcao"
|
||||
render={({ field }) => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const options = Object.entries(ImovelConstrucaoEnum).map(([id, label]) => ({
|
||||
value: Number(id),
|
||||
label,
|
||||
}));
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Construção</FormLabel>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl className="w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className="justify-between"
|
||||
>
|
||||
{field.value
|
||||
? options.find((item) => item.value === field.value)?.label
|
||||
: "Selecione..."}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Buscar tipo construção..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{options.map((item) => (
|
||||
<CommandItem
|
||||
key={item.value}
|
||||
value={item.label.toLowerCase()}
|
||||
onSelect={() => {
|
||||
field.onChange(item.value);
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
field.value === item.value
|
||||
? "opacity-100"
|
||||
: "opacity-0"
|
||||
)}
|
||||
/>
|
||||
{item.label}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/* Iptu */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="iptu"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>IPTU</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Unidade */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-2">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="numero_unidade"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Unidade</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Torre */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-2">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="torre"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Torre</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Condominio */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-2">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="nomecondominio"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Condominio</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field}
|
||||
type='text'
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Loteamento */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-3">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="nomeloteamento"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Loteamento</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* CNM */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-6">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="cib"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>CNM</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* CIB */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-6">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="cnm_numero"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>CIB</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Numero da Edificação */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="numero_edificacao"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Número da Edificação</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/* Complemento */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-8">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="complemento"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Complemento</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* Rodapé do Dialog */}
|
||||
<DialogFooter className="mt-4 flex flex-col sm:flex-row gap-2 justify-end">
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" type="button" onClick={() => onClose(null, false)}>
|
||||
Cancelar
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<LoadingButton
|
||||
text="Salvar"
|
||||
textLoading="Aguarde..."
|
||||
type="submit"
|
||||
loading={buttonIsLoading}
|
||||
/>
|
||||
</DialogFooter>
|
||||
{/* Campo oculto */}
|
||||
<input type="hidden" {...form.register("imovel_unidade_id")} />
|
||||
<input type="hidden" {...form.register("imovel_id")} />
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { TImovelUnidadeFormValues } from "../../schemas/TImovelUnidadeSchema";
|
||||
|
||||
export default interface TImovelUnidadeProps {
|
||||
isOpen: boolean;
|
||||
data: TImovelUnidadeFormValues | null;
|
||||
onClose: (item: null, isFormStatus: boolean) => void;
|
||||
onSave: (data: TImovelUnidadeFormValues) => void;
|
||||
buttonIsLoading: boolean;
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useState, useCallback } from 'react';
|
||||
|
||||
import Loading from '@/app/_components/loading/loading';
|
||||
import TImovelUnidadeTable from './TImovelUnidadeTable';
|
||||
import TImovelUnidadeForm from './TImovelUnidadeForm';
|
||||
|
||||
import { useTImovelUnidadeIndexHook } from '../../hooks/t_imovel_unidade/useTImovelUnidadeIndexHook';
|
||||
import { useTImovelUnidadeSaveHook } from '../../hooks/t_imovel_unidade/useTImovelUnidadeSaveHook';
|
||||
import { useTImovelUnidadeDeleteHook } from '../../hooks/t_imovel_unidade/useTImovelUnidadeDeleteHook';
|
||||
|
||||
import ConfirmDialog from '@/app/_components/confirm_dialog/ConfirmDialog';
|
||||
import { useConfirmDialog } from '@/app/_components/confirm_dialog/useConfirmDialog';
|
||||
|
||||
import TImovelUnidadeInterface from '../../interfaces/TImovelUnidadeInterface';
|
||||
import Header from '@/app/_components/structure/Header';
|
||||
|
||||
export default function TImovelUnidadePage() {
|
||||
// Controle de estado do botão
|
||||
const [buttonIsLoading, setButtonIsLoading] = useState(false);
|
||||
|
||||
// Hooks para leitura e salvamento
|
||||
const { tImovelUnidade, indexTImovelUnidade } = useTImovelUnidadeIndexHook();
|
||||
const { saveTImovelUnidade } = useTImovelUnidadeSaveHook();
|
||||
const { deleteTImovelUnidade } = useTImovelUnidadeDeleteHook();
|
||||
|
||||
// Estados
|
||||
const [selectedAndamento, setSelectedAndamento] = useState<TImovelUnidadeInterface | null>(null);
|
||||
const [isFormOpen, setIsFormOpen] = useState(false);
|
||||
|
||||
// Estado para saber qual item será deletado
|
||||
const [itemToDelete, setItemToDelete] = useState<TImovelUnidadeInterface | null>(null);
|
||||
|
||||
/**
|
||||
* Hook do modal de confirmação
|
||||
*/
|
||||
const {
|
||||
isOpen: isConfirmOpen,
|
||||
openDialog: openConfirmDialog,
|
||||
handleConfirm,
|
||||
handleCancel,
|
||||
} = useConfirmDialog();
|
||||
|
||||
/**
|
||||
* Abre o formulário no modo de edição ou criação
|
||||
*/
|
||||
const handleOpenForm = useCallback((data: TImovelUnidadeInterface | null) => {
|
||||
setSelectedAndamento(data);
|
||||
setIsFormOpen(true);
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Fecha o formulário e limpa o andamento selecionado
|
||||
*/
|
||||
const handleCloseForm = useCallback(() => {
|
||||
setSelectedAndamento(null);
|
||||
setIsFormOpen(false);
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Salva os dados do formulário
|
||||
*/
|
||||
const handleSave = useCallback(
|
||||
async (formData: TImovelUnidadeInterface) => {
|
||||
// Coloca o botão em estado de loading
|
||||
setButtonIsLoading(true);
|
||||
|
||||
// Aguarda salvar o registro
|
||||
await saveTImovelUnidade(formData);
|
||||
|
||||
// Remove o botão em estado de loading
|
||||
setButtonIsLoading(false);
|
||||
|
||||
// Atualiza a lista de dados
|
||||
indexTImovelUnidade();
|
||||
},
|
||||
[saveTImovelUnidade, indexTImovelUnidade, handleCloseForm],
|
||||
);
|
||||
|
||||
/**
|
||||
* Quando o usuário clica em "remover" na tabela
|
||||
*/
|
||||
const handleConfirmDelete = useCallback(
|
||||
(item: TImovelUnidadeInterface) => {
|
||||
// Define o item atual para remoção
|
||||
setItemToDelete(item);
|
||||
|
||||
// Abre o modal de confirmação
|
||||
openConfirmDialog();
|
||||
},
|
||||
[openConfirmDialog],
|
||||
);
|
||||
|
||||
/**
|
||||
* Executa a exclusão de fato quando o usuário confirma
|
||||
*/
|
||||
const handleDelete = useCallback(async () => {
|
||||
// Protege contra null
|
||||
if (!itemToDelete) return;
|
||||
|
||||
// Executa o Hook de remoção
|
||||
await deleteTImovelUnidade(itemToDelete);
|
||||
|
||||
// Atualiza a lista
|
||||
await indexTImovelUnidade();
|
||||
|
||||
// Limpa o item selecionado
|
||||
setItemToDelete(null);
|
||||
|
||||
// Fecha o modal
|
||||
handleCancel();
|
||||
}, [itemToDelete, indexTImovelUnidade, handleCancel]);
|
||||
|
||||
/**
|
||||
* Busca inicial dos dados
|
||||
*/
|
||||
useEffect(() => {
|
||||
indexTImovelUnidade();
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Tela de loading enquanto carrega os dados
|
||||
*/
|
||||
if (tImovelUnidade?.length == 0) {
|
||||
return <Loading type={2} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* Cabeçalho */}
|
||||
<Header
|
||||
title={'Unidades'}
|
||||
description={'Gerenciamento de unidades'}
|
||||
buttonText={'Nova unidade'}
|
||||
buttonAction={() => {
|
||||
handleOpenForm(null);
|
||||
}}
|
||||
/>
|
||||
{/* Tabela de andamentos */}
|
||||
<TImovelUnidadeTable
|
||||
data={tImovelUnidade}
|
||||
onEdit={handleOpenForm}
|
||||
onDelete={handleConfirmDelete} />
|
||||
{/* Modal de confirmação */}
|
||||
<ConfirmDialog
|
||||
isOpen={isConfirmOpen}
|
||||
title="Confirmar exclusão"
|
||||
description="Atenção"
|
||||
message={`Deseja realmente excluir a unidade "${itemToDelete?.cidade}"?`}
|
||||
confirmText="Sim, excluir"
|
||||
cancelText="Cancelar"
|
||||
onConfirm={handleDelete}
|
||||
onCancel={handleCancel}
|
||||
/>
|
||||
{/* Formulário de criação/edição */}
|
||||
<TImovelUnidadeForm
|
||||
isOpen={isFormOpen}
|
||||
data={selectedAndamento}
|
||||
onClose={handleCloseForm}
|
||||
onSave={handleSave}
|
||||
buttonIsLoading={buttonIsLoading}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
'use client';
|
||||
|
||||
import { DataTable } from '@/app/_components/dataTable/DataTable';
|
||||
import TImovelUnidadeInterface from '../../interfaces/TImovelUnidadeInterface';
|
||||
import TImovelUnidadeColumns from './TImovelUnidadeColumns';
|
||||
|
||||
interface TImovelUnidadeTableProps {
|
||||
data: TImovelUnidadeInterface[];
|
||||
onEdit: (item: TImovelUnidadeInterface, isEditingFormStatus: boolean) => void;
|
||||
onDelete: (item: TImovelUnidadeInterface, isEditingFormStatus: boolean) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Componente principal da tabela
|
||||
*/
|
||||
export default function TImovelUnidadeTable({ data, onEdit, onDelete }: TImovelUnidadeTableProps) {
|
||||
const columns = TImovelUnidadeColumns(onEdit, onDelete);
|
||||
return (
|
||||
<div className="max-h-[40vh] overflow-y-auto">
|
||||
<DataTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
filterColumn="numero_unidade"
|
||||
filterPlaceholder="Busque pelo numero da unidade"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ import {
|
|||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
|
||||
import { TPessoaSchema } from '../../_schemas/TPessoaSchema';
|
||||
import { TPessoaSchema } from '../../schemas/TPessoa/TPessoaSchema';
|
||||
import LoadingButton from '@/app/_components/loadingButton/LoadingButton';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import {
|
||||
|
|
@ -47,10 +47,10 @@ import {
|
|||
UserIcon,
|
||||
} from 'lucide-react';
|
||||
import { Sexo } from '@/enums/SexoEnum';
|
||||
import { useGTBEstadoCivilReadHook } from '../../_hooks/g_tb_estadocivil/useGTBEstadoCivilReadHook';
|
||||
import { useGTBEstadoCivilReadHook } from '../../../../app/(protected)/(cadastros)/cadastros/_hooks/g_tb_estadocivil/useGTBEstadoCivilReadHook';
|
||||
import GetCapitalize from '@/actions/text/GetCapitalize';
|
||||
import { useGTBRegimeComunhaoReadHook } from '../../_hooks/g_tb_regimecomunhao/useGTBRegimeComunhaoReadHook';
|
||||
import { useGTBProfissaoReadHook } from '../../_hooks/g_tb_profissao/useGTBProfissaoReadHook';
|
||||
import { useGTBRegimeComunhaoReadHook } from '../../../../app/(protected)/(cadastros)/cadastros/_hooks/g_tb_regimecomunhao/useGTBRegimeComunhaoReadHook';
|
||||
import { useGTBProfissaoReadHook } from '../../../../app/(protected)/(cadastros)/cadastros/_hooks/g_tb_profissao/useGTBProfissaoReadHook';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||
import {
|
||||
Command,
|
||||
|
|
@ -61,9 +61,9 @@ import {
|
|||
CommandList,
|
||||
} from '@/components/ui/command';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useTPessoaIndexHook } from '../../_hooks/t_pessoa/useTPessoaIndexHook';
|
||||
import TPessoaTable from '../t_pessoa/TPessoaTable';
|
||||
import TPessoaInterface from '../../_interfaces/TPessoaInterface';
|
||||
import { useTPessoaIndexHook } from '../../hooks/t_pessoa/useTPessoaIndexHook';
|
||||
import TPessoaTable from '../TPessoa/TPessoaFisica/TPessoaFisicaTable';
|
||||
import TPessoaInterface from '../../interfaces/TPessoa/TPessoaInterface';
|
||||
import { ColumnDef } from '@tanstack/react-table';
|
||||
import GetNameInitials from '@/actions/text/GetNameInitials';
|
||||
import empty from '@/actions/validations/empty';
|
||||
|
|
@ -3,18 +3,18 @@
|
|||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
|
||||
import Loading from '@/app/_components/loading/loading';
|
||||
import TPessoaForm from '../../_components/t_pessoa/TPessoaForm';
|
||||
import TPessoaForm from '../TPessoa/TPessoaFisica/TPessoaFisicaForm';
|
||||
|
||||
import { useTPessoaIndexHook } from '../../_hooks/t_pessoa/useTPessoaIndexHook';
|
||||
import { useTPessoaSaveHook } from '../../_hooks/t_pessoa/useTPessoaSaveHook';
|
||||
import { useTPessoaDeleteHook } from '../../_hooks/t_pessoa/useTPessoaDeleteHook';
|
||||
import { useTPessoaIndexHook } from '../../hooks/t_pessoa/useTPessoaIndexHook';
|
||||
import { useTPessoaSaveHook } from '../../hooks/t_pessoa/useTPessoaSaveHook';
|
||||
import { useTPessoaDeleteHook } from '../../hooks/t_pessoa/useTPessoaDeleteHook';
|
||||
|
||||
import ConfirmDialog from '@/app/_components/confirm_dialog/ConfirmDialog';
|
||||
import { useConfirmDialog } from '@/app/_components/confirm_dialog/useConfirmDialog';
|
||||
|
||||
import TPessoaInterface from '../../_interfaces/TPessoaInterface';
|
||||
import TPessoaInterface from '../../interfaces/TPessoa/TPessoaInterface';
|
||||
import TPessoaRepresentanteTable from './TPessoaRepresentanteTable';
|
||||
import { useTPessoaRepresentanteIndexHook } from '../../_hooks/t_pessoa_representante/useTPessoaRepresentanteIndexHook';
|
||||
import { useTPessoaRepresentanteIndexHook } from '../../hooks/t_pessoa_representante/useTPessoaRepresentanteIndexHook';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import Header from '@/app/_components/structure/Header';
|
||||
import TPessoaRepresentanteForm from './TPessoaRepresentanteForm';
|
||||
|
|
@ -16,7 +16,7 @@ import { ColumnDef } from '@tanstack/react-table';
|
|||
import GetNameInitials from '@/actions/text/GetNameInitials';
|
||||
import { DataTable } from '@/app/_components/dataTable/DataTable';
|
||||
|
||||
import TPessoaInterface from '../../_interfaces/TPessoaInterface';
|
||||
import TPessoaInterface from '../../interfaces/TPessoa/TPessoaInterface';
|
||||
import { FormatCPF } from '@/actions/CPF/FormatCPF';
|
||||
import { FormatPhone } from '@/actions/phone/FormatPhone';
|
||||
import empty from '@/actions/validations/empty';
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { withClientErrorHandler } from "@/actions/withClientErrorHandler/withClientErrorHandler";
|
||||
import TImovelInterface from "../../interfaces/TImovelInterface";
|
||||
|
||||
async function executeTImovelDeleteData(data: TImovelInterface) {
|
||||
|
||||
return Promise.resolve({
|
||||
status: 200,
|
||||
message: 'Dados Removidos'
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export const TImovelDeleteData = withClientErrorHandler(executeTImovelDeleteData);
|
||||
1614
src/packages/administrativo/data/TImovel/TImovelIndexData.ts
Normal file
1614
src/packages/administrativo/data/TImovel/TImovelIndexData.ts
Normal file
File diff suppressed because it is too large
Load diff
18
src/packages/administrativo/data/TImovel/TImovelSaveData.ts
Normal file
18
src/packages/administrativo/data/TImovel/TImovelSaveData.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { withClientErrorHandler } from "@/actions/withClientErrorHandler/withClientErrorHandler";
|
||||
import TImovelInterface from "../../interfaces/TImovelInterface";
|
||||
|
||||
async function executeTImovelSaveData(data: TImovelInterface) {
|
||||
|
||||
console.log({
|
||||
status: 200,
|
||||
message: 'Dados salvos',
|
||||
});
|
||||
|
||||
return Promise.resolve({
|
||||
status: 200,
|
||||
message: 'Dados salvos',
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export const TImovelSaveData = withClientErrorHandler(executeTImovelSaveData);
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { withClientErrorHandler } from "@/actions/withClientErrorHandler/withClientErrorHandler";
|
||||
import TImovelUnidadeInterface from "../../interfaces/TImovelUnidadeInterface";
|
||||
|
||||
async function executeTImovelUnidadeDeleteData(data: TImovelUnidadeInterface) {
|
||||
|
||||
return Promise.resolve({
|
||||
status: 200,
|
||||
message: 'Dados Removidos'
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export const TImovelUnidadeDeleteData = withClientErrorHandler(executeTImovelUnidadeDeleteData);
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
import { withClientErrorHandler } from "@/actions/withClientErrorHandler/withClientErrorHandler";
|
||||
|
||||
async function executeTImovelUnidadeIndexData() {
|
||||
|
||||
return Promise.resolve({
|
||||
status: 200,
|
||||
message: 'Dados Salvos',
|
||||
data: [
|
||||
{
|
||||
"imovel_unidade_id": 3921.00,
|
||||
"imovel_id": 5459.00,
|
||||
"numero_unidade": "asdfasd",
|
||||
"quadra": null,
|
||||
"area": null,
|
||||
"superquadra": null,
|
||||
"conjunto": null,
|
||||
"bloco": null,
|
||||
"area_descritiva": null,
|
||||
"caracteristica": null,
|
||||
"reserva_florestal": null,
|
||||
"geo_referenciamento": null,
|
||||
"logradouro": null,
|
||||
"tb_tipologradouro_id": null,
|
||||
"selecionado": "S",
|
||||
"complemento": null,
|
||||
"tipo_imovel": 67.00,
|
||||
"tipo_construcao": 0.00,
|
||||
"texto": null,
|
||||
"numero_edificacao": null,
|
||||
"iptu": "",
|
||||
"ccir": null,
|
||||
"nirf": null,
|
||||
"lote": null,
|
||||
"torre": null,
|
||||
"nomeloteamento": null,
|
||||
"nomecondominio": null,
|
||||
"numero": null,
|
||||
"cnm_numero": null,
|
||||
"imovel_publico_uniao": null,
|
||||
"spu_rip": null,
|
||||
"cat": null,
|
||||
"inscricao_municipal": null,
|
||||
"cib": null,
|
||||
"area_construida": null
|
||||
},
|
||||
{
|
||||
"imovel_unidade_id": 3918.00,
|
||||
"imovel_id": 5456.00,
|
||||
"numero_unidade": null,
|
||||
"quadra": "45",
|
||||
"area": null,
|
||||
"superquadra": null,
|
||||
"conjunto": null,
|
||||
"bloco": null,
|
||||
"area_descritiva": null,
|
||||
"caracteristica": null,
|
||||
"reserva_florestal": null,
|
||||
"geo_referenciamento": null,
|
||||
"logradouro": null,
|
||||
"tb_tipologradouro_id": null,
|
||||
"selecionado": "S",
|
||||
"complemento": null,
|
||||
"tipo_imovel": 67.00,
|
||||
"tipo_construcao": 0.00,
|
||||
"texto": null,
|
||||
"numero_edificacao": null,
|
||||
"iptu": null,
|
||||
"ccir": null,
|
||||
"nirf": null,
|
||||
"lote": null,
|
||||
"torre": null,
|
||||
"nomeloteamento": null,
|
||||
"nomecondominio": null,
|
||||
"numero": null,
|
||||
"cnm_numero": null,
|
||||
"imovel_publico_uniao": null,
|
||||
"spu_rip": null,
|
||||
"cat": null,
|
||||
"inscricao_municipal": null,
|
||||
"cib": null,
|
||||
"area_construida": null
|
||||
},
|
||||
{
|
||||
"imovel_unidade_id": 3917.00,
|
||||
"imovel_id": 5454.00,
|
||||
"numero_unidade": null,
|
||||
"quadra": "45",
|
||||
"area": 160.00,
|
||||
"superquadra": null,
|
||||
"conjunto": null,
|
||||
"bloco": null,
|
||||
"area_descritiva": null,
|
||||
"caracteristica": null,
|
||||
"reserva_florestal": null,
|
||||
"geo_referenciamento": null,
|
||||
"logradouro": "RUA P 3",
|
||||
"tb_tipologradouro_id": 1.00,
|
||||
"selecionado": "",
|
||||
"complemento": null,
|
||||
"tipo_imovel": 67.00,
|
||||
"tipo_construcao": 0.00,
|
||||
"texto": null,
|
||||
"numero_edificacao": null,
|
||||
"iptu": "1200",
|
||||
"ccir": null,
|
||||
"nirf": null,
|
||||
"lote": "12",
|
||||
"torre": null,
|
||||
"nomeloteamento": null,
|
||||
"nomecondominio": null,
|
||||
"numero": 125.00,
|
||||
"cnm_numero": null,
|
||||
"imovel_publico_uniao": null,
|
||||
"spu_rip": null,
|
||||
"cat": null,
|
||||
"inscricao_municipal": null,
|
||||
"cib": null,
|
||||
"area_construida": null
|
||||
},
|
||||
{
|
||||
"imovel_unidade_id": 3916.00,
|
||||
"imovel_id": 5453.00,
|
||||
"numero_unidade": null,
|
||||
"quadra": "06",
|
||||
"area": 461.51,
|
||||
"superquadra": null,
|
||||
"conjunto": null,
|
||||
"bloco": null,
|
||||
"area_descritiva": null,
|
||||
"caracteristica": null,
|
||||
"reserva_florestal": null,
|
||||
"geo_referenciamento": null,
|
||||
"logradouro": "Mariana Vilela",
|
||||
"tb_tipologradouro_id": 3.00,
|
||||
"selecionado": "S",
|
||||
"complemento": null,
|
||||
"tipo_imovel": 71.00,
|
||||
"tipo_construcao": 2.00,
|
||||
"texto": "{...}",
|
||||
"numero_edificacao": null,
|
||||
"iptu": "001.211.0006.0012.0001",
|
||||
"ccir": null,
|
||||
"nirf": null,
|
||||
"lote": "12",
|
||||
"torre": null,
|
||||
"nomeloteamento": null,
|
||||
"nomecondominio": null,
|
||||
"numero": null,
|
||||
"cnm_numero": null,
|
||||
"imovel_publico_uniao": null,
|
||||
"spu_rip": null,
|
||||
"cat": null,
|
||||
"inscricao_municipal": null,
|
||||
"cib": null,
|
||||
"area_construida": null
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export const TImovelUnidadeIndexData = withClientErrorHandler(executeTImovelUnidadeIndexData);
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { withClientErrorHandler } from "@/actions/withClientErrorHandler/withClientErrorHandler";
|
||||
import TImovelUnidadeInterface from "../../interfaces/TImovelUnidadeInterface";
|
||||
|
||||
async function executeTImovelUnidadeSaveData(data: TImovelUnidadeInterface) {
|
||||
|
||||
return Promise.resolve({
|
||||
status: 200,
|
||||
message: 'Dados salvos',
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export const TImovelUnidadeSaveData = withClientErrorHandler(executeTImovelUnidadeSaveData);
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { useState } from 'react';
|
||||
import TImovelInterface from '../../interfaces/TImovelInterface';
|
||||
import { TImovelDeleteService } from '../../services/t_imovel/TImovelDeleteService';
|
||||
|
||||
export const useTImovelDeleteHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
||||
const [tImovel, setTImovel] = useState<TImovelInterface>();
|
||||
|
||||
const deleteTImovel = async (data: TImovelInterface) => {
|
||||
const response = await TImovelDeleteService(data);
|
||||
|
||||
setTImovel(data);
|
||||
|
||||
setResponse(response);
|
||||
};
|
||||
|
||||
return { tImovel, deleteTImovel };
|
||||
};
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
'use client';
|
||||
|
||||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { useState } from 'react';
|
||||
import TImovelInterface from '../../interfaces/TImovelInterface';
|
||||
import { TImovelIndexData } from '../../data/TImovel/TImovelIndexData';
|
||||
|
||||
export const useTImovelIndexHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
||||
const [tImovel, setTImovel] = useState<TImovelInterface[]>();
|
||||
|
||||
const indexTImovel = async () => {
|
||||
const response = await TImovelIndexData();
|
||||
|
||||
// Armazena os dados consultados
|
||||
setTImovel(response.data);
|
||||
|
||||
// Define os dados do componente de resposta (toast, modal, etc)
|
||||
setResponse(response);
|
||||
};
|
||||
|
||||
return {
|
||||
tImovel,
|
||||
indexTImovel
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
'use client';
|
||||
|
||||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { useState } from 'react';
|
||||
import TImovelInterface from '../../interfaces/TImovelInterface';
|
||||
import { TImovelSaveService } from '../../services/t_imovel/TImovelSaveService';
|
||||
|
||||
export const useTImovelSaveHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
||||
const [tImovel, setTImovel] = useState<TImovelInterface>();
|
||||
|
||||
// controla se o formulário está aberto ou fechado
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const saveTImovel = async (data: TImovelInterface) => {
|
||||
const response = await TImovelSaveService(data);
|
||||
|
||||
// Armazena os dados da repsota
|
||||
setTImovel(response.data);
|
||||
|
||||
// Define os dados da respota(toast, modal, etc)
|
||||
setResponse(response);
|
||||
|
||||
// Fecha o formulário automaticamente após salvar
|
||||
setIsOpen(false);
|
||||
|
||||
// Retorna os valores de forma imediata
|
||||
return response.data;
|
||||
};
|
||||
|
||||
return { tImovel, saveTImovel };
|
||||
};
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { useState } from 'react';
|
||||
import TImovelUnidadeInterface from '../../interfaces/TImovelUnidadeInterface';
|
||||
import { TImovelDeleteService } from '../../services/t_imovel/TImovelDeleteService';
|
||||
|
||||
export const useTImovelUnidadeDeleteHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
||||
const [tImovelUnidade, setTImovelUnidade] = useState<TImovelUnidadeInterface>();
|
||||
|
||||
const deleteTImovelUnidade = async (data: TImovelUnidadeInterface) => {
|
||||
const response = await TImovelDeleteService(data);
|
||||
|
||||
setTImovelUnidade(data);
|
||||
|
||||
setResponse(response);
|
||||
};
|
||||
|
||||
return { tImovelUnidade, deleteTImovelUnidade };
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
'use client';
|
||||
|
||||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { useState } from 'react';
|
||||
import TImovelUnidadeInterface from '../../interfaces/TImovelUnidadeInterface';
|
||||
import { TImovelUnidadeIndexData } from '../../data/TImovelUnidade/TImovelUnidadeIndexData';
|
||||
|
||||
export const useTImovelUnidadeIndexHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
||||
const [tImovelUnidade, setTImovelUnidade] = useState<
|
||||
TImovelUnidadeInterface[]>();
|
||||
|
||||
const indexTImovelUnidade = async () => {
|
||||
const response = await TImovelUnidadeIndexData();
|
||||
|
||||
// Armazena os dados consultados
|
||||
setTImovelUnidade(response.data);
|
||||
|
||||
// Define os dados do componente de resposta (toast, modal, etc)
|
||||
setResponse(response);
|
||||
};
|
||||
|
||||
return {
|
||||
tImovelUnidade,
|
||||
indexTImovelUnidade
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
'use client';
|
||||
|
||||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { useState } from 'react';
|
||||
import TImovelUnidadeInterface from '../../interfaces/TImovelUnidadeInterface';
|
||||
import { TImovelUnidadeSaveService } from '../../services/t_imovel_unidade/TImovelUnidadeSaveService';
|
||||
|
||||
export const useTImovelUnidadeSaveHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
||||
const [tImovelUnidade, setTImovelUnidade] = useState<TImovelUnidadeInterface>();
|
||||
|
||||
// controla se o formulário está aberto ou fechado
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
const saveTImovelUnidade = async (data: TImovelUnidadeInterface) => {
|
||||
const response = await TImovelUnidadeSaveService(data);
|
||||
|
||||
// Armazena os dados da repsota
|
||||
setTImovelUnidade(response.data);
|
||||
|
||||
// Define os dados da respota(toast, modal, etc)
|
||||
setResponse(response);
|
||||
|
||||
// Fecha o formulário automaticamente após salvar
|
||||
setIsOpen(false);
|
||||
|
||||
// Retorna os valores de forma imediata
|
||||
return response.data;
|
||||
};
|
||||
|
||||
return { tImovelUnidade, saveTImovelUnidade };
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// hooks/useTPessoaForm.ts
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { TPessoaFormValues, TPessoaSchema } from "@/packages/administrativo/schemas/TPessoa/TPessoaSchema";
|
||||
|
||||
// Hook customizado
|
||||
export function useTPessoaForm(defaults?: Partial<TPessoaFormValues>) {
|
||||
return useForm<TPessoaFormValues>({
|
||||
resolver: zodResolver(TPessoaSchema),
|
||||
defaultValues: {
|
||||
nome: "",
|
||||
pessoa_id: 0,
|
||||
...defaults, // sobrescreve valores iniciais se forem passados
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import TPessoaJuridicaInterface from '../../../_interfaces/TPessoaJuridicaInterface';
|
||||
import { TCensecDeleteService } from '../../../_services/t_censec/TCensecDeleteService';
|
||||
import TPessoaJuridicaInterface from '../../../interfaces/TPessoa/TPessoaJuridica/TPessoaJuridicaInterface';
|
||||
import { TCensecDeleteService } from '../../../../../app/(protected)/(cadastros)/cadastros/_services/t_censec/TCensecDeleteService';
|
||||
|
||||
export const useTPessoaJuridicaDeleteHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { TPessoaJuridicaIndexService } from '../../../_services/t_pessoa/juridica/TPessoaJuridicaIndexService';
|
||||
import { TPessoaJuridicaIndexService } from '../../../services/t_pessoa/juridica/TPessoaJuridicaIndexService';
|
||||
import { useState } from 'react';
|
||||
import TPessoaJuridicaInterface from '../../../_interfaces/TPessoaJuridicaInterface';
|
||||
import TPessoaJuridicaInterface from '../../../interfaces/TPessoa/TPessoaJuridica/TPessoaJuridicaInterface';
|
||||
|
||||
export const useTPessoaJuridicaIndexHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { useState } from 'react';
|
||||
import TPessoaInterface from '../../../_interfaces/TPessoaInterface';
|
||||
import { TCensecSaveService } from '../../../_services/t_censec/TCensecSaveService';
|
||||
import TPessoaInterface from '../../../interfaces/TPessoa/TPessoaInterface';
|
||||
import { TCensecSaveService } from '../../../../../app/(protected)/(cadastros)/cadastros/_services/t_censec/TCensecSaveService';
|
||||
|
||||
export const useTPessoaJuridicaSaveHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import TPessoaInterface from '../../_interfaces/TPessoaInterface';
|
||||
import { TCensecDeleteService } from '../../_services/t_censec/TCensecDeleteService';
|
||||
import TPessoaInterface from '../../interfaces/TPessoa/TPessoaInterface';
|
||||
import { TCensecDeleteService } from '../../../../app/(protected)/(cadastros)/cadastros/_services/t_censec/TCensecDeleteService';
|
||||
|
||||
export const useTPessoaDeleteHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { TPessoaIndexService } from '../../_services/t_pessoa/TPessoaIndexService';
|
||||
import { TPessoaIndexService } from '../../services/t_pessoa/TPessoaIndexService';
|
||||
import { useState } from 'react';
|
||||
import TPessoaInterface from '../../_interfaces/TPessoaInterface';
|
||||
import TPessoaInterface from '../../interfaces/TPessoa/TPessoaInterface';
|
||||
|
||||
export const useTPessoaIndexHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { useState } from 'react';
|
||||
import TPessoaInterface from '../../_interfaces/TPessoaInterface';
|
||||
import { TCensecSaveService } from '../../_services/t_censec/TCensecSaveService';
|
||||
import TPessoaInterface from '../../interfaces/TPessoa/TPessoaInterface';
|
||||
import { TCensecSaveService } from '../../../../app/(protected)/(cadastros)/cadastros/_services/t_censec/TCensecSaveService';
|
||||
|
||||
export const useTPessoaSaveHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import TPessoaInterface from '../../_interfaces/TPessoaInterface';
|
||||
import { TCensecDeleteService } from '../../_services/t_censec/TCensecDeleteService';
|
||||
import TPessoaInterface from '../../interfaces/TPessoa/TPessoaInterface';
|
||||
import { TCensecDeleteService } from '../../../../app/(protected)/(cadastros)/cadastros/_services/t_censec/TCensecDeleteService';
|
||||
|
||||
export const useTPessoaDeleteHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { TPessoaIndexService } from '../../_services/t_pessoa/TPessoaIndexService';
|
||||
import { TPessoaIndexService } from '../../services/t_pessoa/TPessoaIndexService';
|
||||
import { useState } from 'react';
|
||||
import TPessoaInterface from '../../_interfaces/TPessoaInterface';
|
||||
import { TPessoaRepresentanteIndexData } from '../../_data/TPessoaRepresentante/TPessoaRepresentanteIndexData';
|
||||
import TPessoaInterface from '../../interfaces/TPessoa/TPessoaInterface';
|
||||
import { TPessoaRepresentanteIndexData } from '../../data/TPessoaRepresentante/TPessoaRepresentanteIndexData';
|
||||
|
||||
export const useTPessoaRepresentanteIndexHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
import { useResponse } from '@/app/_response/ResponseContext';
|
||||
import { useState } from 'react';
|
||||
import TPessoaInterface from '../../_interfaces/TPessoaInterface';
|
||||
import { TCensecSaveService } from '../../_services/t_censec/TCensecSaveService';
|
||||
import TPessoaInterface from '../../interfaces/TPessoa/TPessoaInterface';
|
||||
import { TCensecSaveService } from '../../../../app/(protected)/(cadastros)/cadastros/_services/t_censec/TCensecSaveService';
|
||||
|
||||
export const useTPessoaSaveHook = () => {
|
||||
const { setResponse } = useResponse();
|
||||
16
src/packages/administrativo/interfaces/TImovelInterface.ts
Normal file
16
src/packages/administrativo/interfaces/TImovelInterface.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
export default interface TImovelInterface {
|
||||
imovel_id?: number,
|
||||
tipo_classe?: string,
|
||||
tipo_registro?: string,
|
||||
data_registro?: string,
|
||||
numero?: number,
|
||||
numero_letra?: string,
|
||||
cidade?: string,
|
||||
cep?: string,
|
||||
uf?: string,
|
||||
tb_bairro_id?: number,
|
||||
cartorio?: string,
|
||||
livro?: string,
|
||||
cns?: number,
|
||||
gtb_descricao?: string,
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
export default interface TImovelUnidadeInterface {
|
||||
imovel_unidade_id?: number;
|
||||
imovel_id?: number;
|
||||
numero_unidade?: string;
|
||||
quadra?: string;
|
||||
area?: number;
|
||||
superquadra?: string;
|
||||
conjunto?: string;
|
||||
bloco?: string;
|
||||
area_descritiva?: string;
|
||||
caracteristica?: string;
|
||||
reserva_florestal?: string;
|
||||
geo_referenciamento?: string;
|
||||
logradouro: string;
|
||||
tb_tipologradouro_id?: number;
|
||||
selecionado?: string;
|
||||
complemento?: string;
|
||||
tipo_imovel?: number;
|
||||
tipo_construcao?: number;
|
||||
texto?: string;
|
||||
numero_edificacao?: string;
|
||||
iptu?: string;
|
||||
ccir?: string;
|
||||
nirf?: string;
|
||||
lote?: string;
|
||||
torre?: string;
|
||||
nomeloteamento?: string;
|
||||
nomecondominio?: string;
|
||||
numero?: number;
|
||||
cnm_numero?: string;
|
||||
imovel_publico_uniao?: string;
|
||||
spu_rip?: string;
|
||||
cat?: string;
|
||||
inscricao_municipal?: string;
|
||||
cib?: string;
|
||||
area_construida?: number;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { TPessoaFisicaFormValues } from "../../../schemas/TPessoa/TPessoaFisicaSchema";
|
||||
|
||||
export default interface TPessoaFisicaFormInterface {
|
||||
isOpen: boolean;
|
||||
data: TPessoaFisicaFormValues | null;
|
||||
onClose: (item: null, isFormStatus: boolean) => void;
|
||||
onSave: (data: TPessoaFisicaFormValues) => void;
|
||||
buttonIsLoading: boolean;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import TPessoaInterface from "../TPessoaInterface";
|
||||
|
||||
export default interface TPessoaFisicaInterface extends TPessoaInterface {
|
||||
nacionalidade?: string;
|
||||
tb_documentotipo_id?: number;
|
||||
tb_profissao_id?: number;
|
||||
tb_estadocivil_id?: number;
|
||||
nome_pai?: string;
|
||||
nome_mae?: string;
|
||||
data_nascimento?: string;
|
||||
sexo?: string;
|
||||
tb_regimecomunhao_id?: number;
|
||||
pessoa_conjuge_id?: number;
|
||||
documento_expedicao?: string;
|
||||
documento_validade?: string;
|
||||
cert_casamento_numero?: string;
|
||||
cert_casamento_folha?: string;
|
||||
cert_casamento_livro?: string;
|
||||
cert_casamento_cartorio?: string;
|
||||
cert_casamento_data?: string;
|
||||
cert_casamento_lei?: string;
|
||||
pessoa_conjuge_nome?: string;
|
||||
estrangeiro_nat?: string;
|
||||
estrangeiro_nat_tb_pais_id?: number;
|
||||
estrangeiro_res_tb_pais_id?: number;
|
||||
estrangeiro_res?: string;
|
||||
documento_orgao?: string;
|
||||
documento_uf?: string;
|
||||
uf_residencia?: string;
|
||||
deficiencias?: string;
|
||||
grau_instrucao?: string;
|
||||
cidade_nat_id?: number;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import TPessoaFisicaInterface from "./TPessoaFisicaInterface";
|
||||
|
||||
export default interface TPessoaFisicaTableInterface {
|
||||
data: TPessoaFisicaInterface[];
|
||||
onEdit: (item: TPessoaFisicaInterface, isEditingFormStatus: boolean) => void;
|
||||
onDelete: (item: TPessoaFisicaInterface, isEditingFormStatus: boolean) => void;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
export default interface TPessoaInterface {
|
||||
pessoa_id?: number;
|
||||
pessoa_tipo?: string;
|
||||
nome?: string;
|
||||
documento?: string;
|
||||
data_cadastro?: string;
|
||||
naturalidade?: string;
|
||||
telefone?: string;
|
||||
endereco?: string;
|
||||
cidade?: string;
|
||||
uf?: string;
|
||||
email?: string;
|
||||
documento_numero?: string;
|
||||
bairro?: string;
|
||||
cep?: string;
|
||||
observacao?: string;
|
||||
cpf_cnpj?: string;
|
||||
cpf_terceiro?: string;
|
||||
texto?: string;
|
||||
ddd?: number;
|
||||
municipio_id?: number;
|
||||
enviado_cnncnb?: boolean;
|
||||
data_auteracao?: string;
|
||||
data_envioccn?: string;
|
||||
ccnregistros_id?: number;
|
||||
observacao_envioccn?: string;
|
||||
observacao_envio_ccn?: string;
|
||||
tb_tipologradouro_id?: number;
|
||||
unidade?: string;
|
||||
numero_end?: string;
|
||||
foto?: string;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import TPessoaJuridicaInterface from "./TPessoaJuridicaInterface";
|
||||
|
||||
export default interface TPessoaJuridicaFormInterface {
|
||||
isOpen: boolean;
|
||||
data: TPessoaJuridicaInterface | null;
|
||||
onClose: (item: null, isFormStatus: boolean) => void;
|
||||
onSave: (data: TPessoaJuridicaInterface) => void;
|
||||
buttonIsLoading: boolean;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import TPessoaInterface from "../TPessoaInterface";
|
||||
|
||||
export default interface TPessoaJuridicaInterface extends TPessoaInterface {
|
||||
razao_social?: string;
|
||||
nome_fantasia?: string;
|
||||
inscricao_estadual?: string;
|
||||
inscricao_municipal?: string;
|
||||
capital_social?: number;
|
||||
data_abertura?: string;
|
||||
cnae_principal?: string;
|
||||
cnae_secundario?: string[];
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import TPessoaJuridicaInterface from "./TPessoaJuridicaInterface";
|
||||
|
||||
export default interface TPessoaJuridicaTableInterface {
|
||||
data: TPessoaJuridicaInterface[];
|
||||
onEdit: (item: TPessoaJuridicaInterface, isEditingFormStatus: boolean) => void;
|
||||
onDelete: (item: TPessoaJuridicaInterface, isEditingFormStatus: boolean) => void;
|
||||
}
|
||||
19
src/packages/administrativo/schemas/TImovelSchema.ts
Normal file
19
src/packages/administrativo/schemas/TImovelSchema.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import z from "zod";
|
||||
|
||||
export const TImovelSchema = z.object({
|
||||
imovel_id: z.number().optional(),
|
||||
tipo_classe: z.string().optional(),
|
||||
tipo_registro: z.string().optional(),
|
||||
data_registro: z.string().optional(),
|
||||
numero: z.number().optional(),
|
||||
numero_letra: z.string().optional(),
|
||||
cidade: z.string().optional(),
|
||||
cep: z.string().optional(),
|
||||
uf: z.string().optional(),
|
||||
tb_bairro_id: z.number().optional(),
|
||||
cartorio: z.string().optional(),
|
||||
livro: z.string().optional(),
|
||||
cns: z.number().optional(),
|
||||
});
|
||||
|
||||
export type TImovelFormValues = z.infer<typeof TImovelSchema>;
|
||||
42
src/packages/administrativo/schemas/TImovelUnidadeSchema.ts
Normal file
42
src/packages/administrativo/schemas/TImovelUnidadeSchema.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import z from "zod";
|
||||
|
||||
export const TImovelUnidadeSchema = z.object({
|
||||
imovel_unidade_id: z.number().optional(),
|
||||
imovel_id: z.number().optional(),
|
||||
numero_unidade: z.string().optional(),
|
||||
quadra: z.string().optional(),
|
||||
area: z.number().optional(),
|
||||
superquadra: z.string().optional(),
|
||||
conjunto: z.string().optional(),
|
||||
bloco: z.string().optional(),
|
||||
area_descritiva: z.string().optional(),
|
||||
caracteristica: z.string().optional(),
|
||||
reserva_florestal: z.string().optional(),
|
||||
geo_referenciamento: z.string().optional(),
|
||||
logradouro: z.string().min(1, 'O campo deve ser preenchido').max(90, 'O campo não deve exceder 90 caracteres'),
|
||||
tb_tipologradouro_id: z.number().optional(),
|
||||
selecionado: z.string().optional(),
|
||||
complemento: z.string().optional(),
|
||||
tipo_imovel: z.number().optional(),
|
||||
tipo_construcao: z.number().optional(),
|
||||
texto: z.string().optional(),
|
||||
numero_edificacao: z.string().optional(),
|
||||
iptu: z.string().optional(),
|
||||
ccir: z.string().optional(),
|
||||
nirf: z.string().optional(),
|
||||
lote: z.string().optional(),
|
||||
torre: z.string().optional(),
|
||||
nomeloteamento: z.string().optional(),
|
||||
nomecondominio: z.string().optional(),
|
||||
numero: z.number().optional(),
|
||||
cnm_numero: z.string().optional(),
|
||||
imovel_publico_uniao: z.string().optional(),
|
||||
spu_rip: z.string().optional(),
|
||||
cat: z.string().optional(),
|
||||
inscricao_municipal: z.string().optional(),
|
||||
cib: z.string().optional(),
|
||||
area_construida: z.number().optional(),
|
||||
});
|
||||
|
||||
// Exportar o tipo inferido junto (opcional)
|
||||
export type TImovelUnidadeFormValues = z.infer<typeof TImovelUnidadeSchema>;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import { TPessoaSchema } from "./TPessoaSchema";
|
||||
import z from "zod";
|
||||
|
||||
export const TPessoaFisicaSchema = TPessoaSchema.extend({
|
||||
nacionalidade: z.string().optional(),
|
||||
tb_documentotipo_id: z.number().optional(),
|
||||
tb_profissao_id: z.number().optional(),
|
||||
tb_estadocivil_id: z.number().optional(),
|
||||
nome_pai: z.string().optional(),
|
||||
nome_mae: z.string().optional(),
|
||||
data_nascimento: z.string().optional(),
|
||||
sexo: z.string().optional(),
|
||||
tb_regimecomunhao_id: z.number().optional(),
|
||||
pessoa_conjuge_id: z.number().optional(),
|
||||
documento_expedicao: z.string().optional(),
|
||||
documento_validade: z.string().optional(),
|
||||
cert_casamento_numero: z.string().optional(),
|
||||
cert_casamento_folha: z.string().optional(),
|
||||
cert_casamento_livro: z.string().optional(),
|
||||
cert_casamento_cartorio: z.string().optional(),
|
||||
cert_casamento_data: z.string().optional(),
|
||||
cert_casamento_lei: z.string().optional(),
|
||||
pessoa_conjuge_nome: z.string().optional(),
|
||||
estrangeiro_nat: z.string().optional(),
|
||||
estrangeiro_nat_tb_pais_id: z.number().optional(),
|
||||
estrangeiro_res_tb_pais_id: z.number().optional(),
|
||||
estrangeiro_res: z.string().optional(),
|
||||
documento_orgao: z.string().optional(),
|
||||
documento_uf: z.string().optional(),
|
||||
uf_residencia: z.string().optional(),
|
||||
deficiencias: z.string().optional(),
|
||||
grau_instrucao: z.string().optional(),
|
||||
cidade_nat_id: z.number().optional(),
|
||||
});
|
||||
|
||||
export type TPessoaFisicaFormValues = z.infer<typeof TPessoaFisicaSchema>;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import { TPessoaSchema } from "./TPessoaSchema";
|
||||
import z from "zod";
|
||||
|
||||
export const TPessoaJuridicaSchema = TPessoaSchema.extend({
|
||||
razao_social: z.string().min(1, "Razão social é obrigatória"),
|
||||
nome_fantasia: z.string().optional(),
|
||||
inscricao_estadual: z.string().optional(),
|
||||
inscricao_municipal: z.string().optional(),
|
||||
capital_social: z.number().optional(),
|
||||
data_abertura: z.string().optional(),
|
||||
cnae_principal: z.string().optional(),
|
||||
cnae_secundario: z.array(z.string()).optional(),
|
||||
});
|
||||
|
||||
export type TPessoaJuridicaFormValues = z.infer<typeof TPessoaJuridicaSchema>;
|
||||
33
src/packages/administrativo/schemas/TPessoa/TPessoaSchema.ts
Normal file
33
src/packages/administrativo/schemas/TPessoa/TPessoaSchema.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import z from 'zod';
|
||||
|
||||
export const TPessoaSchema = z.object({
|
||||
pessoa_id: z.number().optional(),
|
||||
pessoa_tipo: z.string().optional(),
|
||||
nome: z.string().min(1, 'O campo deve ser preenchido').max(120, 'O nome excede 120 caracteres'),
|
||||
documento: z.string().optional(),
|
||||
data_cadastro: z.string().optional(),
|
||||
telefone: z.string().optional(),
|
||||
endereco: z.string().optional(),
|
||||
cidade: z.string().optional(),
|
||||
uf: z.string().optional(),
|
||||
email: z.string().email().optional(),
|
||||
documento_numero: z.string().optional(),
|
||||
bairro: z.string().optional(),
|
||||
cep: z.string().optional(),
|
||||
observacao: z.string().optional(),
|
||||
cpf_cnpj: z.string().optional(),
|
||||
cpf_terceiro: z.string().optional(),
|
||||
texto: z.string().optional(),
|
||||
ddd: z.number().optional(),
|
||||
municipio_id: z.number().optional(),
|
||||
enviado_cnncnb: z.boolean().optional(),
|
||||
data_auteracao: z.string().optional(),
|
||||
data_envioccn: z.string().optional(),
|
||||
ccnregistros_id: z.number().optional(),
|
||||
observacao_envioccn: z.string().optional(),
|
||||
observacao_envio_ccn: z.string().optional(),
|
||||
tb_tipologradouro_id: z.number().optional(),
|
||||
unidade: z.string().optional(),
|
||||
numero_end: z.string().optional(),
|
||||
foto: z.string().optional(),
|
||||
});
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { withClientErrorHandler } from '@/actions/withClientErrorHandler/withClientErrorHandler';
|
||||
import { TImovelDeleteData } from '../../data/TImovel/TImovelDeleteData';
|
||||
import TImovelInterface from '../../interfaces/TImovelInterface';
|
||||
|
||||
async function executeTImovelDeleteService(data: TImovelInterface) {
|
||||
const response = await TImovelDeleteData(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const TImovelDeleteService = withClientErrorHandler(executeTImovelDeleteService);
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import { withClientErrorHandler } from '@/actions/withClientErrorHandler/withClientErrorHandler';
|
||||
import { TImovelIndexData } from '../../data/TImovel/TImovelIndexData';
|
||||
|
||||
export default async function executeTImovelIndexService() {
|
||||
const response = await TImovelIndexData();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const TImovelIndexService = withClientErrorHandler(executeTImovelIndexService);
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { withClientErrorHandler } from '@/actions/withClientErrorHandler/withClientErrorHandler';
|
||||
import { TImovelSaveData } from '../../data/TImovel/TImovelSaveData';
|
||||
import TImovelInterface from '../../interfaces/TImovelInterface';
|
||||
|
||||
async function executeTImovelSaveService(data: TImovelInterface) {
|
||||
const response = await TImovelSaveData(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const TImovelSaveService = withClientErrorHandler(executeTImovelSaveService);
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { withClientErrorHandler } from '@/actions/withClientErrorHandler/withClientErrorHandler';
|
||||
import TImovelUnidadeInterface from '../../interfaces/TImovelUnidadeInterface';
|
||||
import { TImovelUnidadeDeleteData } from '../../data/TImovelUnidade/TImovelUnidadeDeleteData';
|
||||
|
||||
async function executeTImovelUnidadeDeleteService(data: TImovelUnidadeInterface) {
|
||||
const response = await TImovelUnidadeDeleteData(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const TImovelUnidadeDeleteService = withClientErrorHandler(executeTImovelUnidadeDeleteService);
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import { withClientErrorHandler } from '@/actions/withClientErrorHandler/withClientErrorHandler';
|
||||
import { TImovelUnidadeIndexData } from '../../data/TImovelUnidade/TImovelUnidadeIndexData';
|
||||
|
||||
export default async function executeTImovelUnidadeIndexService() {
|
||||
const response = await TImovelUnidadeIndexData();
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const TImovelUnidadeIndexService = withClientErrorHandler(executeTImovelUnidadeIndexService);
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { withClientErrorHandler } from '@/actions/withClientErrorHandler/withClientErrorHandler';
|
||||
import TImovelUnidadeInterface from '../../interfaces/TImovelUnidadeInterface';
|
||||
import { TImovelUnidadeSaveData } from '../../data/TImovelUnidade/TImovelUnidadeSaveData';
|
||||
|
||||
async function executeTImovelUnidadeSaveService(data: TImovelUnidadeInterface) {
|
||||
const response = await TImovelUnidadeSaveData(data);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const TImovelUnidadeSaveService = withClientErrorHandler(executeTImovelUnidadeSaveService);
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { withClientErrorHandler } from '@/actions/withClientErrorHandler/withClientErrorHandler';
|
||||
import { TPessoaIndexData } from '../../_data/TPessoa/TPessoaIndexData';
|
||||
import { TPessoaIndexData } from '../../data/TPessoa/TPessoaIndexData';
|
||||
|
||||
async function executeTPessoaIndexService() {
|
||||
const response = TPessoaIndexData();
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { withClientErrorHandler } from '@/actions/withClientErrorHandler/withClientErrorHandler';
|
||||
import { TPessoaJuridicaIndexData } from '../../../_data/TPessoa/juridica/TPessoaJuridicaIndexData';
|
||||
import { TPessoaJuridicaIndexData } from '../../../data/TPessoa/juridica/TPessoaJuridicaIndexData';
|
||||
|
||||
async function executeTPessoaJuridicaIndexService() {
|
||||
const response = TPessoaJuridicaIndexData();
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { withClientErrorHandler } from '@/actions/withClientErrorHandler/withClientErrorHandler';
|
||||
import { TPessoaRepresentanteIndexData } from '../../_data/TPessoaRepresentante/TPessoaRepresentanteIndexData';
|
||||
import { TPessoaRepresentanteIndexData } from '../../data/TPessoaRepresentante/TPessoaRepresentanteIndexData';
|
||||
|
||||
async function executeTPessoaRepresentanteIndexService() {
|
||||
const response = TPessoaRepresentanteIndexData();
|
||||
Loading…
Add table
Reference in a new issue