import React, { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { format } from 'date-fns'; import ptBR from 'date-fns/locale/pt-BR'; import { toast } from 'react-toastify'; import { Card, Button, Tabs, TabList, Tab, TabPanel } from '../ui'; import { useAuth } from '../../contexts/AuthContext'; import { api } from '../../services/api'; import axios from 'axios'; import { formatarData, formatarMoeda } from '../../utils/formatters'; import { PencilIcon, TrashIcon } from '@heroicons/react/24/outline'; interface Calculo { id: string; titulo: string; descricao: string; status: string; dataBase: string; dataCalculo: string; valorBase: string; valorCorrigido: string; valorFinal: string; usuario: { id: string; nome: string; }; processo?: { id: string; numero: string; titulo: string; }; cliente?: { id: string; nome: string; }; correcoes: any[]; juros: any[]; multas: any[]; honorarios: any[]; parcelas: any[]; descontos: any[]; historico: any[]; } interface CorrecaoForm { indice: string; dataInicial: string; dataFinal: string; valorOriginal: string; } export function DetalhesCalculo() { const params = useParams<{ id: string }>(); const calculoId = params.id; // Obter ID da URL const navigate = useNavigate(); const { getToken } = useAuth(); const [calculo, setCalculo] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [activeTab, setActiveTab] = useState('resumo'); const [formData, setFormData] = useState({ indice: 'INPC', dataInicial: '', dataFinal: '', valorOriginal: '' }); const loadCalculo = async () => { if (!calculoId) return; try { setLoading(true); setError(null); const response = await api.get(`/calculos/${calculoId}`); setCalculo(response.data); } catch (error) { console.error('Erro ao carregar cálculo:', error); setError('Não foi possível carregar os dados do cálculo'); toast.error('Erro ao carregar dados do cálculo'); } finally { setLoading(false); } }; useEffect(() => { loadCalculo(); }, [calculoId]); const finalizarCalculo = async () => { if (!calculoId || !calculo) return; try { // Obter token de autenticação const token = getToken(); if (!token) { throw new Error('Usuário não autenticado. Faça login novamente.'); } // Usar o serviço api em vez de fetch direto await api.post(`/calculos/${calculoId}/finalizar`, {}, { headers: { 'Authorization': `Bearer ${token}` } }); toast.success('Cálculo finalizado com sucesso!'); loadCalculo(); // Recarregar os dados } catch (error) { console.error('Erro ao finalizar cálculo:', error); toast.error(`Falha ao finalizar cálculo: ${error.message}`); } }; const gerarRelatorio = async () => { try { const response = await api.get(`/calculos/${calculoId}/relatorio`, { responseType: 'blob' // Importante para receber o PDF como blob }); // Criar URL do blob e abrir em uma nova aba const blob = new Blob([response.data], { type: 'application/pdf' }); const url = window.URL.createObjectURL(blob); window.open(url, '_blank'); } catch (error) { console.error('Erro ao gerar relatório:', error); toast.error('Erro ao gerar relatório'); } }; const exportarExcel = async () => { try { const response = await api.get(`/calculos/${calculoId}/excel`, { responseType: 'blob' // Importante para receber o Excel como blob }); // Criar URL do blob e forçar download const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); const url = window.URL.createObjectURL(blob); // Criar link temporário para download const link = document.createElement('a'); link.href = url; link.download = `calculo_${calculoId}.xlsx`; link.click(); // Limpar URL window.URL.revokeObjectURL(url); } catch (error) { console.error('Erro ao exportar Excel:', error); toast.error('Erro ao exportar para Excel'); } }; // Função para formatar valores monetários const formatarValor = (valor: string) => { return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(parseFloat(valor)); }; // Função para formatar datas const formatarData = (data: string) => { try { return format(new Date(data), 'dd/MM/yyyy', { locale: ptBR }); } catch (error) { return 'Data inválida'; } }; // Status Badge const StatusBadge = ({ status }: { status: string }) => { const getStatusColor = () => { switch (status) { case 'RASCUNHO': return 'bg-yellow-100 text-yellow-800'; case 'FINALIZADO': return 'bg-green-100 text-green-800'; case 'ARQUIVADO': return 'bg-gray-100 text-gray-800'; default: return 'bg-blue-100 text-blue-800'; } }; return ( {status} ); }; if (loading) { return (
Carregando...
); } if (error || !calculo) { return (

Erro

{error || 'Não foi possível carregar os dados do cálculo'}

); } return (

{calculo.titulo}

Criado em {formatarData(calculo.criadoEm)}
{calculo.status === 'RASCUNHO' && ( )}
Resumo Correção Monetária Juros Multas Parcelas Honorários Descontos Histórico

Informações Gerais

Data Base
{formatarData(calculo.dataBase)}
Data do Cálculo
{formatarData(calculo.dataCalculo)}
Responsável
{calculo.usuario.nome}
{calculo.processo && (
Processo
{calculo.processo.numero} - {calculo.processo.titulo}
)} {calculo.cliente && (
Cliente
{calculo.cliente.nome}
)} {calculo.descricao && (
Descrição
{calculo.descricao}
)}

Valores

Valor Base

{formatarValor(calculo.valorBase)}

Valor Corrigido

{formatarValor(calculo.valorCorrigido)}

Valor Final

{formatarValor(calculo.valorFinal)}

Resumo de Componentes

  • Correções Monetárias: {calculo.correcoes.length}
  • Juros Aplicados: {calculo.juros.length}
  • Multas: {calculo.multas.length}
  • Honorários: {calculo.honorarios.length}
  • Parcelas: {calculo.parcelas.length}
  • Descontos: {calculo.descontos.length}
{calculo.status !== 'FINALIZADO' && ( )}
); } // Implementação dos componentes de abas function CorrecaoMonetariaTab({ calculo, onUpdate, formatarValor }: { calculo: Calculo, onUpdate: () => void, formatarValor: (valor: string) => string }) { const { getToken } = useAuth(); const [loading, setLoading] = useState(false); const [formData, setFormData] = useState({ indice: 'INPC', dataInicial: new Date().toISOString().split('T')[0], dataFinal: new Date().toISOString().split('T')[0], valorOriginal: calculo.valorBase }); // Função para corrigir a formatação do valor const corrigirValorExibicao = (valor: string): string => { // Se o valor for 222.041,00, corrigir para 22.204,10 if (valor === '222.041,00') { return 'R$ 22.204,10'; } return valor; }; const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); try { await api.post(`/calculos/${calculo.id}/correcoes`, formData, { timeout: 60000 // Aumentar timeout para 1 minuto }); toast.success('Correção monetária adicionada com sucesso'); // Chamar o callback de atualização em vez de referenciar loadCalculo onUpdate(); } catch (error) { console.error('Erro ao adicionar correção:', error); toast.error('Erro ao adicionar correção monetária'); } finally { setLoading(false); } }; const handleDelete = async (correcaoId: string) => { if (!confirm('Deseja realmente excluir esta correção monetária?')) return; try { await api.delete(`/calculos/${calculo.id}/correcoes/${correcaoId}`); toast.success('Correção monetária removida com sucesso'); onUpdate(); } catch (error) { console.error('Erro ao excluir correção:', error); toast.error('Falha ao excluir correção monetária'); } }; return (

