Update PredictionsChart.tsx
All checks were successful
Build Frontend / build (push) Successful in 1m5s

This commit is contained in:
g
2026-01-12 00:59:40 +00:00
parent a8fdac532c
commit c0f4b05ef4

View File

@@ -29,6 +29,7 @@ import {
Brain, Brain,
Layers, Layers,
Zap, Zap,
Info,
} from "lucide-react"; } from "lucide-react";
import { useToast } from "@/hooks/use-toast"; import { useToast } from "@/hooks/use-toast";
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
@@ -54,9 +55,15 @@ import {
XAxis, XAxis,
YAxis, YAxis,
CartesianGrid, CartesianGrid,
Tooltip, Tooltip as RechartsTooltip,
ResponsiveContainer, ResponsiveContainer,
} from "recharts"; } from "recharts";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
interface PredictionsChartProps { interface PredictionsChartProps {
timeRange?: number; timeRange?: number;
@@ -230,132 +237,185 @@ export default function PredictionsChart({
<div className="space-y-6"> <div className="space-y-6">
{/* Sales Predictions */} {/* Sales Predictions */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<Card> <TooltipProvider>
<CardHeader className="pb-3"> <Card>
<CardTitle className="text-sm font-medium flex items-center gap-2"> <CardHeader className="pb-3">
<DollarSign className="h-4 w-4" /> <CardTitle className="text-sm font-medium flex items-center gap-2">
Revenue Prediction <DollarSign className="h-4 w-4" />
</CardTitle> Revenue Prediction
</CardHeader> </CardTitle>
<CardContent> </CardHeader>
{predictions.sales.predicted !== null ? ( <CardContent>
<div className="space-y-2"> {predictions.sales.predicted !== null ? (
<div className="text-2xl font-bold"> <div className="space-y-2">
{formatGBP(predictions.sales.predicted)} <Tooltip>
</div> <TooltipTrigger asChild>
<div className="flex items-center gap-2 flex-wrap"> <div className="text-2xl font-bold w-fit cursor-help">
<Badge {formatGBP(predictions.sales.predicted)}
className={getConfidenceColor( </div>
predictions.sales.confidence, </TooltipTrigger>
<TooltipContent>
<p>Predicted daily average revenue for the next {daysAhead} days</p>
</TooltipContent>
</Tooltip>
<div className="flex items-center gap-2 flex-wrap">
<Tooltip>
<TooltipTrigger>
<div className="inline-flex">
<Badge
className={getConfidenceColor(
predictions.sales.confidence,
)}
>
{getConfidenceLabel(predictions.sales.confidence)} Confidence
{predictions.sales.confidenceScore !== undefined && (
<span className="ml-1 opacity-75">
({Math.round(predictions.sales.confidenceScore * 100)}%)
</span>
)}
</Badge>
</div>
</TooltipTrigger>
<TooltipContent>
<p>Based on data consistency, historical accuracy, and model agreement</p>
</TooltipContent>
</Tooltip>
{predictions.sales.aiModel?.used && (
<Tooltip>
<TooltipTrigger>
<div className="inline-flex">
<Badge variant="outline" className="bg-purple-500/10 text-purple-700 dark:text-purple-400 border-purple-500/30">
🤖 AI Powered
{predictions.sales.aiModel.modelAccuracy !== undefined && (
<span className="ml-1 opacity-75">
({Math.round(predictions.sales.aiModel.modelAccuracy * 100)}%)
</span>
)}
</Badge>
</div>
</TooltipTrigger>
<TooltipContent>
<p>Predictions generated using a Deep Learning Ensemble Model (TensorFlow.js)</p>
</TooltipContent>
</Tooltip>
)} )}
> {predictions.sales.trend && (
{getConfidenceLabel(predictions.sales.confidence)} Confidence <Tooltip>
{predictions.sales.confidenceScore !== undefined && ( <TooltipTrigger>
<span className="ml-1 opacity-75"> <div className="inline-flex">
({Math.round(predictions.sales.confidenceScore * 100)}%) <Badge
</span> variant="outline"
className={
predictions.sales.trend.direction === "up"
? "text-green-600 border-green-600"
: predictions.sales.trend.direction === "down"
? "text-red-600 border-red-600"
: ""
}
>
{predictions.sales.trend.direction === "up" && (
<TrendingUp className="h-3 w-3 mr-1" />
)}
{predictions.sales.trend.direction === "down" && (
<TrendingDown className="h-3 w-3 mr-1" />
)}
{predictions.sales.trend.direction === "up"
? "Trending Up"
: predictions.sales.trend.direction === "down"
? "Trending Down"
: "Stable"}
</Badge>
</div>
</TooltipTrigger>
<TooltipContent>
<p>Direction of the recent sales trend (slope analysis)</p>
</TooltipContent>
</Tooltip>
)} )}
</Badge> <span className="text-xs text-muted-foreground">
{predictions.sales.aiModel?.used && ( Next {daysAhead} days
<Badge variant="outline" className="bg-purple-500/10 text-purple-700 dark:text-purple-400 border-purple-500/30"> </span>
🤖 AI Powered
{predictions.sales.aiModel.modelAccuracy !== undefined && (
<span className="ml-1 opacity-75">
({Math.round(predictions.sales.aiModel.modelAccuracy * 100)}%)
</span>
)}
</Badge>
)}
{predictions.sales.trend && (
<Badge
variant="outline"
className={
predictions.sales.trend.direction === "up"
? "text-green-600 border-green-600"
: predictions.sales.trend.direction === "down"
? "text-red-600 border-red-600"
: ""
}
>
{predictions.sales.trend.direction === "up" && (
<TrendingUp className="h-3 w-3 mr-1" />
)}
{predictions.sales.trend.direction === "down" && (
<TrendingDown className="h-3 w-3 mr-1" />
)}
{predictions.sales.trend.direction === "up"
? "Trending Up"
: predictions.sales.trend.direction === "down"
? "Trending Down"
: "Stable"}
</Badge>
)}
<span className="text-xs text-muted-foreground">
Next {daysAhead} days
</span>
</div>
{predictions.sales.predictedOrders && (
<div className="text-sm text-muted-foreground">
~{Math.round(predictions.sales.predictedOrders)}{" "}
orders
</div> </div>
)} {predictions.sales.predictedOrders && (
{!predictions.sales.confidenceIntervals && <div className="text-sm text-muted-foreground">
predictions.sales.minPrediction && ~{Math.round(predictions.sales.predictedOrders)}{" "}
predictions.sales.maxPrediction && ( orders
<div className="text-xs text-muted-foreground">
Range: {formatGBP(predictions.sales.minPrediction)} -{" "}
{formatGBP(predictions.sales.maxPrediction)}
</div> </div>
)} )}
</div> {!predictions.sales.confidenceIntervals &&
) : ( predictions.sales.minPrediction &&
<div className="text-sm text-muted-foreground"> predictions.sales.maxPrediction && (
{predictions.sales.message || <div className="text-xs text-muted-foreground">
"Insufficient data for prediction"} Range: {formatGBP(predictions.sales.minPrediction)} -{" "}
</div> {formatGBP(predictions.sales.maxPrediction)}
)} </div>
</CardContent> )}
</Card> </div>
) : (
{/* Model Intelligence Card */} <div className="text-sm text-muted-foreground">
<Card> {predictions.sales.message ||
<CardHeader className="pb-3"> "Insufficient data for prediction"}
<CardTitle className="text-sm font-medium flex items-center gap-2">
<Brain className="h-4 w-4" />
Model Intelligence
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Architecture</span>
<span className="text-sm font-medium flex items-center gap-1">
<Layers className="h-3 w-3 text-purple-500" />
Hybrid Ensemble (Deep Learning)
</span>
</div>
{stockPredictions?.predictions && (
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Features</span>
<span className="text-xs font-medium bg-secondary px-2 py-1 rounded-md">
Multi-Feature Enabled
</span>
</div> </div>
)} )}
<div className="flex justify-between items-center"> </CardContent>
<span className="text-sm text-muted-foreground">Optimization</span> </Card>
<span className="text-sm font-medium flex items-center gap-1">
<Zap className="h-3 w-3 text-amber-500" /> {/* Model Intelligence Card */}
Performance Tuned <Card>
</span> <CardHeader className="pb-3">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<Brain className="h-4 w-4" />
Model Intelligence
<Tooltip>
<TooltipTrigger>
<Info className="h-3 w-3 text-muted-foreground cursor-help" />
</TooltipTrigger>
<TooltipContent>
<p>Technical details about the active prediction model</p>
</TooltipContent>
</Tooltip>
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Architecture</span>
<Tooltip>
<TooltipTrigger asChild>
<span className="text-sm font-medium flex items-center gap-1 cursor-help">
<Layers className="h-3 w-3 text-purple-500" />
Hybrid Ensemble (Deep Learning)
</span>
</TooltipTrigger>
<TooltipContent>
<p>Combines LSTM Neural Networks with Statistical Methods (Holt-Winters, ARIMA)</p>
</TooltipContent>
</Tooltip>
</div>
{stockPredictions?.predictions && (
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Features</span>
<span className="text-xs font-medium bg-secondary px-2 py-1 rounded-md">
Multi-Feature Enabled
</span>
</div>
)}
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Optimization</span>
<span className="text-sm font-medium flex items-center gap-1">
<Zap className="h-3 w-3 text-amber-500" />
Performance Tuned
</span>
</div>
<div className="pt-2 border-t text-xs text-muted-foreground">
Model automatically retrains with new sales data.
</div>
</div> </div>
<div className="pt-2 border-t text-xs text-muted-foreground"> </CardContent>
Model automatically retrains with new sales data. </Card>
</div> </TooltipProvider>
</div>
</CardContent>
</Card>
</div> </div>
{/* Daily Predictions Chart */} {/* Daily Predictions Chart */}
@@ -404,7 +464,7 @@ export default function PredictionsChart({
axisLine={false} axisLine={false}
tickFormatter={(value) => `£${value}`} tickFormatter={(value) => `£${value}`}
/> />
<Tooltip <RechartsTooltip
contentStyle={{ contentStyle={{
backgroundColor: "hsl(var(--background))", backgroundColor: "hsl(var(--background))",
borderColor: "hsl(var(--border))", borderColor: "hsl(var(--border))",