"use client" import { useState, useEffect } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { useToast } from "@/hooks/use-toast"; import { Skeleton } from "@/components/ui/skeleton"; import { BarChart3, Clock, CheckCircle, XCircle, AlertCircle } from "lucide-react"; import { getOrderAnalyticsWithStore, type OrderAnalytics } from "@/lib/services/analytics-service"; import { formatGBP } from "@/utils/format"; interface OrderAnalyticsChartProps { timeRange: string; } export default function OrderAnalyticsChart({ timeRange }: OrderAnalyticsChartProps) { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const { toast } = useToast(); useEffect(() => { const fetchOrderData = async () => { try { setIsLoading(true); setError(null); const response = await getOrderAnalyticsWithStore(timeRange); setData(response); } catch (err) { console.error('Error fetching order analytics:', err); setError('Failed to load order data'); toast({ title: "Error", description: "Failed to load order analytics data.", variant: "destructive", }); } finally { setIsLoading(false); } }; fetchOrderData(); }, [timeRange, toast]); const getStatusColor = (status: string) => { switch (status) { case 'completed': case 'acknowledged': return 'bg-green-100 text-green-800'; case 'paid': case 'shipped': return 'bg-blue-100 text-blue-800'; case 'unpaid': case 'confirming': return 'bg-yellow-100 text-yellow-800'; case 'cancelled': return 'bg-red-100 text-red-800'; case 'disputed': return 'bg-orange-100 text-orange-800'; default: return 'bg-gray-100 text-gray-800'; } }; const getStatusIcon = (status: string) => { switch (status) { case 'completed': case 'acknowledged': return ; case 'paid': case 'shipped': return ; case 'unpaid': case 'confirming': return ; case 'cancelled': return ; default: return ; } }; const getStatusLabel = (status: string) => { switch (status) { case 'completed': return 'Completed'; case 'acknowledged': return 'Acknowledged'; case 'paid': return 'Paid'; case 'shipped': return 'Shipped'; case 'unpaid': return 'Unpaid'; case 'confirming': return 'Confirming'; case 'cancelled': return 'Cancelled'; case 'disputed': return 'Disputed'; default: return status.charAt(0).toUpperCase() + status.slice(1); } }; if (isLoading) { return ( Order Analytics Order status distribution and trends
); } if (error || !data) { return ( Order Analytics

Failed to load order data

); } const totalOrders = data.statusDistribution.reduce((sum, item) => sum + item.count, 0); const totalRevenue = data.dailyOrders.reduce((sum, item) => sum + item.revenue, 0); return (
{/* Order Status Distribution */} Order Status Distribution Breakdown of orders by current status
{data.statusDistribution.map((status) => { const percentage = totalOrders > 0 ? (status.count / totalOrders * 100).toFixed(1) : '0'; const Icon = getStatusIcon(status._id); return (
{Icon}
{getStatusLabel(status._id)}
{status.count} orders
{percentage}%
of total
); })}
{/* Daily Order Trends */} Daily Order Trends Orders and revenue over the selected time period {data.dailyOrders.length === 0 ? (

No order data available for this period

) : (
{/* Summary Stats */}
{data.dailyOrders.length}
Days with Orders
{totalOrders}
Total Orders
{formatGBP(totalRevenue)}
Total Revenue
{/* Chart */}
{data.dailyOrders.map((item, index) => { const maxOrders = Math.max(...data.dailyOrders.map(d => d.orders)); const height = maxOrders > 0 ? (item.orders / maxOrders) * 100 : 0; const date = new Date(item._id.year, item._id.month - 1, item._id.day); const dateLabel = date.toLocaleDateString('en-GB', { month: 'short', day: 'numeric' }); return (
{dateLabel}
); })}
)} {/* Processing Time */} Order Processing Time Average time to complete orders
{data.averageProcessingDays.toFixed(1)}
Average Days to Complete
); }