[MVPTN-88] feat(Form): Formulário de cadastro estático
This commit is contained in:
parent
3fe6ed8c08
commit
b7f35889a6
5 changed files with 654 additions and 415 deletions
11
src/actions/text/GetCapitalize.ts
Normal file
11
src/actions/text/GetCapitalize.ts
Normal 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();
|
||||
}
|
||||
|
|
@ -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 */}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
);
|
||||
}
|
||||
|
|
@ -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
4
src/enums/SexoEnum.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export enum Sexo {
|
||||
M = 'Masculino',
|
||||
F = 'Feminino',
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue