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

This commit is contained in:
g
2026-01-11 16:07:44 +00:00
parent 506b4b2f04
commit a8fdac532c

View File

@@ -26,7 +26,9 @@ import {
RefreshCw, RefreshCw,
Calendar, Calendar,
BarChart3, BarChart3,
Sparkles, Brain,
Layers,
Zap,
} 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";
@@ -46,6 +48,15 @@ import {
TableRow, TableRow,
} from "@/components/ui/table"; } from "@/components/ui/table";
import { format } from "date-fns"; import { format } from "date-fns";
import {
AreaChart,
Area,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
} from "recharts";
interface PredictionsChartProps { interface PredictionsChartProps {
timeRange?: number; timeRange?: number;
@@ -163,9 +174,6 @@ export default function PredictionsChart({
<CardTitle className="flex items-center gap-2"> <CardTitle className="flex items-center gap-2">
<BarChart3 className="h-5 w-5" /> <BarChart3 className="h-5 w-5" />
Predictions & Forecasting Predictions & Forecasting
{predictions.sales.aiModel?.used && (
<Sparkles className="h-4 w-4 text-purple-500" />
)}
</CardTitle> </CardTitle>
<CardDescription> <CardDescription>
{predictions.sales.aiModel?.used {predictions.sales.aiModel?.used
@@ -292,36 +300,6 @@ export default function PredictionsChart({
orders orders
</div> </div>
)} )}
{predictions.sales.confidenceIntervals && (
<div className="text-xs text-muted-foreground space-y-1">
<div>
Range: {formatGBP(predictions.sales.confidenceIntervals.lower)} -{" "}
{formatGBP(predictions.sales.confidenceIntervals.upper)}
</div>
<div className="text-xs opacity-75">
95% confidence interval
</div>
{predictions.sales.confidenceIntervals.confidenceScore !== undefined && (
<div className="flex gap-3 text-xs opacity-75 mt-2 pt-2 border-t">
{predictions.sales.confidenceIntervals.avgModelAccuracy !== undefined && (
<div>
Model Accuracy: {Math.round(predictions.sales.confidenceIntervals.avgModelAccuracy * 100)}%
</div>
)}
{predictions.sales.confidenceIntervals.modelAgreement !== undefined && (
<div>
Agreement: {Math.round(predictions.sales.confidenceIntervals.modelAgreement * 100)}%
</div>
)}
{predictions.sales.confidenceIntervals.dataConsistency !== undefined && (
<div>
Data Quality: {Math.round(predictions.sales.confidenceIntervals.dataConsistency * 100)}%
</div>
)}
</div>
)}
</div>
)}
{!predictions.sales.confidenceIntervals && {!predictions.sales.confidenceIntervals &&
predictions.sales.minPrediction && predictions.sales.minPrediction &&
predictions.sales.maxPrediction && ( predictions.sales.maxPrediction && (
@@ -340,51 +318,42 @@ export default function PredictionsChart({
</CardContent> </CardContent>
</Card> </Card>
{/* Model Intelligence Card */}
<Card> <Card>
<CardHeader className="pb-3"> <CardHeader className="pb-3">
<CardTitle className="text-sm font-medium flex items-center gap-2"> <CardTitle className="text-sm font-medium flex items-center gap-2">
<Package className="h-4 w-4" /> <Brain className="h-4 w-4" />
Demand Prediction Model Intelligence
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
{predictions.demand.predictedDaily !== null ? ( <div className="space-y-4">
<div className="space-y-2"> <div className="flex justify-between items-center">
<div className="text-2xl font-bold"> <span className="text-sm text-muted-foreground">Architecture</span>
{predictions.demand.predictedDaily.toFixed(1)} units/day <span className="text-sm font-medium flex items-center gap-1">
</div> <Layers className="h-3 w-3 text-purple-500" />
<div className="flex items-center gap-2"> Hybrid Ensemble (Deep Learning)
<Badge </span>
className={getConfidenceColor(
predictions.demand.confidence,
)}
>
{getConfidenceLabel(predictions.demand.confidence)} Confidence
</Badge>
</div>
{predictions.demand.predictedWeekly && (
<div className="text-sm text-muted-foreground">
~{predictions.demand.predictedWeekly.toFixed(0)} units/week
</div>
)}
{predictions.demand.predictedMonthly && (
<div className="text-sm text-muted-foreground">
~{predictions.demand.predictedMonthly.toFixed(0)} units/month
</div>
)}
{predictions.demand.confidenceIntervals && (
<div className="text-xs text-muted-foreground">
Range: {predictions.demand.confidenceIntervals.lower.toFixed(1)} -{" "}
{predictions.demand.confidenceIntervals.upper.toFixed(1)} units/day
</div>
)}
</div> </div>
) : ( {stockPredictions?.predictions && (
<div className="text-sm text-muted-foreground"> <div className="flex justify-between items-center">
{predictions.demand.message || <span className="text-sm text-muted-foreground">Features</span>
"Insufficient data for prediction"} <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>
)} <div className="pt-2 border-t text-xs text-muted-foreground">
Model automatically retrains with new sales data.
</div>
</div>
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
@@ -399,28 +368,59 @@ export default function PredictionsChart({
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="space-y-2"> <div className="h-[300px] w-full mt-4">
{predictions.sales.dailyPredictions.map((day) => ( <ResponsiveContainer width="100%" height="100%">
<div <AreaChart
key={day.day} data={predictions.sales.dailyPredictions.map(d => ({
className="flex items-center justify-between p-2 rounded-lg border" ...d,
formattedDate: format(new Date(d.date), "MMM d"),
value: d.predicted
}))}
margin={{
top: 5,
right: 10,
left: 0,
bottom: 0,
}}
> >
<div className="flex items-center gap-3"> <defs>
<Calendar className="h-4 w-4 text-muted-foreground" /> <linearGradient id="colorValue" x1="0" y1="0" x2="0" y2="1">
<div> <stop offset="5%" stopColor="#8884d8" stopOpacity={0.8} />
<div className="text-sm font-medium"> <stop offset="95%" stopColor="#8884d8" stopOpacity={0} />
Day {day.day} </linearGradient>
</div> </defs>
<div className="text-xs text-muted-foreground"> <CartesianGrid strokeDasharray="3 3" vertical={false} stroke="hsl(var(--border))" />
{format(new Date(day.date), "MMM d, yyyy")} <XAxis
</div> dataKey="formattedDate"
</div> stroke="hsl(var(--muted-foreground))"
</div> fontSize={12}
<div className="text-sm font-semibold"> tickLine={false}
{formatGBP(day.predicted)} axisLine={false}
</div> />
</div> <YAxis
))} stroke="hsl(var(--muted-foreground))"
fontSize={12}
tickLine={false}
axisLine={false}
tickFormatter={(value) => `£${value}`}
/>
<Tooltip
contentStyle={{
backgroundColor: "hsl(var(--background))",
borderColor: "hsl(var(--border))",
borderRadius: "var(--radius)",
}}
formatter={(value: number) => [formatGBP(value), "Revenue"]}
/>
<Area
type="monotone"
dataKey="value"
stroke="#8884d8"
fillOpacity={1}
fill="url(#colorValue)"
/>
</AreaChart>
</ResponsiveContainer>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>