feat(TAto): Implementa a listagem de atos para realizar o pedido de certidão

This commit is contained in:
Keven 2025-12-17 10:12:42 -03:00
parent 4561194b6b
commit b5ea5a75a8
17 changed files with 753 additions and 52 deletions

View file

@ -57,10 +57,6 @@ const data = {
title: 'Pedidos',
url: '/servicos/pedidos/',
},
{
title: 'Certidões',
url: '/servicos/certidoes/',
},
],
},
{

View file

@ -3,13 +3,13 @@ import { ArrowUpDownIcon } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface';
import { FormatCPF } from '@/shared/actions/CPF/FormatCPF';
import { FormatDateTime } from '@/shared/actions/dateTime/FormatDateTime';
import { FormatPhone } from '@/shared/actions/phone/FormatPhone';
import GetNameInitials from '@/shared/actions/text/GetNameInitials';
import empty from '@/shared/actions/validations/empty';
import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface';
/**
* Função para criar a definição das colunas da tabela

View file

@ -37,47 +37,92 @@ function TPessoaTableFormSubview({
return (
<div>
<Item variant="outline">
<ItemMedia>
<Avatar className="size-10">
<AvatarImage src={``} />
<AvatarFallback>{GetNameInitials(data.pessoa?.nome)}</AvatarFallback>
</Avatar>
</ItemMedia>
<ItemContent>
<ItemTitle>
{data.pessoa?.cpf_cnpj} - {data.pessoa?.nome}
</ItemTitle>
<ItemDescription>{data.pessoa?.email || 'Email não informado'}</ItemDescription>
{params
.filter((param) => Number(param.valor) === data?.servico?.servico_tipo_id)
.map((param) => (
<TPessoaCartaoForm form={form} index={item_index} key={param.config_id} />
))}
</ItemContent>
<ItemActions>
{data?.servico?.requer_biometria === 'S' && (
<BiometriaButton
status={statusBiometria}
onCaptureSuccess={handleCaptureSuccess}
/>
)}
{data?.servico?.requer_biometria && (
<Button
type="button"
size="icon-lg"
variant="outline"
className="cursor-pointer rounded-full"
aria-label="Capturar imagem"
onClick={() => {
setIsWebCamOpenDialog(true);
}}
>
<WebcamIcon />
</Button>
)}
</ItemActions>
</Item>
{data.pessoa && (
<Item variant="outline">
<ItemMedia>
<Avatar className="size-10">
<AvatarImage src={``} />
<AvatarFallback>{GetNameInitials(data.pessoa?.nome)}</AvatarFallback>
</Avatar>
</ItemMedia>
<ItemContent>
<ItemTitle>
{data.pessoa?.cpf_cnpj} - {data.pessoa?.nome}
</ItemTitle>
<ItemDescription>{data.pessoa?.email || 'Email não informado'}</ItemDescription>
{params
.filter((param) => Number(param.valor) === data?.servico?.servico_tipo_id)
.map((param) => (
<TPessoaCartaoForm form={form} index={item_index} key={param.config_id} />
))}
</ItemContent>
<ItemActions>
{data?.servico?.requer_biometria === 'S' && (
<BiometriaButton
status={statusBiometria}
onCaptureSuccess={handleCaptureSuccess}
/>
)}
{data?.servico?.requer_biometria && (
<Button
type="button"
size="icon-lg"
variant="outline"
className="cursor-pointer rounded-full"
aria-label="Capturar imagem"
onClick={() => {
setIsWebCamOpenDialog(true);
}}
>
<WebcamIcon />
</Button>
)}
</ItemActions>
</Item>
)}
{data.servico.tipo_item == 'C' && (
<Item variant="outline">
<ItemMedia>
<Avatar className="size-10">
<AvatarImage src={``} />
<AvatarFallback>{GetNameInitials(data.pessoa?.nome)}</AvatarFallback>
</Avatar>
</ItemMedia>
<ItemContent>
<ItemTitle>
{data.pessoa?.cpf_cnpj} - {data.pessoa?.nome}
</ItemTitle>
<ItemDescription>{data.pessoa?.email || 'Email não informado'}</ItemDescription>
{params
.filter((param) => Number(param.valor) === data?.servico?.servico_tipo_id)
.map((param) => (
<TPessoaCartaoForm form={form} index={item_index} key={param.config_id} />
))}
</ItemContent>
<ItemActions>
{data?.servico?.requer_biometria === 'S' && (
<BiometriaButton
status={statusBiometria}
onCaptureSuccess={handleCaptureSuccess}
/>
)}
{data?.servico?.requer_biometria && (
<Button
type="button"
size="icon-lg"
variant="outline"
className="cursor-pointer rounded-full"
aria-label="Capturar imagem"
onClick={() => {
setIsWebCamOpenDialog(true);
}}
>
<WebcamIcon />
</Button>
)}
</ItemActions>
</Item>
)}
{isWebCamOpenDialog && (
<WebCamDialog
isOpen={isWebCamOpenDialog}

View file

@ -25,6 +25,12 @@ export default function TServicoPedidoItemLocalPrepare(data, response) {
};
}
if (data.servico_tipo.tipo_item === 'C') {
item.subview = {
servico: data.servico_tipo,
};
}
return item
}

View file

@ -0,0 +1,106 @@
import { ColumnDef } from '@tanstack/react-table';
import { ArrowUpDownIcon } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface';
import { FormatDateTime } from '@/shared/actions/dateTime/FormatDateTime';
export function TAtoTableFormColumnsDialog(
setSelectedTPessoa: React.Dispatch<React.SetStateAction<any | null>>,
): ColumnDef<TPessoaInterface>[] {
return [
{
id: 'select',
header: '',
cell: ({ row, table }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => {
// Limpa todas as seleções antes de selecionar uma nova
table.resetRowSelection();
row.toggleSelected(!!value);
setSelectedTPessoa(value ? row.original : null);
}}
aria-label="Select row"
/>
),
enableSorting: false,
enableHiding: false,
},
// ID
{
accessorKey: 'ato_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('ato_id')),
enableSorting: false,
},
// CPF
{
accessorKey: 'protocolo',
header: ({ column }) => (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
Protocolo <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
</Button>
),
cell: ({ row }) => Number(row.getValue('protocolo')),
enableSorting: true,
},
// Data LAvratura
{
accessorKey: 'data_lavratura',
header: ({ column }) => (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
Lavratura <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
</Button>
),
cell: ({ row }) => FormatDateTime(row.getValue('data_lavratura')),
enableSorting: true,
},
// Folha Inicial
{
accessorKey: 'folha_inicial',
header: ({ column }) => (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
Fl. Inicial <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
</Button>
),
cell: ({ row }) => Number(row.getValue('folha_inicial')),
enableSorting: true,
},
// Folha Final
{
accessorKey: 'folha_final',
header: ({ column }) => (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
Fl. Inicial <ArrowUpDownIcon className="ml-1 h-4 w-4 cursor-pointer" />
</Button>
),
cell: ({ row }) => Number(row.getValue('folha_final')),
enableSorting: true,
},
];
}

View file

@ -0,0 +1,99 @@
'use client';
import { useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface';
import { useTAtoIndexHook } from '@/packages/servicos/hooks/TAto/useTAtoIndexHook';
import TAtoTableFormInterface from '@/packages/servicos/interfaces/TAto/TAtoTableFormInterface';
import { DataTable } from '@/shared/components/dataTable/DataTable';
import LoadingButton from '@/shared/components/loadingButton/LoadingButton';
import { TAtoTableFormColumnsDialog } from './TAtoTableFormColumnsDialog';
export default function TAtoTableFormDialog({
isOpen,
onClose,
onSave,
buttonIsLoading,
}: TAtoTableFormInterface) {
const { tAto, fetchTAto } = useTAtoIndexHook();
const [atos, setAtos] = useState<any>();
const [selectedTPessoa, setSelectedTPessoa] = useState<TPessoaInterface | null>(null);
// Executa o Hook de Acordo com o tipo de pessoa informado
const loadData = async () => {
await fetchTAto();
};
// Atualiza a variavel de pessoa quando tiver alteração na variavel de pessoas fisicas
useEffect(() => {
setAtos(tAto);
}, [tAto]);
// Executa o hook correspondente ao tipo de pessoa, sempre que o tipo pessoa mudar
useEffect(() => {
// Dispara o carregamento de informações
loadData();
}, []);
const columns = TAtoTableFormColumnsDialog(setSelectedTPessoa);
return (
<Dialog
open={isOpen}
onOpenChange={(open) => {
if (!open) onClose(null, false);
}}
>
<DialogContent className="max-h-[70vh] w-full max-w-full overflow-auto p-6 sm:max-w-4xl md:max-w-6xl lg:max-w-6xl">
<DialogHeader>
<DialogTitle>Atos</DialogTitle>
<DialogDescription>Busque o Ato desejado</DialogDescription>
</DialogHeader>
<div className="max-h-[50vh] overflow-y-auto">
<DataTable
data={atos}
columns={columns}
filterColumn="nome_completo"
filterPlaceholder="Buscar por nome ou email..."
/>
</div>
{/* Rodapé do Dialog */}
<DialogFooter className="mt-4">
<DialogClose asChild>
<Button
variant="outline"
type="button"
onClick={() => onClose(null, false)}
className="cursor-pointer"
>
Cancelar
</Button>
</DialogClose>
<LoadingButton
text="Selecionar"
textLoading="Aguarde..."
loading={buttonIsLoading}
type="button"
onClick={() => {
onSave(selectedTPessoa);
onClose(null, false);
}}
/>
</DialogFooter>
</DialogContent>
</Dialog>
);
}

