363 lines
No EOL
13 KiB
TypeScript
363 lines
No EOL
13 KiB
TypeScript
'use client';
|
|
|
|
import { useRouter } from 'next/navigation';
|
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
|
import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface';
|
|
import { useTServicoItemPedidoCalculoHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCalculoHook';
|
|
import { useTServicoItemPedidoIndexHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook';
|
|
import { useTServicoItemPedidoLocalHandleHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoLocalHandleHook';
|
|
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 TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface';
|
|
import { TServicoPedidoFormValues } from '@/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema';
|
|
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) {
|
|
|
|
const router = useRouter();
|
|
const form = useTServicoPedidoFormHook({});
|
|
const { setValue, reset, watch } = form;
|
|
|
|
const [isSaving, setIsSaving] = useState(false);
|
|
const [isAdding, setIsAdding] = useState(false);
|
|
const [isPessoaFormOpen, setIsPessoaFormOpen] = useState(false);
|
|
const [isSaveConfirmOpen, setIsSaveConfirmOpen] = useState(false);
|
|
const [isCancelDialogOpen, setIsCancelDialogOpen] = useState(false);
|
|
const [selectedPessoaTipo, setSelectedPessoaTipo] = useState('');
|
|
const [shouldKeepFormOpen, setShouldKeepFormOpen] = useState(false);
|
|
|
|
const ref = useRef<StepNavigatorRef>(null);
|
|
|
|
// Controles de formulário
|
|
const handleClosePessoaForm = useCallback(() => setIsPessoaFormOpen(false), []);
|
|
const handleOpenSaveConfirm = useCallback(() => setIsSaveConfirmOpen(true), []);
|
|
const handleCloseSaveConfirm = useCallback(() => setIsSaveConfirmOpen(false), []);
|
|
|
|
// Hooks
|
|
// const playSuccess = useSoundHook("/sounds/success.mp3");
|
|
const { setResponse } = useResponse();
|
|
const { saveTServicoPedido } = useTServicoPedidoSaveHook();
|
|
const { showTServicoPedido } = useTServicoPedidoShowHook();
|
|
const { TServicoItemPedidoLocal, localAddTServicoItemPedido, localRemoveTServicoItemPedido, setLocalTServicoItemPedido } = useTServicoItemPedidoLocalHandleHook(setValue);
|
|
const { calculoTServicoItemPedido } = useTServicoItemPedidoCalculoHook(setValue);
|
|
const { indexTServicoItemPedido } = useTServicoItemPedidoIndexHook();
|
|
const { TServicoPedidoParams, loadParamsTServicoPedido } = useTServicoPedidoLoadParamsHook();
|
|
|
|
// Acompanha as alterações, nos campos definidos
|
|
const selectedServicoTipo = watch('servico_tipo');
|
|
const selectedEmolumento = watch('emolumento');
|
|
|
|
const handleFormError = useCallback((errors: any) => {
|
|
console.group('Erros de validação do formulário');
|
|
console.log('Campos com erro:', errors);
|
|
console.groupEnd();
|
|
}, []);
|
|
|
|
// Envia a requisição para a API
|
|
const handleSavePedido = useCallback(
|
|
async (data: TServicoPedidoFormValues) => {
|
|
// Ativa o botão de loading
|
|
setIsSaving(true);
|
|
|
|
// Converte o tipo do formulário (Zod) para o tipo da API (Interface)
|
|
const payload: TServicoPedidoInterface = {
|
|
...data,
|
|
situacao: data.situacao as unknown as SituacoesEnum,
|
|
};
|
|
|
|
const response = await saveTServicoPedido(payload);
|
|
|
|
// Desativa o botão de loading
|
|
setIsSaving(false);
|
|
|
|
// Verifica se devo redirecionar a pagina
|
|
if (response?.servico_pedido_id > 0) {
|
|
// Toca o som do sistema
|
|
// playSuccess()
|
|
}
|
|
|
|
// Verifica se devo redirecionar a pagina
|
|
if (response?.servico_pedido_id > 0 && !shouldKeepFormOpen) {
|
|
router.replace(`/servicos/balcao/detalhes/${response.servico_pedido_id}`);
|
|
}
|
|
},
|
|
[saveTServicoPedido, shouldKeepFormOpen],
|
|
);
|
|
|
|
// Modal de confirmação de serviço
|
|
const handleSubmitWithConfirmation = useCallback(() => {
|
|
// Envia o formulário
|
|
form.handleSubmit(handleSavePedido, handleFormError)();
|
|
}, [form, handleSavePedido, handleFormError]);
|
|
|
|
// Busca os itens do Pedido
|
|
const fetchPedidoItens = useCallback(
|
|
async (id: number) => {
|
|
const pedidoItens = {
|
|
servico_pedido_id: id,
|
|
};
|
|
|
|
// Busca os itens do pedido
|
|
const response = await indexTServicoItemPedido(pedidoItens);
|
|
|
|
// Verifica se os dados foram localizados
|
|
if (response?.data?.length) {
|
|
// Atualiza os dados dos itens locais
|
|
setLocalTServicoItemPedido(response.data);
|
|
|
|
// Atualiza os itens do formulário
|
|
setValue('itens', response.data);
|
|
}
|
|
},
|
|
[indexTServicoItemPedido, setValue, setLocalTServicoItemPedido],
|
|
);
|
|
|
|
// Busca o pedido Principal
|
|
const fetchPedido = useCallback(async () => {
|
|
// Busca o pedido principal
|
|
const response = await showTServicoPedido({ servico_pedido_id });
|
|
|
|
// Verifica se o pedido foi localizado
|
|
if (response?.servico_pedido_id) {
|
|
// Atualiza os dados do formulário
|
|
reset(response);
|
|
|
|
// Carrega os itens do pedido
|
|
fetchPedidoItens(response.servico_pedido_id);
|
|
}
|
|
}, [servico_pedido_id, showTServicoPedido, reset, fetchPedidoItens]);
|
|
|
|
const handleAddItemWithPessoa = useCallback(
|
|
async (selectedTPessoa: TPessoaInterface) => {
|
|
handleAddItem(selectedTPessoa)
|
|
}, [selectedEmolumento, selectedServicoTipo]);
|
|
|
|
// Controla o formulário de cancelamento de pedido
|
|
const handleOpenCancelDialog = useCallback(async () => {
|
|
// Fecha a confirmação
|
|
setIsCancelDialogOpen(true);
|
|
}, []);
|
|
|
|
// Controle de redirecionamento
|
|
const handleConfirmCancel = useCallback(async () => {
|
|
// Redireciona o usuário
|
|
router.replace(`/servicos/balcao/`);
|
|
}, []);
|
|
|
|
// Controle do formulário de cancelamento do Pedido
|
|
const handleCloseCancelDialog = useCallback(async () => {
|
|
// Fecha o formulário
|
|
setIsCancelDialogOpen(false);
|
|
}, []);
|
|
|
|
const handleRemoveLocalItem = useCallback(async (index: number) => {
|
|
|
|
localRemoveTServicoItemPedido(index)
|
|
|
|
}, []);
|
|
|
|
// Controle de itens
|
|
const handleAddItem = useCallback(async (selectedTPessoa?: TPessoaInterface) => {
|
|
|
|
setIsAdding(true);
|
|
|
|
// Prepara e valida os dados de item do pedido
|
|
const payload = {
|
|
servico_tipo: selectedServicoTipo,
|
|
emolumento: selectedEmolumento,
|
|
};
|
|
|
|
// Se existir pessoa, adiciona ao payload
|
|
if (selectedTPessoa) {
|
|
payload.pessoa = selectedTPessoa;
|
|
}
|
|
|
|
// Obtem o resultado da adição do item
|
|
const item = await calculoTServicoItemPedido(payload);
|
|
|
|
// Verifica se foi realizado o calculo
|
|
if (!item) {
|
|
setResponse({
|
|
status: 422,
|
|
detail: 'Não foi localizado item para o serviço',
|
|
})
|
|
setIsAdding(false);
|
|
return;
|
|
}
|
|
|
|
// Define índice e adiciona localmente
|
|
const index = TServicoItemPedidoLocal.length;
|
|
|
|
// Guarda o indice
|
|
item.index = index
|
|
|
|
// Adiciona o item calculo localmente
|
|
localAddTServicoItemPedido(item)
|
|
|
|
// Define os itens
|
|
form.setValue(`itens.${index}`, item);
|
|
|
|
setIsAdding(false);
|
|
|
|
}, [calculoTServicoItemPedido, selectedServicoTipo, selectedEmolumento, localAddTServicoItemPedido]);
|
|
|
|
// Habilita o formulário de pessoas
|
|
const handleOpenPessoaForm = useCallback((tipoPessoa: string) => {
|
|
setSelectedPessoaTipo(tipoPessoa);
|
|
setIsPessoaFormOpen(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({
|
|
status: 422,
|
|
detail: 'Serviço e emolumento devem ser selecionados',
|
|
})
|
|
return;
|
|
}
|
|
|
|
// Verifica se deve selecionar pessoas
|
|
switch (tipoPessoa.includes(selectedServicoTipo.tipo_pessoa)) {
|
|
|
|
// Habilita o formulário
|
|
case true:
|
|
|
|
handleOpenPessoaForm(selectedServicoTipo.tipo_pessoa);
|
|
break;
|
|
|
|
// Adiciona direto
|
|
default:
|
|
|
|
handleAddItem();
|
|
break;
|
|
|
|
}
|
|
|
|
}, [selectedServicoTipo, selectedEmolumento, handleOpenPessoaForm, handleAddItem]);
|
|
|
|
const calcularTotais = useCallback(() => {
|
|
const itens = form.getValues('itens') || [];
|
|
|
|
if (!itens.length) {
|
|
setValue('valor_pedido', 0, { shouldDirty: true });
|
|
setValue('valor_pago', 0, { shouldDirty: true });
|
|
return;
|
|
}
|
|
|
|
const total = itens.reduce((acc, item) => acc + Number(item.valor ?? 0), 0);
|
|
|
|
// Atualiza sempre o valor do pedido
|
|
setValue('valor_pedido', total, { shouldDirty: true });
|
|
|
|
// Atualiza o valor pago apenas se estiver vazio, null, undefined ou 0
|
|
const valorPagoAtual = Number(form.getValues('valor_pago')) || 0;
|
|
if (!valorPagoAtual) {
|
|
setValue('valor_pago', total, { shouldDirty: true });
|
|
}
|
|
}, [form, setValue]);
|
|
|
|
// Incremente ou decrementa a quantidade
|
|
const handleChangeQtd = useCallback(
|
|
(index: number, delta: number) => {
|
|
const currentItens = form.getValues('itens') || [];
|
|
const currentItem = currentItens[index];
|
|
if (!currentItem) return;
|
|
|
|
const currentQtd = Number(currentItem.qtd ?? 1);
|
|
const newQtd = currentQtd + delta;
|
|
|
|
// Se quantidade for 0 ou menor, remove o item
|
|
if (newQtd <= 0) {
|
|
const filteredItens = currentItens.filter((_, i) => i !== index);
|
|
form.setValue('itens', filteredItens, { shouldDirty: true });
|
|
localRemoveTServicoItemPedido(index);
|
|
calcularTotais();
|
|
return;
|
|
}
|
|
|
|
const multiplier = newQtd / currentQtd;
|
|
|
|
const updatedItem = {
|
|
...currentItem,
|
|
qtd: newQtd,
|
|
emolumento: (Number(currentItem.emolumento) * multiplier).toFixed(2),
|
|
taxa_judiciaria: (Number(currentItem.taxa_judiciaria) * multiplier).toFixed(2),
|
|
fundesp: (Number(currentItem.fundesp) * multiplier).toFixed(2),
|
|
valor_iss: (Number(currentItem.valor_iss) * multiplier).toFixed(2),
|
|
valor: (Number(currentItem.valor) * multiplier).toFixed(2),
|
|
};
|
|
|
|
const updatedItens = [...currentItens];
|
|
updatedItens[index] = updatedItem;
|
|
|
|
form.setValue('itens', updatedItens, { shouldDirty: true });
|
|
calcularTotais();
|
|
},
|
|
[form, localRemoveTServicoItemPedido, calcularTotais],
|
|
);
|
|
|
|
// Dispara a busca do pedido
|
|
useEffect(() => {
|
|
// Se existir pedido_id, busca o pedido
|
|
if (servico_pedido_id) fetchPedido();
|
|
}, [servico_pedido_id, fetchPedido]);
|
|
|
|
// Dispara a busca de itens
|
|
useEffect(() => {
|
|
// Dispara a busca dos itens
|
|
setValue('itens', TServicoItemPedidoLocal, { shouldDirty: true });
|
|
}, [TServicoItemPedidoLocal, setValue]);
|
|
|
|
// Dispara a busca de parâmetros
|
|
useEffect(() => {
|
|
loadParamsTServicoPedido();
|
|
}, []);
|
|
|
|
// Monitora mudanças na lista de itens
|
|
useEffect(() => {
|
|
calcularTotais();
|
|
}, [TServicoItemPedidoLocal, calcularTotais]);
|
|
|
|
return {
|
|
form,
|
|
ref,
|
|
isSaving,
|
|
isAdding,
|
|
isPessoaFormOpen,
|
|
isSaveConfirmOpen,
|
|
isCancelDialogOpen,
|
|
shouldKeepFormOpen,
|
|
selectedPessoaTipo,
|
|
TServicoItemPedidoLocal,
|
|
TServicoPedidoParams,
|
|
|
|
// setters diretos
|
|
setIsSaveConfirmOpen,
|
|
setIsCancelDialogOpen,
|
|
setShouldKeepFormOpen,
|
|
|
|
// handlers principais
|
|
handleSavePedido,
|
|
handleSelectServicoTipo,
|
|
handleSubmitWithConfirmation,
|
|
handleCloseSaveConfirm,
|
|
handleOpenCancelDialog,
|
|
handleConfirmCancel,
|
|
handleCloseCancelDialog,
|
|
handleClosePessoaForm,
|
|
handleAddItemWithPessoa,
|
|
handleOpenSaveConfirm,
|
|
handleChangeQtd
|
|
};
|
|
} |