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,
Calendar,
BarChart3,
Sparkles,
Brain,
Layers,
Zap,
} from "lucide-react";
import { useToast } from "@/hooks/use-toast";
import { Skeleton } from "@/components/ui/skeleton";
@@ -46,6 +48,15 @@ import {
TableRow,
} from "@/components/ui/table";
import { format } from "date-fns";
import {
AreaChart,
Area,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
} from "recharts";
interface PredictionsChartProps {
timeRange?: number;
@@ -163,9 +174,6 @@ export default function PredictionsChart({
<CardTitle className="flex items-center gap-2">
<BarChart3 className="h-5 w-5" />
Predictions & Forecasting
{predictions.sales.aiModel?.used && (
<Sparkles className="h-4 w-4 text-purple-500" />
)}
</CardTitle>
<CardDescription>
{predictions.sales.aiModel?.used
@@ -292,36 +300,6 @@ export default function PredictionsChart({
orders
</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.minPrediction &&
predictions.sales.maxPrediction && (
@@ -340,51 +318,42 @@ export default function PredictionsChart({
</CardContent>
</Card>
{/* Model Intelligence Card */}
<Card>
<CardHeader className="pb-3">
<CardTitle className="text-sm font-medium flex items-center gap-2">
<Package className="h-4 w-4" />
Demand Prediction
<Brain className="h-4 w-4" />
Model Intelligence
</CardTitle>
</CardHeader>
<CardContent>
{predictions.demand.predictedDaily !== null ? (
<div className="space-y-2">
<div className="text-2xl font-bold">
{predictions.demand.predictedDaily.toFixed(1)} units/day
</div>
<div className="flex items-center gap-2">
<Badge
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 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>
) : (
<div className="text-sm text-muted-foreground">
{predictions.demand.message ||
"Insufficient data for prediction"}
{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>
</CardContent>
</Card>
</div>
@@ -399,28 +368,59 @@ export default function PredictionsChart({
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-2">
{predictions.sales.dailyPredictions.map((day) => (
<div
key={day.day}
className="flex items-center justify-between p-2 rounded-lg border"
<div className="h-[300px] w-full mt-4">
<ResponsiveContainer width="100%" height="100%">
<AreaChart
data={predictions.sales.dailyPredictions.map(d => ({
...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">
<Calendar className="h-4 w-4 text-muted-foreground" />
<div>
<div className="text-sm font-medium">
Day {day.day}
</div>
<div className="text-xs text-muted-foreground">
{format(new Date(day.date), "MMM d, yyyy")}
</div>
</div>
</div>
<div className="text-sm font-semibold">
{formatGBP(day.predicted)}
</div>
</div>
))}
<defs>
<linearGradient id="colorValue" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#8884d8" stopOpacity={0.8} />
<stop offset="95%" stopColor="#8884d8" stopOpacity={0} />
</linearGradient>
</defs>
<CartesianGrid strokeDasharray="3 3" vertical={false} stroke="hsl(var(--border))" />
<XAxis
dataKey="formattedDate"
stroke="hsl(var(--muted-foreground))"
fontSize={12}
tickLine={false}
axisLine={false}
/>
<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>
</CardContent>
</Card>