View file

@ -0,0 +1,195 @@
import { useState } from 'react';
import { FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import TPessoaCartaoFormInterface from '@/packages/servicos/interfaces/TPessoaCartao/TPessoaCartaoFormInterface';
import ConfirmacaoSelect from '@/shared/components/confirmacao/ConfirmacaoSelect';
import TiposCertidoesSelect from '@/shared/components/tiposCertidoes/TiposCertidoesSelect';
import { TipoCertidaoEnum } from '@/shared/enums/TipoCertidoesEnum';
export default function TServicoPedidoCertidaoForm({ index, form }: TPessoaCartaoFormInterface) {
const [tipoCertidao, setTipoCertidao] = useState<TipoCertidaoEnum | null>(null);
return (
<div>
<div className="grid w-full grid-cols-12 gap-4">
{/* Tipo Certidão*/}
<div className="col-span-12 sm:col-span-12 md:col-span-12">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Tipo de Certidão</FormLabel>
<TiposCertidoesSelect
field={{
...field,
onChange: (value: number) => {
field.onChange(value);
setTipoCertidao(value as TipoCertidaoEnum);
},
}}
/>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* Verifica o tipo de formulário que deve exibir */}
{tipoCertidao && (
<>
{tipoCertidao === 1 && (
<>
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Protocolo</FormLabel>
<Input {...field} type="text" />
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Pedido</FormLabel>
<Input {...field} type="text" />
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Livro</FormLabel>
<Input {...field} type="text" />
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Folha Inicial</FormLabel>
<Input {...field} type="text" />
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="col-span-12 sm:col-span-12 md:col-span-12">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Natureza</FormLabel>
<Input {...field} type="text" />
<FormMessage />
</FormItem>
)}
/>
</div>
</>
)}
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Livro</FormLabel>
<Input {...field} type="text" />
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Fl. Inicial</FormLabel>
<Input {...field} type="text" />
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Fl. Final</FormLabel>
<Input {...field} type="text" />
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="col-span-12 sm:col-span-12 md:col-span-3">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Lavratura</FormLabel>
<Input {...field} type="text" />
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Páginas</FormLabel>
<Input {...field} type="text" />
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="col-span-12 sm:col-span-12 md:col-span-6">
<FormField
control={form.control}
name={`itens.${index}.tipo_certidao`}
render={({ field }) => (
<FormItem>
<FormLabel>Frente e Verso</FormLabel>
<ConfirmacaoSelect field={field} />
<FormMessage />
</FormItem>
)}
/>
</div>
</>
)}
</div>
</div>
);
}

