"use client"; import { useState, useEffect } from "react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { TrendingUp, TrendingDown, Package, DollarSign, AlertTriangle, RefreshCw, Calendar, BarChart3, } from "lucide-react"; import { useToast } from "@/hooks/use-toast"; import { Skeleton } from "@/components/ui/skeleton"; import { getPredictionsOverviewWithStore, getStockPredictionsWithStore, type PredictionsOverview, type StockPredictionsResponse, } from "@/lib/services/analytics-service"; import { formatGBP } from "@/utils/format"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { format } from "date-fns"; interface PredictionsChartProps { timeRange?: number; } export default function PredictionsChart({ timeRange = 30, }: PredictionsChartProps) { const [predictions, setPredictions] = useState( null, ); const [stockPredictions, setStockPredictions] = useState(null); const [loading, setLoading] = useState(true); const [daysAhead, setDaysAhead] = useState(7); const [activeTab, setActiveTab] = useState<"overview" | "stock">("overview"); const { toast } = useToast(); const fetchPredictions = async () => { try { setLoading(true); const [overview, stock] = await Promise.all([ getPredictionsOverviewWithStore(daysAhead, timeRange), getStockPredictionsWithStore(timeRange), ]); setPredictions(overview); setStockPredictions(stock); } catch (error) { console.error("Error fetching predictions:", error); toast({ title: "Error", description: "Failed to load predictions", variant: "destructive", }); } finally { setLoading(false); } }; useEffect(() => { fetchPredictions(); }, [daysAhead, timeRange]); const getConfidenceColor = (confidence: string) => { switch (confidence) { case "high": return "bg-green-500/10 text-green-700 dark:text-green-400"; case "medium": return "bg-yellow-500/10 text-yellow-700 dark:text-yellow-400"; case "low": return "bg-red-500/10 text-red-700 dark:text-red-400"; default: return "bg-gray-500/10 text-gray-700 dark:text-gray-400"; } }; if (loading) { return (
); } if (!predictions) { return ( Predictions Forecast future sales, demand, and stock levels

No prediction data available. Need more historical data.

); } return (
Predictions & Forecasting AI-powered predictions for sales, demand, and inventory
{activeTab === "overview" && (
{/* Sales Predictions */}
Revenue Prediction {predictions.sales.predicted !== null ? (
{formatGBP(predictions.sales.predicted)}
{predictions.sales.confidence} confidence Next {daysAhead} days
{predictions.sales.predictedOrders && (
~{Math.round(predictions.sales.predictedOrders)}{" "} orders
)} {predictions.sales.minPrediction && predictions.sales.maxPrediction && (
Range: {formatGBP(predictions.sales.minPrediction)} -{" "} {formatGBP(predictions.sales.maxPrediction)}
)}
) : (
{predictions.sales.message || "Insufficient data for prediction"}
)}
Demand Prediction {predictions.demand.predictedDaily !== null ? (
{predictions.demand.predictedDaily.toFixed(1)} units/day
{predictions.demand.confidence} confidence
{predictions.demand.predictedWeekly && (
~{predictions.demand.predictedWeekly.toFixed(0)} units/week
)} {predictions.demand.predictedMonthly && (
~{predictions.demand.predictedMonthly.toFixed(0)} units/month
)}
) : (
{predictions.demand.message || "Insufficient data for prediction"}
)}
{/* Daily Predictions Chart */} {predictions.sales.dailyPredictions && predictions.sales.dailyPredictions.length > 0 && ( Daily Revenue Forecast
{predictions.sales.dailyPredictions.map((day) => (
Day {day.day}
{format(new Date(day.date), "MMM d, yyyy")}
{formatGBP(day.predicted)}
))}
)}
)} {activeTab === "stock" && (
{stockPredictions && stockPredictions.predictions.length > 0 ? ( <>

{stockPredictions.totalProducts} products tracked

{stockPredictions.productsNeedingRestock > 0 && (

{stockPredictions.productsNeedingRestock} products need restocking soon

)}
Product Current Stock Days Until Out Estimated Date Confidence Status {stockPredictions.predictions.map((prediction) => ( {prediction.productName} {prediction.currentStock} {prediction.unitType} {prediction.prediction.daysUntilOutOfStock !== null ? `${prediction.prediction.daysUntilOutOfStock} days` : "N/A"} {prediction.prediction.estimatedDate ? format( new Date( prediction.prediction.estimatedDate, ), "MMM d, yyyy", ) : "N/A"} {prediction.prediction.confidence} {prediction.needsRestock ? ( Restock Soon ) : ( OK )} ))}
) : (

No stock predictions available

Enable stock tracking on products to get predictions

)}
)}
); }