Update PredictionsChart.tsx
All checks were successful
Build Frontend / build (push) Successful in 1m5s
All checks were successful
Build Frontend / build (push) Successful in 1m5s
This commit is contained in:
@@ -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))",
|
||||||
|
|||||||
Reference in New Issue
Block a user