import { useState, useEffect } from 'react'; import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts'; import { TrendingUp, Info } from 'lucide-react'; import api from '../api/axios'; import { useSettings } from '../context/SettingsContext'; const ForecastChart = () => { const { currencySymbol } = useSettings(); const [data, setData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchForecast = async () => { try { const response = await api.get('analytics/forecast/'); if (Array.isArray(response.data)) { setData(response.data); } else { throw new Error("Invalid format"); } setLoading(false); } catch (err) { console.error("Forecast Error:", err); const errMsg = err.response?.data?.error || "AI Engine Initializing..."; setError(errMsg); setLoading(false); } }; fetchForecast(); }, []); if (loading) return (
); if (error || !data.length) return (

{error || "No forecast data available yet."}

); // Calculate total predicted spend safely const totalPredicted = Array.isArray(data) ? data.reduce((acc, curr) => acc + (curr.amount || 0), 0) : 0; return (

🔮 Smart Forecast (Chronos Bolt)

AI-predicted spending for next 30 days

Projected Total
{currencySymbol}{totalPredicted.toLocaleString(undefined, { maximumFractionDigits: 0 })}
{ const d = new Date(str); return `${d.getDate()}/${d.getMonth() + 1}`; }} interval={4} /> `${currencySymbol}${val}`} /> { if (name === 'high') return [`${currencySymbol}${value}`, 'Upper Bound (P90)']; if (name === 'amount') return [`${currencySymbol}${value}`, 'Wait Forecast (P50)']; if (name === 'low') return [`${currencySymbol}${value}`, 'Lower Bound (P10)']; return [value, name]; }} labelStyle={{ color: '#818cf8', fontWeight: 'bold', marginBottom: '0.5rem' }} /> {/* Confidence Interval Area */} {/* We stack to create the band? No, simple Area is easier. */} {/* Actually, representing Low/High as area requires specific processing or multiple areas. Simplest visual: Area for Amount, and Lines for Low/High, OR a stacked approach: Low (invisible), (High-Low) as range. Let's try a transparent range. */} {/* We need to mask the bottom part if we want a band, but standard Area is 0-to-val. Recharts Area 'baseValue' isn't dynamic. Better visual: Just show the main line and a faint area for 'high' to give an impression of ceiling. Or use `Area` with `dataKey="amount"` as the main visual. */}
Predicted
Confidence Range
); }; export default ForecastChart;