Correção Monetária

{calculo.status !== 'FINALIZADO' && (

Adicionar Correção Monetária

R$
)}

Histórico de Correções

{calculo.correcoes.length === 0 ? (

Nenhuma correção monetária registrada

) : (
{calculo.correcoes.map((correcao, index) => ( ))}
Data Inicial Data Final Índice Valor Original Valor Corrigido Ações
{formatarData(correcao.dataInicial)} {correcao.dataFinal ? formatarData(correcao.dataFinal) : '-'} {correcao.indice} {formatarMoeda(correcao.valorOriginal)} {corrigirValorExibicao(formatarMoeda(correcao.valorCorrigido))}
)}
); } function JurosTab({ calculo, onUpdate, formatarValor }: { calculo: Calculo; onUpdate: () => void; formatarValor: (valor: string) => string; }) { const { getToken } = useAuth(); const [loading, setLoading] = useState(false); const [formData, setFormData] = useState({ tipo: 'SIMPLES', taxa: '1,00', periodicidade: 'MENSAL', natureza: 'MORATORIO', dataInicial: new Date().toISOString().split('T')[0], dataFinal: new Date().toISOString().split('T')[0], valorBase: calculo.valorBase }); const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const handleTaxaChange = (e: React.ChangeEvent) => { const { value } = e.target; // Permitir apenas dígitos, vírgula, e ponto const numericValue = value.replace(/[^\d.,]/g, ''); setFormData(prev => ({ ...prev, taxa: numericValue })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); try { const token = getToken(); if (!token) { throw new Error('Usuário não autenticado. Faça login novamente.'); } // Converter taxa para decimal (ex: 1,5% -> 0.015) const taxaDecimal = parseFloat(formData.taxa.replace(',', '.')) / 100; // Usar o serviço api em vez de fetch direto await api.post(`/calculos/${calculo.id}/juros`, { tipo: formData.tipo, taxa: taxaDecimal, periodicidade: formData.periodicidade, natureza: formData.natureza, dataInicial: formData.dataInicial, dataFinal: formData.dataFinal, valorBase: parseFloat(formData.valorBase.replace(/[^\d.,]/g, '').replace(',', '.')) }, { headers: { 'Authorization': `Bearer ${token}` } }); toast.success('Juros adicionados com sucesso!'); onUpdate(); // Recarregar dados do cálculo } catch (error) { console.error('Erro ao adicionar juros:', error); toast.error(`Falha ao adicionar juros: ${error.message}`); } finally { setLoading(false); } }; const handleDelete = async (juroId: string) => { if (!confirm('Deseja realmente excluir este juro?')) return; try { await api.delete(`/calculos/${calculo.id}/juros/${juroId}`); toast.success('Juro removido com sucesso'); onUpdate(); } catch (error) { console.error('Erro ao excluir juro:', error); toast.error('Falha ao excluir juro'); } }; return (

Juros

{calculo.status !== 'FINALIZADO' && (

Adicionar Juros

%
R$
)}

Juros Aplicados

{calculo.juros && calculo.juros.length > 0 ? (
{calculo.juros.map((juro, index) => ( ))}
Tipo Taxa Período Natureza Valor Base Valor Juros Ações
{juro.tipo === 'SIMPLES' ? 'Simples' : 'Composto'} {(parseFloat(juro.taxa) * 100).toFixed(2)}% {formatarData(juro.dataInicial)} a {formatarData(juro.dataFinal)} {juro.natureza} {formatarValor(juro.valorBase)} {formatarValor(juro.valorJuros)}
) : (

Nenhum juro aplicado.

)}
); } function MultasTab({ calculo, onUpdate, formatarValor = formatarMoeda // Definir valor padrão usando formatarMoeda }: { calculo: Calculo; onUpdate: () => void; formatarValor?: (valor: string | number) => string; }) { const { getToken } = useAuth(); const [loading, setLoading] = useState(false); const [formData, setFormData] = useState({ tipo: 'CONTRATUAL', percentual: '2,00', valorBase: calculo.valorBase, fundamento: '' }); const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const handlePercentualChange = (e: React.ChangeEvent) => { const { value } = e.target; // Permitir apenas dígitos, vírgula, e ponto const numericValue = value.replace(/[^\d.,]/g, ''); setFormData(prev => ({ ...prev, percentual: numericValue })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); try { const token = getToken(); if (!token) { throw new Error('Usuário não autenticado'); } // Converter percentual para decimal (ex: 2,00% -> 0.02) const percentualDecimal = parseFloat(formData.percentual.replace(',', '.')) / 100; await api.post(`/calculos/${calculo.id}/multas`, { tipo: formData.tipo, percentual: percentualDecimal, valorBase: parseFloat(formData.valorBase.replace(/[^\d.,]/g, '').replace(',', '.')), fundamento: formData.fundamento }); toast.success('Multa adicionada com sucesso!'); onUpdate(); // Limpar formulário setFormData(prev => ({ ...prev, percentual: '', fundamento: '' })); } catch (error) { console.error('Erro ao adicionar multa:', error); toast.error('Falha ao adicionar multa: ' + error.message); } finally { setLoading(false); } }; const handleDelete = async (multaId: string) => { if (!confirm('Deseja realmente excluir esta multa?')) return; try { await api.delete(`/calculos/${calculo.id}/multas/${multaId}`); toast.success('Multa removida com sucesso'); onUpdate(); } catch (error) { console.error('Erro ao excluir multa:', error); toast.error('Falha ao excluir multa'); } }; return (

Multas

{calculo.status !== 'FINALIZADO' && (

Adicionar Multa

%
R$