"use client" import { useState, useEffect } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { useToast } from "@/hooks/use-toast"; import { Skeleton } from "@/components/ui/skeleton"; import { TrendingUp, DollarSign } from "lucide-react"; import { getRevenueTrendsWithStore, type RevenueData } from "@/lib/services/analytics-service"; import { formatGBP } from "@/utils/format"; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, BarChart, Bar } from 'recharts'; import { ChartSkeleton } from './SkeletonLoaders'; interface RevenueChartProps { timeRange: string; hideNumbers?: boolean; } interface ChartDataPoint { date: string; revenue: number; orders: number; formattedDate: string; } export default function RevenueChart({ timeRange, hideNumbers = false }: RevenueChartProps) { const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const { toast } = useToast(); useEffect(() => { const fetchRevenueData = async () => { try { setIsLoading(true); setError(null); const response = await getRevenueTrendsWithStore(timeRange); console.log('Revenue trends response:', response); setData(Array.isArray(response) ? response : []); } catch (err) { console.error('Error fetching revenue data:', err); setError('Failed to load revenue data'); setData([]); toast({ title: "Error", description: "Failed to load revenue trends data.", variant: "destructive", }); } finally { setIsLoading(false); } }; fetchRevenueData(); }, [timeRange, toast]); // Transform data for Recharts const chartData: ChartDataPoint[] = data.map(item => { // Use UTC to avoid timezone issues const date = new Date(Date.UTC(item._id.year, item._id.month - 1, item._id.day)); return { date: date.toISOString().split('T')[0], // YYYY-MM-DD format revenue: item.revenue || 0, orders: item.orders || 0, formattedDate: date.toLocaleDateString('en-GB', { weekday: 'short', month: 'short', day: 'numeric', timeZone: 'UTC' }) }; }); // Calculate summary stats const safeData = Array.isArray(data) ? data : []; const totalRevenue = safeData.reduce((sum, item) => sum + (item.revenue || 0), 0); const totalOrders = safeData.reduce((sum, item) => sum + (item.orders || 0), 0); const averageRevenue = safeData.length > 0 ? totalRevenue / safeData.length : 0; // Function to mask sensitive numbers const maskValue = (value: string): string => { if (!hideNumbers) return value; // For currency values (£X.XX), show £*** if (value.includes('£')) { return '£***'; } // For regular numbers, replace with asterisks return '***'; }; // Custom tooltip for the chart const CustomTooltip = ({ active, payload, label }: any) => { if (active && payload && payload.length) { const data = payload[0].payload; return (

{data.formattedDate}

Revenue: {hideNumbers ? '£***' : formatGBP(data.revenue)}

Orders: {hideNumbers ? '***' : data.orders}

); } return null; }; if (isLoading) { return ( ); } if (error) { return ( Revenue Trends

Failed to load revenue data

); } if (chartData.length === 0) { return ( Revenue Trends Revenue performance over the selected time period

No revenue data available for this period

); } return ( Revenue Trends Revenue performance over the selected time period
{/* Chart */}
hideNumbers ? '***' : `£${(value / 1000).toFixed(0)}k`} /> } />
{/* Summary stats */}
{maskValue(formatGBP(totalRevenue))}
Total Revenue
{maskValue(totalOrders.toString())}
Total Orders
{maskValue(formatGBP(averageRevenue))}
Avg Daily Revenue
); }