[MVPTN-37] fix(Pedido): Ajustes diversos na tela de pedido

This commit is contained in:
Keven 2025-11-17 17:39:04 -03:00
parent bc2c2ef3dd
commit fdd4cf7cfc
29 changed files with 298 additions and 624 deletions

View file

@ -21,21 +21,24 @@ import GetNameInitials from '@/shared/actions/text/GetNameInitials';
import WebCamDialog from '@/shared/components/webcam/WebCamDialog';
import { useFingerTechIndexHook } from '@/shared/hooks/FingerTech/useFingerTechIndexHook';
import TPessoaTableFormSubviewInterface from '../../interfaces/TPessoa/TPessoaTableFormSubviewInterface';
function TPessoaTableFormSubview({
item_index,
data,
params,
form,
}: any) {
}: TPessoaTableFormSubviewInterface) {
const [isWebCamOpenDialog, setIsWebCamOpenDialog] = useState(false)
const { base64, captureFingerTech } = useFingerTechIndexHook();
// Chama o leitor biométrico
const handleBiometria = useCallback(() => {
console.log(captureFingerTech())
})
}, [])
// Define a classe do botão de biometria com base no status, sem estado extra
const biometriaButtonClass = useMemo(() => {
@ -115,7 +118,7 @@ function TPessoaTableFormSubview({
isOpen={isWebCamOpenDialog}
onClose={() => { setIsWebCamOpenDialog(false) }}
onSave={() => { }}
key={1}
key={item_index}
/>
)}
</div>

View file

@ -0,0 +1,11 @@
import { UseFormReturn } from "react-hook-form";
import { TServicoPedidoFormValues } from "@/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema";
import GConfigInterface from "@/shared/interfaces/GConfigInterface";
export default interface TPessoaTableFormSubviewInterface {
item_index: number,
data: any,
params: GConfigInterface[],
form: UseFormReturn<TServicoPedidoFormValues>;
}

View file

@ -1,12 +1,45 @@
import { GCalculoServico } from "@/packages/administrativo/data/GCalculo/GCalculoServicoData";
import GCalculoServicoInterface from "@/packages/administrativo/interfaces/GCalculo/GCalculoServicoInterface";
import { PrepareTServicoItemPedidoCalculoResponse } from "@/packages/servicos/actions/TServicoPedido/PrepareTServicoItemPedidoResponseItem";
import TServicoItemPedidoAddInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface";
import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/withClientErrorHandler";
async function executeGCalculoServicoService(payload: GCalculoServicoInterface, data) {
async function executeGCalculoServicoService(payload: GCalculoServicoInterface, data: TServicoItemPedidoAddInterface) {
const response = await GCalculoServico(payload);
const item = PrepareTServicoItemPedidoCalculoResponse(response, data)
if (response.status == 404 || response.status == 400) {
return {
'status': response.status,
'message': 'Erro ao processar dados'
};
}
const item = {
emolumento_id: response.data.emolumento_id,
emolumento_item_id: response.data.emolumento_item_id ?? null,
servico_tipo_id: data.servico_tipo.servico_tipo_id ?? 0,
tipo_item: data.servico_tipo.tipo_item ?? "",
descricao: data.servico_tipo.descricao ?? "",
tabela: data.servico_tipo?.descricao ?? "",
situacao: "F",
qtd: 1,
valor: response.data.valor_total ?? 0,
emolumento: response.data.valor_emolumento ?? 0,
fundesp: response.data.valor_fundos ?? 0,
taxa_judiciaria: response.data.taxa_judiciaria ?? 0,
valor_iss: response.data.valor_iss ?? 0,
pessoa_id: data?.pessoa?.pessoa_id ?? null,
subview: {
servico: data.servico_tipo,
pessoa: data.pessoa,
}
};
return item;
}

View file

@ -1,38 +0,0 @@
import TServicoItemPedidoAddInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface";
import TServicoItemPedidoAddResponseInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddResponseInterface";
export function PrepareTServicoItemPedidoCalculoResponse(
result: any,
data: TServicoItemPedidoAddInterface
) {
if (result.status == 404 || result.status == 400) {
return {
'status': result.status,
'message': result.detail
};
}
const item: TServicoItemPedidoAddResponseInterface = {
emolumento_id: result.data.emolumento_id,
emolumento_item_id: result.data.emolumento_item_id ?? null,
servico_tipo_id: data.servico_tipo.servico_tipo_id ?? 0,
tipo_item: data.servico_tipo.tipo_item ?? "",
descricao: data.servico_tipo.descricao ?? "",
tabela: data.servico_tipo?.descricao ?? "",
situacao: "F",
qtd: 1,
valor: result.data.valor_total ?? 0,
emolumento: result.data.valor_emolumento ?? 0,
fundesp: result.data.valor_fundos ?? 0,
taxa_judiciaria: result.data.taxa_judiciaria ?? 0,
valor_iss: result.data.valor_iss ?? 0,
pessoa_id: data.pessoa.pessoa_id ?? null,
subview: {
servico: data.servico_tipo,
pessoa: data.pessoa,
}
};
return item;
}

View file

@ -1,8 +1,8 @@
import TServicoItemPedidoAddInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface";
export default function PrepareTServicoItemPedidoPayload(data: TServicoItemPedidoAddInterface) {
export default function TServicoPedidoItemPreparePayload(data: TServicoItemPedidoAddInterface) {
data.quantidade = 1
data.qtd = 1
data.valor_documento = 0
// Verifica dados obrigatórios de serviço e emolumento
@ -14,25 +14,17 @@ export default function PrepareTServicoItemPedidoPayload(data: TServicoItemPedid
}
// Valida sistema_id (padrão 2, mas ainda assim precisa ser válido)
if (!data?.emolumento.sistema_id || data.servico_tipo.sistema_id <= 0) {
if (!data?.emolumento.sistema_id || data.servico_tipo.servico_tipo_id <= 0) {
return {
status: 400,
message: 'Sistema inválido ou não informado.'
};
}
// Valida quantidade (padrão 1, precisa ser >= 1)
if (Number(data.quantidade) < 1) {
return {
status: 400,
message: 'Quantidade inválida.'
};
}
return {
sistema_id: data.emolumento.sistema_id,
valor_documento: data.valor_documento,
quantidade: data.quantidade,
quantidade: data.qtd,
emolumento_id: data.emolumento.emolumento_id,
};

View file

@ -1,78 +0,0 @@
import { ColumnDef } from '@tanstack/react-table';
import { EllipsisIcon, PencilIcon, Trash2Icon } from 'lucide-react';
import { Button } from '@/components/ui/button';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import GetCapitalize from '@/shared/actions/text/GetCapitalize';
import { SortableHeader } from '@/shared/components/dataTable/SortableHeader';
import TServicoItemPedidoInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce';
export default function TServicoItemPedidoColumns(
onEdit: (item: TServicoItemPedidoInterface, isEditingFormStatus: boolean) => void,
onDelete: (item: TServicoItemPedidoInterface, isEditingFormStatus: boolean) => void,
): ColumnDef<TServicoItemPedidoInterface>[] {
return [
// ID
{
accessorKey: 'gramatica_id',
header: ({ column }) => SortableHeader('ID', column),
cell: ({ row }) => Number(row.getValue('gramatica_id')),
enableSorting: true,
},
// Descrição
{
accessorKey: 'palavra',
header: ({ column }) => SortableHeader('Palavra', column),
cell: ({ row }) => GetCapitalize(String(row.getValue('palavra') || '')),
},
// Ações
{
id: 'actions',
header: 'Ações',
cell: ({ row }) => {
const natureza = row.original;
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<EllipsisIcon />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent side="left" align="start">
<DropdownMenuGroup>
<DropdownMenuItem onSelect={() => onEdit(natureza, true)}>
<PencilIcon className="mr-2 h-4 w-4" />
Editar
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
className="text-red-600"
onSelect={() => onDelete(natureza, true)}
>
<Trash2Icon className="mr-2 h-4 w-4" />
Remover
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
);
},
enableSorting: false,
enableHiding: false,
},
];
}

View file

@ -1,110 +0,0 @@
'use client';
import { useEffect } from 'react';
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 { ResetFormIfData } from '@/shared/actions/form/ResetFormIfData';
import LoadingButton from '@/shared/components/loadingButton/LoadingButton';
import { useTServicoItemPedidoFormHook } from '../../hooks/TServicoItemPedido/useTServicoItemPedidoFormHook';
import { TServicoItemPedidoFormInterface } from '../../interfaces/TServicoItemPedido/TServicoItemPedidoFormInterface';
/**
* Formulário de cadastro/edição de Natureza
* Baseado nos campos da tabela G_NATUREZA
*/
export default function TServicoItemPedidoForm({
isOpen,
data,
onClose,
onSave,
buttonIsLoading,
}: TServicoItemPedidoFormInterface) {
const form = useTServicoItemPedidoFormHook({});
// Atualiza o formulário quando recebe dados para edição
useEffect(() => {
ResetFormIfData(form, data);
}, [data, form]);
function onError(error: any) {
console.log('Erro no formulário:', error);
}
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-2xl lg:max-w-2xl">
<DialogHeader>
<DialogTitle className="text-lg sm:text-xl">Formulário de Gramática</DialogTitle>
<DialogDescription className="text-muted-foreground text-sm">
Formulário de Gramática
</DialogDescription>
</DialogHeader>
{/* Formulário principal */}
<Form {...form}>
<form onSubmit={form.handleSubmit(onSave, onError)} className="space-y-6">
{/* GRID MOBILE FIRST */}
<div className="grid w-full grid-cols-12 gap-4">
{/* Palavra */}
<div className="col-span-12 sm:col-span-6 md:col-span-12">
<FormField
control={form.control}
name="desc_complementar"
render={({ field }) => (
<FormItem className="col-span-1 sm:col-span-2">
<FormLabel>Palavra</FormLabel>
<FormControl>
<Input
{...field}
type="text"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
{/* Rodapé */}
<DialogFooter className="mt-6 flex flex-col justify-end gap-2 sm:flex-row">
<DialogClose asChild>
<Button variant="outline" type="button">
Cancelar
</Button>
</DialogClose>
<LoadingButton
text="Salvar"
textLoading="Salvando..."
type="submit"
loading={buttonIsLoading}
/>
</DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
);
}

View file

@ -74,23 +74,11 @@ function TServicoItemPedidoFormTableComponent({
<TableCell>R$ {item.valor ?? '---'}</TableCell>
<TableCell>
<div className="flex items-center gap-1 justify-center">
<Button
type="button"
size="icon"
variant="outline"
className="bg-white border h-8 w-8 rounded-lg"
>
<Button type="button" size="icon" variant="outline" className="bg-white border h-8 w-8 rounded-lg" >
<Minus className="h-4 w-4" />
</Button>
<Input type="number" className="h-8 text-center px-1 w-12" />
<Button
type="button"
size="icon"
variant="outline"
className="bg-white border h-8 w-8 rounded-lg"
>
<Button type="button" size="icon" variant="outline" className="bg-white border h-8 w-8 rounded-lg" >
<Plus className="h-4 w-4" />
</Button>
</div>
@ -101,7 +89,7 @@ function TServicoItemPedidoFormTableComponent({
<TableRow className="bg-gray-50">
<TableCell colSpan={7} className="p-4">
<TPessoaTableFormSubview
item_index={item.index}
item_index={Number(item.index)}
data={item.subview}
params={params}
form={form}

View file

@ -1,161 +0,0 @@
'use client';
import { useCallback, useEffect, useState } from 'react';
import { useTServicoItemPedidoDeleteHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoDeleteHook';
import { useTServicoItemPedidoIndexHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook';
import { useTServicoItemPedidoSaveHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoSaveHook';
import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce';
import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog';
import { useConfirmDialog } from '@/shared/components/confirmDialog/useConfirmDialog';
import Loading from '@/shared/components/loading/loading';
import Header from '@/shared/components/structure/Header';
import TServicoItemPedidoForm from './TServicoItemPedidoForm';
import TServicoItemPedidoTable from './TServicoItemPedidoTable';
export default function TServicoItemPedidoIndex() {
// Controle de estado do botão
const [buttonIsLoading, setButtonIsLoading] = useState(false);
// Hooks para leitura e salvamento
const { TServicoItemPedido, indexTServicoItemPedido } = useTServicoItemPedidoIndexHook();
const { saveTServicoItemPedido } = useTServicoItemPedidoSaveHook();
const { deleteTServicoItemPedido } = useTServicoItemPedidoDeleteHook();
// Estados
const [selectedData, setSelectedData] = useState<TServicoItemPedidoInterface | null>(null);
const [isFormOpen, setIsFormOpen] = useState(false);
// Estado para saber qual item será deletado
const [itemToDelete, setItemToDelete] = useState<TServicoItemPedidoInterface | null>(null);
/**
* Hook do modal de confirmação
*/
const { isOpen: isConfirmOpen, openDialog: openConfirmDialog, handleCancel } = useConfirmDialog();
/**
* Abre o formulário no modo de edição ou criação
*/
const handleOpenForm = useCallback((data: TServicoItemPedidoInterface | null) => {
setSelectedData(data);
setIsFormOpen(true);
}, []);
/**
* Fecha o formulário e limpa o andamento selecionado
*/
const handleCloseForm = useCallback(() => {
setSelectedData(null);
setIsFormOpen(false);
}, []);
/**
* Salva os dados do formulário
*/
const handleSave = useCallback(
async (formData: TServicoItemPedidoInterface) => {
// Coloca o botão em estado de loading
setButtonIsLoading(true);
// Aguarda salvar o registro
await saveTServicoItemPedido(formData);
// Remove o botão em estado de loading
setButtonIsLoading(false);
// Atualiza a lista de dados
indexTServicoItemPedido();
},
[saveTServicoItemPedido, indexTServicoItemPedido, handleCloseForm],
);
/**
* Quando o usuário clica em "remover" na tabela
*/
const handleConfirmDelete = useCallback(
(item: TServicoItemPedidoInterface) => {
// 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 deleteTServicoItemPedido(itemToDelete);
// Atualiza a lista
await indexTServicoItemPedido();
// Limpa o item selecionado
setItemToDelete(null);
// Fecha o modal
handleCancel();
}, [itemToDelete, indexTServicoItemPedido, handleCancel]);
/**
* Busca inicial dos dados
*/
useEffect(() => {
indexTServicoItemPedido();
}, []);
/**
* Tela de loading enquanto carrega os dados
*/
if (TServicoItemPedido?.length == 0) {
return <Loading type={2} />;
}
return (
<div>
{/* Cabeçalho */}
<Header
title={'Gramatica'}
description={'Gramatica'}
buttonText={'Nova palavra'}
buttonAction={() => {
handleOpenForm(null);
}}
/>
{/* Tabela de andamentos */}
<TServicoItemPedidoTable data={TServicoItemPedido} onEdit={handleOpenForm} onDelete={handleConfirmDelete} />
{/* Modal de confirmação */}
{isConfirmOpen && (
<ConfirmDialog
isOpen={isConfirmOpen}
title="Confirmar exclusão"
description="Atenção"
message={`Deseja realmente excluir o valor "${itemToDelete?.valor}"?`}
confirmText="Sim, excluir"
cancelText="Cancelar"
onConfirm={handleDelete}
onCancel={handleCancel}
/>
)}
{/* Formulário de criação/edição */}
{isFormOpen && (
<TServicoItemPedidoForm
isOpen={isFormOpen}
data={selectedData}
onClose={handleCloseForm}
onSave={handleSave}
buttonIsLoading={buttonIsLoading}
/>
)}
</div>
);
}

View file

@ -1,23 +0,0 @@
'use client';
import { DataTable } from '@/shared/components/dataTable/DataTable';
import TServicoItemPedidoTableInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoTableInterface';
import TServicoItemPedidoColumns from './TServicoItemPedidoColumns';
/**
* Componente principal da tabela de Naturezas
*/
export default function TServicoItemPedidoTable({ data, onEdit, onDelete }: TServicoItemPedidoTableInterface) {
const columns = TServicoItemPedidoColumns(onEdit, onDelete);
return (
<div>
<DataTable
data={data}
columns={columns}
filterColumn="palavra"
filterPlaceholder="Buscar por descrição da natureza..."
/>
</div>
);
}

View file

@ -1,28 +0,0 @@
import { Input } from "@/components/ui/input";
export function PessoaSubviewForm({ form, index, pessoa }) {
return (
<div className="space-y-3 p-4 border rounded-md bg-gray-50">
<h3 className="font-semibold text-gray-700">
Dados da Pessoa Selecionada
</h3>
<div className="grid grid-cols-2 gap-3">
<div>
<label className="text-sm font-medium">Nome</label>
<Input {...form.register(`itens.${index}.pessoa_nome`)} defaultValue={pessoa?.nome} />
</div>
<div>
<label className="text-sm font-medium">CPF/CNPJ</label>
<Input {...form.register(`itens.${index}.pessoa_documento`)} defaultValue={pessoa?.cpfcnpj}
/>
</div>
</div>
</div>
);
}

View file

@ -28,13 +28,15 @@ import TPessoaTableFormDialog from '@/packages/administrativo/components/TPessoa
import TServicoTipoSelect from '@/packages/administrativo/components/TServicoTipo/TServicoTipoSelect';
import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface';
import HandleSelectTServicoTipoAction from '@/packages/servicos/actions/TServicoPedido/HandleSelectTServicoTipoAction';
import { useTServicoItemPedidoAddHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoAddHook';
import { TServicoItemPedidoFormTable } from '@/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoFormTable';
import { useTServicoItemPedidoCalculoHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCalculoHook';
import { useTServicoItemPedidoIndexHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook';
import { useTServicoItemPedidoLocalAddHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoLocalAddHook';
import { useTServicoPedidoFormHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoFormHook';
import { useTServicoPedidoLoadParamsHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoLoadParamsHook';
import { useTServicoPedidoSaveHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoSaveHook';
import { useTServicoPedidoShowHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook';
import TServicoItemPedidoAddInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface';
import { TServicoPedidoFormInterface } from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoFormInterface';
import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface';
import { FormatCPFCNPJForm } from '@/shared/actions/CPF/FormatCPFCNPJForm';
@ -50,9 +52,6 @@ import {
} from '@/shared/components/step/stepNavigator';
import TipoPagamentoSelect from '@/shared/components/tipoPagamento/TipoPagamentoSelect';
import TServicoItemPedidoAddInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface';
import TServicoItemPedidoAddResponseInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoAddResponseInterface';
import { TServicoItemPedidoFormTable } from '../TServicoItemPedido/TServicoItemPedidoFormTable';
export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedidoFormInterface) {
@ -82,7 +81,7 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
const { saveTServicoPedido } = useTServicoPedidoSaveHook();
const { showTServicoPedido } = useTServicoPedidoShowHook();
const { TServicoItemPedidoLocal, localAddTServicoItemPedido, setLocalTServicoItemPedido } = useTServicoItemPedidoLocalAddHook(setValue);
const { addTServicoItemPedido } = useTServicoItemPedidoAddHook(setValue);
const { addTServicoItemPedido } = useTServicoItemPedidoCalculoHook(setValue);
const { indexTServicoItemPedido } = useTServicoItemPedidoIndexHook();
const { TServicoPedidoParams, loadParamsTServicoPedido } =
useTServicoPedidoLoadParamsHook();
@ -181,7 +180,7 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
setIsAdding(true)
// Constroi um novo item
const newItem: TServicoItemPedidoAddResponseInterface = await addTServicoItemPedido({
const newItem = await addTServicoItemPedido({
servico_tipo: selectedServicoTipo,
emolumento: selectedEmolumento,
pessoa: selectedTPessoa
@ -324,6 +323,7 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
// Dispara a busca do pedido
useEffect(() => {
// Se existir pedido_id, busca o pedido
if (servico_pedido_id) fetchPedido();
}, [servico_pedido_id, fetchPedido]);
@ -331,6 +331,7 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
// Dispara a busca de itens
useEffect(() => {
// Dispara a busca dos itens
setValue('itens', TServicoItemPedidoLocal, { shouldDirty: true });
}, [TServicoItemPedidoLocal, setValue]);

View file

@ -5,21 +5,23 @@ import { FieldValues, UseFormSetValue } from 'react-hook-form';
import { GCalculoServicoService } from '@/packages/administrativo/services/GCalculo/GCalculoServicoService';
import PrepareTServicoItemPedidoPayload from '@/packages/servicos/actions/TServicoPedido/PrepareTServicoItemPedidoPayload';
import TServicoPedidoItemPreparePayload from '@/packages/servicos/actions/TServicoPedidoItem/TServicoPedidoItemPreparePayload';
import TServicoItemPedidoAddInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface';
import { default as TServicoItemPedidoIndexResponseInterface } from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddResponseInterface';
import TServicoItemPedidoCalculoResponseInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface';
import { useResponse } from '@/shared/components/response/ResponseContext';
export function useTServicoItemPedidoAddHook<TFormValues extends FieldValues>(setValue?: UseFormSetValue<TFormValues>) {
export function useTServicoItemPedidoCalculoHook<TFormValues extends FieldValues>(setValue?: UseFormSetValue<TFormValues>) {
const { setResponse } = useResponse();
const [TServicoItemPedido, setTServicoItemPedido] = useState<TServicoItemPedidoIndexResponseInterface[]>([]);
const [TServicoItemPedido, setTServicoItemPedido] = useState<TServicoItemPedidoCalculoResponseInterface[]>([]);
const addTServicoItemPedido = async (data: TServicoItemPedidoAddInterface) => {
// Trata os dados do payload
const payload = PrepareTServicoItemPedidoPayload(data);
const payload = TServicoPedidoItemPreparePayload(data);
if (payload.status) {
@ -42,14 +44,23 @@ export function useTServicoItemPedidoAddHook<TFormValues extends FieldValues>(se
}
// Obtem o resultado da busca
const item = response;
// Verifica se tem status de erro
if (response.status) {
return {
'status': response.status,
'message': 'Erro ao processar dados'
};
}
// Atualiza o estado com fallback seguro
setTServicoItemPedido((prev) => {
const safePrev = Array.isArray(prev) ? prev : [];
const novoArray = [...safePrev, item];
const novoArray = [...safePrev, response];
if (setValue) {
@ -62,7 +73,7 @@ export function useTServicoItemPedidoAddHook<TFormValues extends FieldValues>(se
});
return item;
return response;
};

View file

@ -2,7 +2,7 @@
import { useState } from 'react';
import TServicoItemPedidoIndexResponseInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddResponseInterface';
import TServicoItemPedidoIndexResponseInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface';
import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce';
import { TServicoItemPedidoIndexService } from '@/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoIndexService';
import { useResponse } from '@/shared/components/response/ResponseContext';

View file

@ -3,7 +3,7 @@
import { useState } from 'react';
import { FieldValues, UseFormSetValue } from 'react-hook-form';
import { default as TServicoItemPedidoAddResponseInterface, default as TServicoItemPedidoIndexResponseInterface } from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddResponseInterface';
import { default as TServicoItemPedidoAddResponseInterface, default as TServicoItemPedidoIndexResponseInterface } from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface';
export function useTServicoItemPedidoLocalAddHook<TFormValues extends FieldValues>(setValue?: UseFormSetValue<TFormValues>) {

View file

@ -1,4 +1,8 @@
import { UseFormReturn } from "react-hook-form";
import { TServicoPedidoFormValues } from "@/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema";
export default interface TPessoaCartaoFormInterface {
index: number;
form: any;
form: UseFormReturn<TServicoPedidoFormValues>;
}

View file

@ -1,4 +1,4 @@
export default interface TServicoInterface {
servico_pedido_id: number;
escrevente_id: number;
}
}

View file

@ -2,6 +2,6 @@ import TServicoTipoInterface from "@/app/(protected)/(cadastros)/cadastros/_inte
import TPessoaInterface from "@/packages/administrativo/interfaces/TPessoa/TPessoaInterface";
export default interface TServicoItemPedidoSubviewInterface {
servico: TServicoTipoInterface,
pessoa: TPessoaInterface
}
servico: TServicoTipoInterface;
pessoa: TPessoaInterface;
}

View file

@ -1,7 +1,28 @@
import TServicoTipoInterface from "@/app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface";
import GEmolumentoInterface from "@/packages/administrativo/interfaces/GEmolumento/GEmolumentoInterface";
import TPessoaInterface from "@/packages/administrativo/interfaces/TPessoa/TPessoaInterface";
export default interface TServicoItemPedidoAddInterface {
/**
* Índice local na lista de itens (usado no front)
*/
index?: number;
qtd?: number;
valor_documento?: number;
/**
* Emolumento selecionado
*/
emolumento: GEmolumentoInterface;
/**
* Serviço/tipo de serviço selecionado
*/
servico_tipo: TServicoTipoInterface;
}
/**
* Pessoa vinculada ao item (quando aplicável)
*/
pessoa?: TPessoaInterface;
}

View file

@ -1,20 +1,29 @@
import TServicoItemPedidoSubviewInterface from "../TServico/TServicoItemPedidoSubviewInterface";
export default interface TServicoItemPedidoAddResponseInterface {
export default interface TServicoItemPedidoCalculoResponseInterface {
index?: number;
emolumento_id: number;
emolumento_item_id: number;
servico_tipo_id: number;
tipo_item: string;
descricao: string;
tabela: string;
situacao: string;
qtd: number;
valor: number;
emolumento: number;
fundesp: number;
taxa_judiciaria: number;
valor_iss: number;
pessoa_id?: number;
/**
* Subview com serviço + pessoa (usado na linha expandida)
*/
subview?: TServicoItemPedidoSubviewInterface;
}

View file

@ -1,10 +1,13 @@
import TServicoItemPedidoAddResponseInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddResponseInterface";
import { TServicoPedidoFormInterface } from "@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoFormInterface";
import { UseFormReturn } from "react-hook-form";
import TServicoItemPedidoAddResponseInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface";
import GConfigInterface from "@/shared/interfaces/GConfigInterface";
import { TServicoPedidoFormValues } from "../../schemas/TServicoPedido/TServicoPedidoFormSchema";
export default interface TServicoItemPedidoFormTableInterface {
data: TServicoItemPedidoAddResponseInterface;
form: TServicoPedidoFormInterface;
params: GConfigInterface;
data: TServicoItemPedidoAddResponseInterface[];
form: UseFormReturn<TServicoPedidoFormValues>;
params: GConfigInterface[];
}

View file

@ -1,67 +1,91 @@
import TServicoItemPedidoSubviewInterface from "../TServico/TServicoItemPedidoSubviewInterface";
export default interface TServicoItemPedidoInterface {
servico_itempedido_id?: number
servico_pedido_id?: number
servico_tipo_id?: number
valor?: number
qtd?: number
pessoa_id?: number
impressao_etiqueta?: string
situacao?: string
etiqueta_numero?: number
pessoa_auxiliar_id?: number
pessoa_sp_abono_rep?: string
tipo_item?: string
imprimir?: string
observacao?: string
impressao_direta?: string
selo_livro_id?: number
emolumento?: number
fundesp?: number
taxa_judiciaria?: number
desconto?: number
desc_complementar?: string
valor_manual?: string
valor_documento?: number
outra_taxa1?: number
emolumento_item_id?: number
certidao_impressa?: string
certidao_ato_id?: number
emolumento_id?: number
certidao_previsao?: string | Date
certidao_ato_antigo?: string
certidao_data_emissao?: string | Date
certidao_texto?: string | null
ato_antigo_tipo?: string
valor_iss?: number
id_ato_isentado?: number
motivo_isencao?: string
pessoas_etiquetas?: number
abonador?: string
servico_cartao?: string
valor_informacoes_centrais?: number
situacao_diferido?: string
sigla_numero?: string
motivo_diferido?: string
nome_juridico?: string
etiqueta_apenas_frente?: string
indexacao_id?: number
certidao_data_lavratura?: string | Date
nfse_id?: number
qtd_pagina_certidao?: number
placa?: string
dut?: string
etiqueta_unica?: string
fundo_abonador?: string
instrumento_publico?: string
data_lavratura_abono?: string | Date
valor_base_calculo?: number
valor_avaliacao?: number
ato_abonado?: number
transferencia_veiculo?: string
usar_a4?: string
cpf_abono_rep?: string
vrcext?: number
valor_fundo_selo?: number
averbacao?: string
descricao?: string
servico_itempedido_id?: number;
servico_pedido_id?: number;
servico_tipo_id?: number;
valor?: number;
qtd?: number;
pessoa_id?: number;
impressao_etiqueta?: string;
situacao?: string;
etiqueta_numero?: number;
pessoa_auxiliar_id?: number;
pessoa_sp_abono_rep?: string;
tipo_item?: string;
imprimir?: string;
observacao?: string;
impressao_direta?: string;
// 🔹 Valores financeiros e emolumentos
selo_livro_id?: number;
emolumento?: number;
fundesp?: number;
taxa_judiciaria?: number;
desconto?: number;
desc_complementar?: string;
valor_manual?: string;
valor_documento?: number;
outra_taxa1?: number;
emolumento_item_id?: number;
emolumento_id?: number;
valor_iss?: number;
valor_informacoes_centrais?: number;
id_ato_isentado?: number;
motivo_isencao?: string;
valor_base_calculo?: number;
valor_avaliacao?: number;
vrcext?: number;
valor_fundo_selo?: number;
// 🔹 Certidão
certidao_impressa?: string;
certidao_ato_id?: number;
certidao_previsao?: string | Date;
certidao_ato_antigo?: string;
certidao_data_emissao?: string | Date;
certidao_texto?: string | null;
ato_antigo_tipo?: string;
pessoas_etiquetas?: number;
qtd_pagina_certidao?: number;
// 🔹 Situações / Diferimento / Notas
situacao_diferido?: string;
motivo_diferido?: string;
averbacao?: string;
// 🔹 Dados auxiliares
abonador?: string;
servico_cartao?: string;
nome_juridico?: string;
etiqueta_apenas_frente?: string;
indexacao_id?: number;
certidao_data_lavratura?: string | Date;
nfse_id?: number;
placa?: string;
dut?: string;
etiqueta_unica?: string;
fundo_abonador?: string;
instrumento_publico?: string;
data_lavratura_abono?: string | Date;
ato_abonado?: number;
transferencia_veiculo?: string;
usar_a4?: string;
cpf_abono_rep?: string;
// 🔹 Campos usados na UI
descricao?: string;
tabela?: string;
/**
* Índice local na lista (usado no front para map e controle)
*/
index?: number;
/**
* Subview: serviço + pessoa vinculada ao item
*/
subview?: TServicoItemPedidoSubviewInterface;
}

View file

@ -1,4 +1,4 @@
import TServicoItemPedidoIndexResponseInterface from "./TServicoItemPedidoAddResponseInterface";
import TServicoItemPedidoIndexResponseInterface from "./TServicoItemPedidoCalculoResponseInterface";
export default interface TServicoItemPedidoListInterface {
items: TServicoItemPedidoIndexResponseInterface[];

View file

@ -1,4 +1,4 @@
import TServicoItemPedidoIndexResponseInterface from "../TServicoItemPedido/TServicoItemPedidoAddResponseInterface";
import TServicoItemPedidoIndexResponseInterface from "../TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface";
export default interface TServicoPedidoDetailsPagamentoInterface {

View file

@ -1,4 +1,7 @@
export interface TServicoPedidoFormInterface {
servico_pedido_id?: number
}
/**
* ID opcional do pedido, usado para modo edição
* - Se não informado, o formulário funciona em modo "novo pedido"
*/
servico_pedido_id?: number;
}

View file

@ -1,8 +1,22 @@
import TServicoTipoInterface from "@/app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface";
import GEmolumentoInterface from "@/packages/administrativo/interfaces/GEmolumento/GEmolumentoInterface";
import TServicoItemPedidoAddResponseInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface";
export default interface TServicoPedidoInterface {
/**
* Chave primária do pedido
*/
servico_pedido_id?: number;
/**
* Valores financeiros do pedido
*/
valor_pedido?: number;
valor_pago?: number;
/**
* Dados de controle
*/
usuario_id?: number;
data_pedido?: string;
mensalista_livrocaixa_id?: number;
@ -11,16 +25,38 @@ export default interface TServicoPedidoInterface {
situacao?: string;
estornado?: string;
nfse_id?: number;
/**
* Apresentante / Pessoa selo
*/
apresentante?: string;
cpfcnpj_apresentante?: string;
selo_pessoa_nome?: string;
selo_pessoa_cpfcnpj?: string;
/**
* Meta-informações de usuário/funcão (quando retornado pela API)
*/
login?: string;
funcao?: string;
itens?: [];
servico_tipo: object;
emolumento: object;
pagador_nome?: string,
pagador_cpfcnpj?: string,
tipo_pagamento?: number,
}
/**
* Serviço e emolumento selecionados no front.
* - No backend, provavelmente IDs são gravados,
* mas no front trabalhamos com o objeto completo.
*/
servico_tipo: TServicoTipoInterface;
emolumento: GEmolumentoInterface;
/**
* Itens do pedido (array tipado, e não mais [])
*/
itens?: TServicoItemPedidoAddResponseInterface[];
/**
* Dados de pagamento
*/
pagador_nome?: string;
pagador_cpfcnpj?: string;
tipo_pagamento?: number;
}

View file

@ -1,6 +1,11 @@
import z from "zod";
export const TServicoPedidoFormSchema = z.object({
servico_pedido_id: z
.number()
.optional(),
escrevente_id: z
.number()
.int()

View file

@ -34,7 +34,6 @@ import {
} from '@/components/ui/table';
import DataTableInterface from './interfaces/DataTableInterface';
import DataTableSubview from './interfaces/DataTableSubview';
/**
* DataTable genérico com suporte a subvisões dinâmicas (subtabelas ou detalhes).
@ -180,42 +179,22 @@ export function DataTable<TData extends { subview?: React.ReactNode | (() => Rea
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => {
const subview =
typeof row.original.subview === 'function'
? row.original.subview()
: row.original.subview;
return (
<React.Fragment key={row.id}>
{/* Linha principal */}
<TableRow
className={
onRowClick ? 'hover:bg-muted/50 cursor-pointer' : ''
}
onClick={() => onRowClick?.(row.original)}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
{/* Subview dinâmica (qualquer conteúdo) */}
{subview && (
<TableRow className="bg-muted/10">
<TableCell
colSpan={row.getVisibleCells().length}
className="p-0"
>
<DataTableSubview subview={subview} />
</TableCell>
</TableRow>
)}
</React.Fragment>
<TableRow
className={
onRowClick ? 'hover:bg-muted/50 cursor-pointer' : ''
}
onClick={() => onRowClick?.(row.original)}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext(),
)}
</TableCell>
))}
</TableRow>
);
})
) : (

View file

@ -1,11 +0,0 @@
'use client';
export default function DataTableSubview({ subview }) {
if (!subview) return null;
if (!subview.component) return null;
const Component = subview.component;
const props = subview.props || {};
return <Component {...props} />;
}