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.
*/}
);
};
export default ForecastChart;