View file

@ -34,6 +34,8 @@ import {
} from '@/shared/components/step/stepNavigator';
import TipoPagamentoSelect from '@/shared/components/tipoPagamento/TipoPagamentoSelect';
import TAtoTableFormDialog from '../TAto/TAtoTableFormDialog';
export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedidoFormInterface) {
const tServicoPedidoController = useTServicoPedidoFormControllerHook(servico_pedido_id)
@ -437,6 +439,16 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
buttonIsLoading={tServicoPedidoController.isSaving}
/>
)}
{/* Modal TAto */}
{tServicoPedidoController.isAtoFormOpen && (
<TAtoTableFormDialog
isOpen={tServicoPedidoController.isAtoFormOpen}
onClose={tServicoPedidoController.handleCloseAtoForm}
onSave={tServicoPedidoController.handleAddItemWithPessoa}
buttonIsLoading={tServicoPedidoController.isSaving}
/>
)}
</Form>
</div>
);

View file

@ -0,0 +1,13 @@
import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler';
import API from '@/shared/services/api/Api';
import { Methods } from '@/shared/services/api/enums/ApiMethodEnum';
async function executeTAtoIndexData() {
const api = new API();
return await api.send({
method: Methods.GET,
endpoint: `servicos/atos/t_ato/`,
});
}
export const TAtoIndexData = withClientErrorHandler(executeTAtoIndexData);

