import React, { useState, useRef, useEffect } from 'react'; import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, BarController, Title, Tooltip, Legend, } from 'chart.js'; import { Bar } from 'react-chartjs-2'; import { useTranslation } from 'react-i18next'; import useFormatters from '../../hooks/useFormatters'; // Registrar componentes do Chart.js ChartJS.register( CategoryScale, LinearScale, BarElement, BarController, Title, Tooltip, Legend ); const OverpaymentsAnalysis = ({ data, loading, onTransactionClick }) => { const { t, i18n } = useTranslation(); const { currency } = useFormatters(); const chartRef = useRef(null); const [selectedMonth, setSelectedMonth] = useState(null); const [isMobile, setIsMobile] = useState(window.innerWidth < 768); const [isExpanded, setIsExpanded] = useState(false); // Helper para locale dinâmico const getLocale = () => i18n.language === 'pt-BR' ? 'pt-BR' : i18n.language === 'es' ? 'es-ES' : 'en-US'; // Agrupar transações por mês (apenas sobrepagamentos - variance > 0) const overpaymentsByMonth = {}; if (data?.transactions) { data.transactions .filter(t => t.variance > 0) .forEach(t => { const month = t.effective_date.substring(0, 7); if (!overpaymentsByMonth[month]) { overpaymentsByMonth[month] = { month, total: 0, count: 0, transactions: [] }; } overpaymentsByMonth[month].total += t.variance; overpaymentsByMonth[month].count += 1; overpaymentsByMonth[month].transactions.push(t); }); } // Criar array de meses ordenados const monthsData = Object.values(overpaymentsByMonth).sort((a, b) => a.month.localeCompare(b.month)); useEffect(() => { const handleResize = () => { const mobile = window.innerWidth < 768; setIsMobile(mobile); if (!mobile) { setIsExpanded(false); } }; window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); // Auto-expand if we have data in mobile useEffect(() => { if (isMobile && monthsData.length > 0 && !isExpanded) { setIsExpanded(true); } }, [isMobile, monthsData.length, isExpanded]); if (loading) { return (
Loading...
); } if (!data || !data.transactions || data.transactions.length === 0) { return (
{t('dashboard.overpaymentsAnalysis')}

{t('dashboard.noOverpayments')}

); } // Calcular total geral const totalOverpayment = monthsData.reduce((sum, m) => sum + m.total, 0); // Labels do gráfico formatados const labels = monthsData.map(d => { const [year, month] = d.month.split('-'); const date = new Date(year, month - 1); return date.toLocaleDateString(getLocale(), { month: 'short', year: 'numeric' }); }); const chartData = { labels, datasets: [ { label: t('dashboard.overpayment'), data: monthsData.map(d => d.total), backgroundColor: monthsData.map((_, i) => selectedMonth === i ? 'rgba(251, 191, 36, 1)' : 'rgba(251, 191, 36, 0.7)' ), borderColor: 'rgba(251, 191, 36, 1)', borderWidth: 0, borderRadius: 4, hoverBackgroundColor: 'rgba(251, 191, 36, 1)', }, ], }; const options = { responsive: true, maintainAspectRatio: false, onClick: (event, elements) => { if (elements.length > 0) { const index = elements[0].index; setSelectedMonth(selectedMonth === index ? null : index); } }, plugins: { legend: { display: false, }, tooltip: { backgroundColor: 'rgba(15, 23, 42, 0.95)', titleColor: '#fbbf24', bodyColor: '#f1f5f9', borderColor: '#fbbf24', borderWidth: 1, padding: 12, cornerRadius: 8, displayColors: false, callbacks: { title: (items) => { const idx = items[0].dataIndex; return monthsData[idx]?.month || ''; }, label: (context) => { const idx = context.dataIndex; const monthData = monthsData[idx]; return [ `${t('dashboard.overpayment')}: ${currency(monthData.total, 'BRL')}`, `${t('dashboard.transactions')}: ${monthData.count}` ]; }, }, }, }, scales: { x: { grid: { display: false, }, ticks: { color: '#64748b', font: { size: 11 }, }, }, y: { grid: { color: 'rgba(100, 116, 139, 0.1)', drawBorder: false, }, ticks: { color: '#64748b', font: { size: 11 }, callback: (value) => `+${currency(value, 'BRL').replace('R$', '').trim()}`, }, }, }, }; // Dados do mês selecionado const selectedMonthData = selectedMonth !== null ? monthsData[selectedMonth] : null; return (
{/* Header */}
{t('dashboard.overpaymentsAnalysis')} {!isMobile && `(${data.period?.months || 12} ${t('common.months')})`}
{isMobile && ( )}
{(!isMobile || isExpanded) && ( Total: {currency(totalOverpayment, 'BRL')} )}
{/* Instrução */}

