[MVPTN-88] feat(Form): Formulário de cadastro estático

This commit is contained in:
Keven Willian Pereira de Souza 2025-09-26 15:42:54 -03:00
parent 3fe6ed8c08
commit b7f35889a6
5 changed files with 654 additions and 415 deletions

View file

@ -0,0 +1,11 @@
/**
* Capitaliza a primeira letra de uma string.
*
* @param text - Texto que será capitalizado
* @returns String com a primeira letra em maiúscula
*/
export default function GetCapitalize(text: string): string {
if (!text) return "";
return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
}

View file

@ -6,7 +6,6 @@ import { useForm, Controller } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
Dialog,
DialogClose,
@ -25,14 +24,17 @@ import {
FormMessage
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { TPessoaSchema } from "../../_schemas/TPessoaSchema";
import { SituacoesEnum } from "@/enums/SituacoesEnum";
import LoadingButton from "@/app/_components/loadingButton/LoadingButton";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Select, SelectContent, SelectItem, SelectTrigger } from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { HouseIcon, IdCardIcon, UserIcon } from "lucide-react";
import { Sexo } from "@/enums/SexoEnum";
import { useGTBEstadoCivilReadHook } from "../../_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";
type FormValues = z.infer<typeof TPessoaSchema>;
@ -45,6 +47,11 @@ interface TPessoaFormProps {
}
export default function TCensecForm({ isOpen, data, onClose, onSave, buttonIsLoading }: TPessoaFormProps) {
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),
@ -56,7 +63,21 @@ export default function TCensecForm({ isOpen, data, onClose, onSave, buttonIsLoa
// Atualiza o formulário quando recebe dados para edição
useEffect(() => {
if (data) form.reset(data);
const loadData = async () => {
// Se existir dados, reseta o formulário com os dados informados
if (data) form.reset(data);
// Aguarda a busca terminar
await fetchGTBProfissao();
await fetchGTBEstadoCivil();
await fetchGTBRegimeComunhao();
};
// Dispara a função
loadData();
}, [data, form]);
return (
@ -66,7 +87,8 @@ export default function TCensecForm({ isOpen, data, onClose, onSave, buttonIsLoa
if (!open) onClose(null, false);
}}
>
<DialogContent className="sm:max-w-[1000px]">
<DialogContent className="w-full max-w-full sm:max-w-3xl md:max-w-4xl lg:max-w-5xl p-6">
<DialogHeader>
<DialogTitle>Pessoa</DialogTitle>
<DialogDescription>Preencha os dados da pessoa</DialogDescription>
@ -77,209 +99,628 @@ export default function TCensecForm({ isOpen, data, onClose, onSave, buttonIsLoa
{/* Tabs */}
<Tabs defaultValue="dadosPessoais" className="space-y-4">
<TabsList>
<TabsTrigger value="dadosPessoais">Dados Pessoais</TabsTrigger>
<TabsTrigger value="documentos">Documentos</TabsTrigger>
<TabsTrigger value="endereco">Endereço</TabsTrigger>
<TabsTrigger value="contato">Contato</TabsTrigger>
<TabsTrigger value="casamento">Casamento/Conjuge</TabsTrigger>
<TabsTrigger value="outros">Outros</TabsTrigger>
<TabsList className="w-full flex">
<TabsTrigger className="flex-1 text-center cursor-pointer" value="dadosPessoais">
<UserIcon className="me-1" />Dados Pessoais
</TabsTrigger>
<TabsTrigger className="flex-1 text-center cursor-pointer" value="endereco">
<HouseIcon /> Endereço
</TabsTrigger>
<TabsTrigger className="flex-1 text-center cursor-pointer" value="documentos">
<IdCardIcon /> Documentos
</TabsTrigger>
</TabsList>
{/* Dados Pessoais */}
<TabsContent value="dadosPessoais" className="space-y-4">
<FormField control={form.control} name="nome" render={({ field }) => (
<FormItem>
<FormLabel>Nome</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" />
</FormControl>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="data_nascimento" render={({ field }) => (
<FormItem>
<FormLabel>Data de Nascimento</FormLabel>
<FormControl>
<Input type="date" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="sexo" render={({ field }) => (
<FormItem>
<FormLabel>Sexo</FormLabel>
<FormControl>
<Select {...field}>
<SelectTrigger>{field.value || "Selecione"}</SelectTrigger>
<SelectContent>
<SelectItem value="M">Masculino</SelectItem>
<SelectItem value="F">Feminino</SelectItem>
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="nacionalidade" render={({ field }) => (
<FormItem>
<FormLabel>Nacionalidade</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite a nacionalidade" />
</FormControl>
<FormMessage />
</FormItem>
)} />
</TabsContent>
{/* Documentos */}
<TabsContent value="documentos" className="space-y-4">
<FormField control={form.control} name="cpf_cnpj" render={({ field }) => (
<FormItem>
<FormLabel>CPF/CNPJ</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o CPF ou CNPJ" />
</FormControl>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="documento" render={({ field }) => (
<FormItem>
<FormLabel>Documento</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o documento" />
</FormControl>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="documento_validade" render={({ field }) => (
<FormItem>
<FormLabel>Validade do Documento</FormLabel>
<FormControl>
<Input type="date" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)} />
<div className="grid grid-cols-12 gap-4 w-full">
{/* Nome */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="nome"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Nome
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Data de Nascimento */}
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name="data_nascimento"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Data de Nascimento
</FormLabel>
<FormControl>
<Input type="date" {...field} className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Sexo */}
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name="sexo"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Sexo</FormLabel>
<FormControl>
<Select
value={field.value}
onValueChange={field.onChange}
>
<SelectTrigger className="w-full">
{field.value ? Sexo[field.value as keyof typeof Sexo] : "Selecione"}
</SelectTrigger>
<SelectContent>
{Object.entries(Sexo).map(([key, label]) => (
<SelectItem key={key} value={key} className="cursor-pointer">
{label}
</SelectItem>
))}
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Nacionalidade */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="nacionalidade"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Nacionalidade
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite a nacionalidade" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* País de Nascimento */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="nacionalidade"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
País de Nascimento
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite a nacionalidade" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* UF */}
<div className="col-span-12 sm:col-span-12 md:col-span-2">
<FormField
control={form.control}
name="uf"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
UF
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite a nacionalidade" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Município */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="municipio_id"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Município
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite a nacionalidade" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Naturalidade */}
<div className="col-span-12 sm:col-span-12 md:col-span-4">
<FormField
control={form.control}
name="naturalidade"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Naturalidade
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite a nacionalidade" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Estado Civil */}
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name="tb_estadocivil_id"
render={({ field }) => (
<FormItem>
<FormLabel>
Estado Civil
</FormLabel>
<Select
value={String(field.value)}
// Converter o valor inteiro para ser aceito pelo zod
onValueChange={(val) => field.onChange(Number(val))}
>
<FormControl className="w-full">
<SelectTrigger>
<SelectValue placeholder="Escolha o estado civil" />
</SelectTrigger>
</FormControl>
<SelectContent>
{gTBEstadoCivil.map((item) => (
<SelectItem key={item.tb_estadocivil_id} value={String(item.tb_estadocivil_id)} className="cursor-pointer">
{GetCapitalize(item.descricao)}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Regime */}
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name="tb_regimecomunhao_id"
render={({ field }) => (
<FormItem>
<FormLabel>
Regime
</FormLabel>
<Select
value={String(field.value)}
// Converter o valor inteiro para ser aceito pelo zod
onValueChange={(val) => field.onChange(Number(val))}
>
<FormControl className="w-full">
<SelectTrigger>
<SelectValue placeholder="Escolha o regime" />
</SelectTrigger>
</FormControl>
<SelectContent>
{gTBRegimeComunhao.map((item) => (
<SelectItem key={item.tb_regimecomunhao_id} value={String(item.tb_regimecomunhao_id)} className="cursor-pointer">
{GetCapitalize(item.descricao)}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Profissão */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="tb_profissao_id"
render={({ field }) => (
<FormItem>
<FormLabel>
Profissão
</FormLabel>
<Select
value={String(field.value)}
// Converter o valor inteiro para ser aceito pelo zod
onValueChange={(val) => field.onChange(Number(val))}
>
<FormControl className="w-full">
<SelectTrigger>
<SelectValue placeholder="Escolha a profissão" />
</SelectTrigger>
</FormControl>
<SelectContent>
{gTBProfissao.map((item) => (
<SelectItem key={item.tb_profissao_id} value={String(item.tb_profissao_id)} className="cursor-pointer">
{GetCapitalize(item.descricao)}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Pai */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="nome_pai"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Pai
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite a nacionalidade" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Mãe */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="nome_mae"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Mãe
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite a nacionalidade" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
</TabsContent>
{/* Endereço */}
<TabsContent value="endereco" className="space-y-4">
<FormField control={form.control} name="endereco" render={({ field }) => (
<FormItem>
<FormLabel>Endereço</FormLabel>
<FormControl>
<Input {...field} placeholder="Rua, Av, etc." />
</FormControl>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="bairro" render={({ field }) => (
<FormItem>
<FormLabel>Bairro</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o bairro" />
</FormControl>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="cidade" render={({ field }) => (
<FormItem>
<FormLabel>Cidade</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite a cidade" />
</FormControl>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="uf" render={({ field }) => (
<FormItem>
<FormLabel>UF</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite a UF" />
</FormControl>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="cep" render={({ field }) => (
<FormItem>
<FormLabel>CEP</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o CEP" />
</FormControl>
<FormMessage />
</FormItem>
)} />
<div className="grid grid-cols-12 gap-4 w-full">
{/* País */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="uf_residencia"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
País
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* UF */}
<div className="col-span-12 sm:col-span-12 md:col-span-2">
<FormField
control={form.control}
name="uf_residencia"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
UF
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* CEP */}
<div className="col-span-12 sm:col-span-12 md:col-span-4">
<FormField
control={form.control}
name="cep"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
CEP
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Cidade */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="cidade_nat_id"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Cidade
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Município */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="municipio_id"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Município
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Bairro */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="bairro"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Bairro
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Logradouro */}
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name="tb_tipologradouro_id"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Logradouro
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Número */}
<div className="col-span-12 sm:col-span-12 md:col-span-4">
<FormField
control={form.control}
name="numero_end"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Número
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Unidade */}
<div className="col-span-12 sm:col-span-12 md:col-span-4">
<FormField
control={form.control}
name="unidade"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Unidade
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Cidade não encontrada */}
<div className="col-span-12 sm:col-span-12 md:col-span-4">
<FormField
control={form.control}
name="uf_residencia"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>
Cidade não encontrada
</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
</TabsContent>
{/* Contato */}
<TabsContent value="contato" className="space-y-4">
<FormField control={form.control} name="telefone" render={({ field }) => (
<FormItem>
<FormLabel>Telefone</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o telefone" />
</FormControl>
<FormMessage />
</FormItem>
)} />
{/* Documentos */}
<TabsContent value="documentos" className="space-y-4">
<div className="grid grid-cols-12 gap-4 w-full">
<FormField control={form.control} name="email" render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o email" />
</FormControl>
<FormMessage />
</FormItem>
)} />
{/* Tipo */}
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name="tb_documentotipo_id"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Tipo</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o tipo" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Número */}
<div className="col-span-12 sm:col-span-12 md:col-span-5">
<FormField
control={form.control}
name="documento_numero"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Número</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o número" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* CPF */}
<div className="col-span-12 sm:col-span-12 md:col-span-4">
<FormField
control={form.control}
name="cpf_cnpj"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>CPF</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o CPF" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Órgão Emissor */}
<div className="col-span-12 sm:col-span-12 md:col-span-4">
<FormField
control={form.control}
name="documento_orgao"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Órgão</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o órgão emissor" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* UF */}
<div className="col-span-12 sm:col-span-12 md:col-span-2">
<FormField
control={form.control}
name="documento_uf"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>UF</FormLabel>
<FormControl>
<Input {...field} placeholder="UF" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Data de Expedição */}
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name="documento_expedicao"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Expedição</FormLabel>
<FormControl>
<Input {...field} type="date" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Validade */}
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name="documento_validade"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Validade</FormLabel>
<FormControl>
<Input {...field} type="date" className="w-full" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
</TabsContent>
{/* Casamento / Conjuge */}
<TabsContent value="casamento" className="space-y-4">
<FormField control={form.control} name="pessoa_conjuge_nome" render={({ field }) => (
<FormItem>
<FormLabel>Nome do Cônjuge</FormLabel>
<FormControl>
<Input {...field} placeholder="Digite o nome do cônjuge" />
</FormControl>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="cert_casamento_data" render={({ field }) => (
<FormItem>
<FormLabel>Data do Casamento</FormLabel>
<FormControl>
<Input type="date" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)} />
</TabsContent>
{/* Outros */}
<TabsContent value="outros" className="space-y-4">
<FormField control={form.control} name="observacao" render={({ field }) => (
<FormItem>
<FormLabel>Observação</FormLabel>
<FormControl>
<Textarea {...field} placeholder="Digite observações" />
</FormControl>
<FormMessage />
</FormItem>
)} />
</TabsContent>
</Tabs>
{/* Rodapé do Dialog */}

View file

@ -1,217 +0,0 @@
'use client';
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger
} from "@/components/ui/dropdown-menu";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow
} from "@/components/ui/table";
import { EllipsisIcon, PencilIcon, Trash2Icon } from "lucide-react";
import TPessoaInterface from "../../_interfaces/TPessoaInterface";
interface TPessoaTableProps {
data: TPessoaInterface[];
onEdit: (item: TPessoaInterface, isEditingFormStatus: boolean) => void;
onDelete: (item: TPessoaInterface, isEditingFormStatus: boolean) => void;
}
/**
* Renderiza o badge de situação
*/
function StatusBadge({ situacao }: { situacao: string }) {
const isActive = situacao === "A";
const baseClasses =
"text-xs font-medium px-2.5 py-0.5 rounded-sm me-2";
const activeClasses =
"bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300";
const inactiveClasses =
"bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300";
return (
<span className={`${baseClasses} ${isActive ? activeClasses : inactiveClasses}`}>
{isActive ? "Ativo" : "Inativo"}
</span>
);
}
export default function TCensecTable({
data,
onEdit,
onDelete
}: TPessoaTableProps) {
return (
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-16 text-center">#</TableHead>
<TableHead className="w-32 text-center">Tipo</TableHead>
<TableHead>
Nome / Email
</TableHead>
<TableHead className="w-44">CPF / CNPJ</TableHead>
<TableHead className="w-44">Telefone</TableHead>
<TableHead className="w-52">Cidade / UF</TableHead>
<TableHead className="w-36">Data Cadastro</TableHead>
<TableHead className="w-28 text-center">Status</TableHead>
<TableHead className="text-right w-20">Ações</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{data.map((item) => (
<TableRow
key={item.pessoa_id}
className="hover:bg-muted/50 transition-colors cursor-pointer"
>
{/* ID */}
<TableCell className="text-center font-medium">
{Number(item.pessoa_id)}
</TableCell>
{/* Tipo de pessoa */}
<TableCell className="text-center">
<span
className={`px-2 py-1 rounded-full text-xs font-medium ${item.pessoa_tipo === "F"
? "bg-blue-100 text-blue-700"
: "bg-green-100 text-green-700"
}`}
>
{item.pessoa_tipo === "F" ? "Física" : "Jurídica"}
</span>
</TableCell>
{/* Nome e Email*/}
<TableCell>
<div className="flex items-center gap-3">
{/* Avatar */}
<div className="w-10 h-10 rounded-full bg-gray-200 flex items-center justify-center overflow-hidden">
{item?.foto ? (
<img
src={item?.foto}
alt={item.nome || "Avatar"}
className="w-full h-full object-cover"
/>
) : (
<span className="text-sm font-medium text-gray-700">
{item.nome
? item.nome
.split(" ")
.slice(0, 2) // Pega no máximo 2 palavras
.map((n) => n[0])
.join("")
.toUpperCase()
: "?"}
</span>
)}
</div>
{/* Nome e Email */}
<div>
<div className="font-semibold text-gray-900">
{item.nome || "-"}
</div>
<div className="text-sm text-gray-500">
{item.email || "-"}
</div>
</div>
</div>
</TableCell>
{/* CPF/CNPJ */}
<TableCell>
{item.cpf_cnpj
? item.pessoa_tipo === "F"
? item.cpf_cnpj.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, "$1.$2.$3-$4")
: item.cpf_cnpj.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, "$1.$2.$3/$4-$5")
: "-"}
</TableCell>
{/* Telefone */}
<TableCell>
{item.telefone
? `(${item.ddd || ""}) ${item.telefone.replace(/(\d{5})(\d{4})/, "$1-$2")}`
: "-"}
</TableCell>
{/* Cidade / UF */}
<TableCell>
{item.cidade && item.uf ? `${item.cidade} - ${item.uf}` : "-"}
</TableCell>
{/* Data Cadastro */}
<TableCell>
{item.data_cadastro
? new Date(item.data_cadastro).toLocaleDateString("pt-BR")
: "-"}
</TableCell>
{/* Status (Exemplo: enviado_cnncnb) */}
<TableCell className="text-center">
<span
className={`px-2 py-1 rounded-full text-xs font-medium ${item.enviado_cnncnb
? "bg-green-100 text-green-700"
: "bg-gray-200 text-gray-700"
}`}
>
{item.enviado_cnncnb ? "Enviado" : "Pendente"}
</span>
</TableCell>
{/* Ações */}
<TableCell className="text-right">
<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(item, true)}
>
<PencilIcon className="mr-2 h-4 w-4" />
Editar
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
className="cursor-pointer text-red-600"
onSelect={() => onDelete(item, true)}
>
<Trash2Icon className="mr-2 h-4 w-4" />
Remover
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
}

View file

@ -3,7 +3,7 @@ import z from "zod";
export const TPessoaSchema = z.object({
pessoa_id: z.number().optional(),
pessoa_tipo: z.string().optional(),
nome: 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(),

4
src/enums/SexoEnum.ts Normal file
View file

@ -0,0 +1,4 @@
export enum Sexo {
M = 'Masculino',
F = 'Feminino',
}