diff --git a/CHANGELOG.md b/CHANGELOG.md index 92cb2f7..e48b3f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ O formato segue [Keep a Changelog](https://keepachangelog.com/pt-BR/). Este projeto adota [Versionamento Semântico](https://semver.org/pt-BR/). +## [1.43.22] - 2025-12-16 + +### Fixed +- **Widget de Projeção - Refresh Automático** + - FIX: Widget de projeção agora atualiza automaticamente quando há mudanças + - Sistema de eventos customizados para comunicação entre componentes + - Eventos implementados: `recurring-paid`, `transaction-created`, `transaction-updated`, `transaction-deleted`, `recurring-updated` + - Dashboard escuta eventos e força recarregamento via `refreshKey` + - CalendarWidget emite eventos após pagar/conciliar instâncias + - Widget de projeção desmonta e remonta para recarregar dados atualizados + ## [1.43.21] - 2025-12-16 ### Fixed diff --git a/VERSION b/VERSION index 15a0f2a..fe00e14 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.43.21 +1.43.22 diff --git a/frontend/src/components/dashboard/CalendarWidget.jsx b/frontend/src/components/dashboard/CalendarWidget.jsx index 01ac736..2e930af 100644 --- a/frontend/src/components/dashboard/CalendarWidget.jsx +++ b/frontend/src/components/dashboard/CalendarWidget.jsx @@ -236,6 +236,10 @@ const CalendarWidget = () => { } else { // Não encontrou - criar nova transação diretamente await recurringService.payInstance(instance.id); + + // Emitir evento para atualizar dashboard + window.dispatchEvent(new Event('recurring-paid')); + await loadCalendar(); if (selectedDate) { await loadDay(selectedDate); @@ -255,6 +259,10 @@ const CalendarWidget = () => { setReconcileData(prev => ({ ...prev, loading: true })); try { await recurringService.reconcileInstance(reconcileData.instance.id, transactionId); + + // Emitir evento para atualizar dashboard + window.dispatchEvent(new Event('recurring-paid')); + setShowReconcileModal(false); setReconcileData({ instance: null, candidates: [], loading: false }); await loadCalendar(); @@ -275,6 +283,10 @@ const CalendarWidget = () => { setReconcileData(prev => ({ ...prev, loading: true })); try { await recurringService.payInstance(reconcileData.instance.id); + + // Emitir evento para atualizar dashboard + window.dispatchEvent(new Event('recurring-paid')); + setShowReconcileModal(false); setReconcileData({ instance: null, candidates: [], loading: false }); await loadCalendar(); diff --git a/frontend/src/pages/Dashboard.jsx b/frontend/src/pages/Dashboard.jsx index 096576a..c934117 100644 --- a/frontend/src/pages/Dashboard.jsx +++ b/frontend/src/pages/Dashboard.jsx @@ -32,6 +32,9 @@ const Dashboard = () => { // Filtros dos gráficos const [cashflowMonths, setCashflowMonths] = useState(12); const [variancesMonths, setVariancesMonths] = useState(12); + + // Refresh key para forçar recarregamento de widgets + const [refreshKey, setRefreshKey] = useState(0); // Detectar resize useEffect(() => { @@ -39,6 +42,31 @@ const Dashboard = () => { window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); + + // Listener para eventos de mudança que requerem refresh + useEffect(() => { + const handleDataChange = () => { + setRefreshKey(prev => prev + 1); + loadSummary(); + loadCashflow(); + loadVariances(); + }; + + // Eventos que devem triggar refresh + window.addEventListener('transaction-updated', handleDataChange); + window.addEventListener('transaction-created', handleDataChange); + window.addEventListener('transaction-deleted', handleDataChange); + window.addEventListener('recurring-paid', handleDataChange); + window.addEventListener('recurring-updated', handleDataChange); + + return () => { + window.removeEventListener('transaction-updated', handleDataChange); + window.removeEventListener('transaction-created', handleDataChange); + window.removeEventListener('transaction-deleted', handleDataChange); + window.removeEventListener('recurring-paid', handleDataChange); + window.removeEventListener('recurring-updated', handleDataChange); + }; + }, [loadSummary, loadCashflow, loadVariances]); // Carregar resumo geral const loadSummary = useCallback(async () => { @@ -325,7 +353,7 @@ const Dashboard = () => { {/* Projeção de Saldo - Full Width */}