View file

@ -0,0 +1,23 @@
import { useState } from 'react';
import TAtoInterface from '@/packages/servicos/interfaces/TAto/TAtoInterface';
import { TAtoIndexService } from '@/packages/servicos/services/TAto/TAtoIndexService';
import { useResponse } from '@/shared/components/response/ResponseContext';
export const useTAtoIndexHook = () => {
const { setResponse } = useResponse();
const [tAto, setTAto] = useState<TAtoInterface[]>([]);
const fetchTAto = async () => {
const response = await TAtoIndexService();
setTAto(response.data);
setResponse(response);
return response.data;
};
return { tAto, fetchTAto };
};

View file

@ -16,7 +16,6 @@ import { TServicoPedidoFormValues } from '@/packages/servicos/schemas/TServicoPe
import { useResponse } from '@/shared/components/response/ResponseContext';
import { StepNavigatorRef } from '@/shared/components/step/stepNavigator';
import { SituacoesEnum } from '@/shared/enums/SituacoesEnum';
import { TipoPessoaEnum } from '@/shared/enums/TipoPessoaEnum';
export default function useTServicoPedidoFormControllerHook(servico_pedido_id?: number) {
@ -27,6 +26,7 @@ export default function useTServicoPedidoFormControllerHook(servico_pedido_id?:
const [isSaving, setIsSaving] = useState(false);
const [isAdding, setIsAdding] = useState(false);
const [isPessoaFormOpen, setIsPessoaFormOpen] = useState(false);
const [isAtoFormOpen, setAtoFormOpen] = useState(false);
const [isSaveConfirmOpen, setIsSaveConfirmOpen] = useState(false);
const [isCancelDialogOpen, setIsCancelDialogOpen] = useState(false);
const [selectedPessoaTipo, setSelectedPessoaTipo] = useState('');
@ -36,10 +36,10 @@ export default function useTServicoPedidoFormControllerHook(servico_pedido_id?:
// Controles de formulário
const handleClosePessoaForm = useCallback(() => setIsPessoaFormOpen(false), []);
const handleCloseAtoForm = useCallback(() => setAtoFormOpen(false), []);
const handleOpenSaveConfirm = useCallback(() => setIsSaveConfirmOpen(true), []);
const handleCloseSaveConfirm = useCallback(() => setIsSaveConfirmOpen(false), []);
// Hooks
// const playSuccess = useSoundHook("/sounds/success.mp3");
const { setResponse } = useResponse();
const { saveTServicoPedido } = useTServicoPedidoSaveHook();
@ -213,11 +213,14 @@ export default function useTServicoPedidoFormControllerHook(servico_pedido_id?:
setIsPessoaFormOpen(true);
}, []);
// Habilita o formulário de itens
const handleOpenAtoForm = useCallback(() => {
setAtoFormOpen(true);
}, []);
// Adiciona o item a tabela e verifica se deve ou não montar a subview da linha da tabela
const handleSelectServicoTipo = useCallback(() => {
const tipoPessoa = [TipoPessoaEnum.FISICA, TipoPessoaEnum.JURIDICA]
// Verifica se o emolumento e o tipo de serviço foram selecionados
if (!selectedServicoTipo || !selectedEmolumento) {
setResponse({
@ -228,14 +231,20 @@ export default function useTServicoPedidoFormControllerHook(servico_pedido_id?:
}
// Verifica se deve selecionar pessoas
switch (tipoPessoa.includes(selectedServicoTipo.tipo_pessoa)) {
switch (selectedServicoTipo.tipo_item) {
// Habilita o formulário
case true:
case 'R':
handleOpenPessoaForm(selectedServicoTipo.tipo_pessoa);
break;
// Habilita o formulário
case 'C':
handleOpenAtoForm()
break;
// Adiciona direto
default:
@ -335,6 +344,7 @@ export default function useTServicoPedidoFormControllerHook(servico_pedido_id?:
isSaving,
isAdding,
isPessoaFormOpen,
isAtoFormOpen,
isSaveConfirmOpen,
isCancelDialogOpen,
shouldKeepFormOpen,
@ -356,6 +366,7 @@ export default function useTServicoPedidoFormControllerHook(servico_pedido_id?:
handleConfirmCancel,
handleCloseCancelDialog,
handleClosePessoaForm,
handleCloseAtoForm,
handleAddItemWithPessoa,
handleOpenSaveConfirm,
handleChangeQtd

View file

@ -0,0 +1,83 @@
export default interface TAtoInterface {
ato_id?: string;
ato_tipo_id?: string;
escrevente_ato_id?: string;
escrevente_assina_id?: string;
livro_andamento_id?: string;
data_abertura?: string;
data_lavratura?: string;
usuario_id?: string;
protocolo?: string;
alienacao_data?: string;
qualificacao_imovel_id?: string;
folha_inicial?: string;
folha_final?: string;
folha_total?: string;
alienacao_forma?: string;
grs_numero?: string;
texto?: string;
texto_finalizacao?: string;
natureza_id?: string;
valor_pagamento?: string;
situacao_ato?: string;
texto_imovel_geral?: string;
texto_assinatura?: string;
cancelado_data?: string;
cancelado_motivo?: string;
cancelado_observacao?: string;
cancelado_usuario_id?: string;
data_cancelamento?: string;
alienacao_datalavratura?: string;
ato_antigo?: string;
folha_letra?: string;
qtd_imovel?: string;
minuta_protegida?: string;
havido_marcacao_id?: string;
observacao?: string;
selo_livro_id?: string;
usar_tabela_auxiliar?: string;
ato_antigo_ocorrencia?: string;
fonte_tamanho?: string;
selo_recuo?: string;
ato_antigo_protocolo?: string;
ato_anterior_origem?: string;
ato_anterior_livro?: string;
ato_anterior_finicial?: string;
ato_anterior_tb_cartorio_id?: string;
ato_anterior_outorgante?: string;
ato_anterior_observacao?: string;
ato_anterior_ato_id?: string;
ato_anterior_data?: string;
ato_anterior_anotacao_adicional?: string;
ato_anterior_ato_tipo_id?: string;
ato_anterior_valor_documento?: string;
cadastrar_imovel?: string;
filho_maior_qtd?: string;
filho_maior_descricao?: string;
filho_menor_qtd?: string;
filho_menor_descricao?: string;
casamento_data?: string;
casamento_tb_regime_id?: string;
ato_anterior_ffinal?: string;
resp_filhos_maiores?: string;
resp_filhos_menores?: string;
censec_naturezalitigio_id?: string;
censec_acordo?: string;
nlote?: string;
especie_pagamento?: string;
fora_cartorio?: string;
nfse_id?: string;
acao?: string;
data_protocolo?: string;
frente_verso?: string;
chave_importacao?: string;
lavratura_online?: string;
data_prevista_entrega?: string;
usuario_id_lavratura?: string;
ativo?: string;
convalidacao?: string;
lado_folha_fim?: string;
ato_oneroso?: string;
mne?: string;
eh_restrito?: string;
}

View file

@ -0,0 +1,6 @@
export default interface TAtoTableFormInterface {
isOpen: boolean;
onClose: (item: null, isFormStatus: boolean) => void;
onSave: (data: any) => void;
buttonIsLoading: boolean;
}

View file

@ -0,0 +1,11 @@
'use server';
import { TAtoIndexData } from '@/packages/servicos/data/TAto/TAtoIndexData';
import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler';
async function executeTAtoIndexService() {
const response = await TAtoIndexData();
return response;
}
export const TAtoIndexService = withClientErrorHandler(executeTAtoIndexService);

View file

@ -0,0 +1,80 @@
import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react';
import React from 'react';
import { Button } from '@/components/ui/button';
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from '@/components/ui/command';
import { FormControl } from '@/components/ui/form';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { cn } from '@/lib/utils';
import { TipoCertidoesEnum } from '@/shared/enums/TipoCertidoesEnum';
import TiposCertidoesSelectInterface from './interfaces/TiposCertidoesSelectInterface';
export default function TiposCertidoesSelect({ field }: TiposCertidoesSelectInterface) {
const [open, setOpen] = React.useState(false);
const options = Object.entries(TipoCertidoesEnum).map(([key, label]) => ({
value: Number(key),
label,
}));
// Label exibida atualmente
const selectedLabel =
field.value !== undefined && field.value !== null
? options.find((item) => item.value === Number(field.value))?.label
: 'Selecione...';
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<FormControl className="w-full">
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className="justify-between"
>
{selectedLabel}
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-[var(--radix-popover-trigger-width)] p-0">
<Command>
<CommandInput placeholder="Buscar tipo de parte..." />
<CommandList>
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
<CommandGroup>
{options.map((item) => (
<CommandItem
key={item.value}
value={item.label.toLowerCase()}
onSelect={() => {
field.onChange(item.value); // envia número
setOpen(false);
}}
>
<CheckIcon
className={cn(
'mr-2 h-4 w-4',
Number(field.value) === item.value ? 'opacity-100' : 'opacity-0',
)}
/>
{item.label}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
);
}

View file

@ -0,0 +1,6 @@
export default interface TiposCertidoesSelectInterface {
field: {
value?: number | null;
onChange: (value: number) => void;
};
};

View file

@ -0,0 +1,9 @@
export const TipoCertidoesEnum = {
1: 'Sistema',
2: 'Imagem',
3: 'Imagem Antiga',
4: 'Transcrever',
5: 'Negativa/Positiva',
} as const;
export type TipoCertidaoEnum = keyof typeof TipoCertidoesEnum;