{t('dashboard.clickBarToSeeDetails')}

{/* Gráfico */}
{/* Painel de detalhes do mês selecionado */} {selectedMonthData && (
{/* Header do painel */}
{t('dashboard.overpayments')} - {(() => { const [year, month] = selectedMonthData.month.split('-'); return new Date(year, month - 1).toLocaleDateString(getLocale(), { month: 'long', year: 'numeric' }); })()}
{/* Resumo do mês */}
{isMobile ? 'TOTAL' : t('dashboard.totalOverpaid')} +{currency(selectedMonthData.total, 'BRL')}
{isMobile ? 'QTD' : t('dashboard.transactions')} {selectedMonthData.count}
{isMobile ? 'MÉDIA' : t('dashboard.avgPerTransaction')} +{currency(selectedMonthData.total / selectedMonthData.count, 'BRL')}
{/* Tabela de transações */} {isMobile ? ( /* Layout Mobile - Cards */
{selectedMonthData.transactions.map((tx) => (
onTransactionClick?.(tx.id)} style={{ cursor: 'pointer', background: 'rgba(0,0,0,0.3)', border: '1px solid rgba(251, 191, 36, 0.2)' }} >
{tx.description.length > 25 ? tx.description.substring(0, 25) + '...' : tx.description} +{currency(tx.variance, 'BRL')}
{tx.category && ( {tx.category.name} )} {new Date(tx.effective_date).toLocaleDateString(getLocale(), { day: '2-digit', month: '2-digit' })}
+{tx.variance_percent}%
))}
) : ( /* Layout Desktop - Tabela */
{selectedMonthData.transactions.map((tx) => ( onTransactionClick?.(tx.id)} style={{ cursor: 'pointer' }} > ))}
{t('common.date')} {t('common.description')} {t('dashboard.category')} {t('dashboard.plannedValue')} {t('dashboard.actualValue')} {t('dashboard.difference')} {t('dashboard.delay')} %
{new Date(tx.effective_date).toLocaleDateString(getLocale())} {tx.description.length > 30 ? tx.description.substring(0, 30) + '...' : tx.description} {tx.category ? ( {tx.category.name} ) : ( - )} {currency(tx.planned_amount, 'BRL')} {currency(tx.actual_amount, 'BRL')} +{currency(tx.variance, 'BRL')} {tx.delay_days !== null && tx.delay_days !== 0 ? ( 0 ? 'rgba(239, 68, 68, 0.8)' : 'rgba(34, 197, 94, 0.8)' }} > 0 ? '-history' : ''} me-1`} style={{ fontSize: '9px' }}> {tx.delay_days > 0 ? `+${tx.delay_days}d` : `${tx.delay_days}d`} ) : ( - )} +{tx.variance_percent}%
)}
)} {/* Dica */} {!selectedMonthData && monthsData.length > 0 && (
{t('dashboard.tip')}: {t('dashboard.overpaymentTip')}
)}
); }; export default OverpaymentsAnalysis;