diff --git a/components/analytics/PredictionsChart.tsx b/components/analytics/PredictionsChart.tsx index 6608128..75b93e6 100644 --- a/components/analytics/PredictionsChart.tsx +++ b/components/analytics/PredictionsChart.tsx @@ -79,24 +79,28 @@ export default function PredictionsChart({ const [predictions, setPredictions] = useState( null, ); + const [baselinePredictions, setBaselinePredictions] = useState( + null, + ); const [stockPredictions, setStockPredictions] = useState(null); const [loading, setLoading] = useState(true); + const [isSimulating, setIsSimulating] = useState(false); const [daysAhead, setDaysAhead] = useState(7); const [activeTab, setActiveTab] = useState<"overview" | "stock">("overview"); const [simulationFactor, setSimulationFactor] = useState(0); const [committedSimulationFactor, setCommittedSimulationFactor] = useState(0); const { toast } = useToast(); - const fetchPredictions = async () => { + // Fetch baseline predictions (simulation factor = 0) + const fetchBaseline = async () => { try { setLoading(true); - // Convert percentage (e.g. 50) to factor (e.g. 0.5) - const factor = committedSimulationFactor / 100; const [overview, stock] = await Promise.all([ - getPredictionsOverviewWithStore(daysAhead, timeRange, factor), + getPredictionsOverviewWithStore(daysAhead, timeRange, 0), getStockPredictionsWithStore(timeRange), ]); + setBaselinePredictions(overview); setPredictions(overview); setStockPredictions(stock); } catch (error) { @@ -111,9 +115,43 @@ export default function PredictionsChart({ } }; + // Fetch simulated predictions (without full reload) + const fetchSimulation = async (factor: number) => { + if (factor === 0) { + // Use cached baseline + setPredictions(baselinePredictions); + return; + } + + try { + setIsSimulating(true); + const overview = await getPredictionsOverviewWithStore(daysAhead, timeRange, factor / 100); + setPredictions(overview); + } catch (error) { + console.error("Error fetching simulation:", error); + toast({ + title: "Error", + description: "Failed to load simulation", + variant: "destructive", + }); + } finally { + setIsSimulating(false); + } + }; + + // Fetch baseline on initial load or when daysAhead/timeRange changes useEffect(() => { - fetchPredictions(); - }, [daysAhead, timeRange, committedSimulationFactor]); + fetchBaseline(); + setCommittedSimulationFactor(0); + setSimulationFactor(0); + }, [daysAhead, timeRange]); + + // Fetch simulation when committed slider value changes + useEffect(() => { + if (baselinePredictions) { + fetchSimulation(committedSimulationFactor); + } + }, [committedSimulationFactor]); const getConfidenceColor = (confidence: string) => { switch (confidence) { @@ -145,27 +183,37 @@ export default function PredictionsChart({ } }; - const simulatedData = useMemo(() => { + // Combine baseline and simulated data for overlay chart + const chartData = useMemo(() => { if (!predictions?.sales?.dailyPredictions) return []; - return predictions.sales.dailyPredictions.map((d: any) => ({ + + const baselineData = baselinePredictions?.sales?.dailyPredictions || []; + const simulatedDailyData = predictions.sales.dailyPredictions; + + return simulatedDailyData.map((d: any, idx: number) => ({ ...d, formattedDate: format(new Date(d.date), "MMM d"), - value: d.predicted, - orders: d.predictedOrders || 0, // Ensure orders exist + simulated: d.predicted, + baseline: baselineData[idx]?.predicted ?? d.predicted, + orders: d.predictedOrders || 0, })); - }, [predictions]); + }, [predictions, baselinePredictions]); + + // Keep simulatedData for export compatibility + const simulatedData = chartData; const handleExportCSV = () => { if (!simulatedData.length) return; // Create CSV headers - const headers = ["Date", "Predicted Revenue", "Orders", "Confidence"]; + const headers = ["Date", "Baseline Revenue", "Simulated Revenue", "Orders", "Confidence"]; // Create CSV rows const rows = simulatedData.map(d => [ format(new Date(d.date), "yyyy-MM-dd"), - d.predicted.toFixed(2), - d.orders || "", // Provide fallback if orders is undefined + d.baseline?.toFixed(2) || "", + d.simulated?.toFixed(2) || "", + d.orders || "", predictions?.sales?.confidence || "unknown" ]); @@ -257,11 +305,11 @@ export default function PredictionsChart({ @@ -532,10 +580,15 @@ export default function PredictionsChart({ -
+
+ {isSimulating && ( +
+ +
+ )} - + + + + + @@ -578,16 +643,32 @@ export default function PredictionsChart({ borderColor: "hsl(var(--border))", borderRadius: "var(--radius)", }} - formatter={(value: number) => [formatGBP(value), "Revenue"]} + formatter={(value: number, name: string) => [ + formatGBP(value), + name === "baseline" ? "Baseline" : "Simulated" + ]} /> + {/* Always show baseline as solid line */} + {/* Show simulated line when simulation is active */} + {committedSimulationFactor !== 0 && ( + + )}
@@ -728,6 +809,6 @@ export default function PredictionsChart({
)}
- + ); } diff --git a/public/git-info.json b/public/git-info.json index 5a0a401..04840d9 100644 --- a/public/git-info.json +++ b/public/git-info.json @@ -1,4 +1,4 @@ { - "commitHash": "02ba4b0", - "buildTime": "2026-01-12T03:57:23.436Z" + "commitHash": "5d9f8fa", + "buildTime": "2026-01-12T04:07:03.023Z" } \ No newline at end of file