"use client"; import { useState, useEffect } from "react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Button } from "@/components/ui/button"; import { useToast } from "@/hooks/use-toast"; import { TrendingUp, TrendingDown, Users, ShoppingCart, DollarSign, Package, RefreshCw, } from "lucide-react"; import { getGrowthAnalyticsWithStore, type GrowthAnalytics, } from "@/lib/services/analytics-service"; import { formatGBP } from "@/utils/format"; import { ComposedChart, Bar, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, PieChart, Pie, Cell, } from "recharts"; interface GrowthAnalyticsChartProps { hideNumbers?: boolean; } const SEGMENT_COLORS = { new: "#3b82f6", returning: "#10b981", loyal: "#f59e0b", vip: "#8b5cf6", }; export default function GrowthAnalyticsChart({ hideNumbers = false, }: GrowthAnalyticsChartProps) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [period, setPeriod] = useState("30"); const [refreshing, setRefreshing] = useState(false); const { toast } = useToast(); const fetchData = async () => { try { setLoading(true); const response = await getGrowthAnalyticsWithStore(period); setData(response); } catch (err) { console.error("Error fetching growth data:", err); toast({ title: "Error", description: "Failed to load growth analytics data.", variant: "destructive", }); } finally { setLoading(false); setRefreshing(false); } }; useEffect(() => { fetchData(); }, [period]); const handleRefresh = () => { setRefreshing(true); fetchData(); }; const formatCurrency = (value: number) => { if (hideNumbers) return "£***"; return new Intl.NumberFormat("en-GB", { style: "currency", currency: "GBP", maximumFractionDigits: 0, }).format(value); }; const formatNumber = (value: number) => { if (hideNumbers) return "***"; return value.toLocaleString(); }; const TrendIndicator = ({ value, suffix = "%", }: { value: number; suffix?: string; }) => { if (hideNumbers) return ***; const isPositive = value > 0; const isNeutral = value === 0; return (
{isPositive ? ( ) : isNeutral ? null : ( )} {isPositive ? "+" : ""} {value.toFixed(1)} {suffix}
); }; const CustomTooltip = ({ active, payload }: any) => { if (active && payload?.length) { const item = payload[0].payload; return (

{item.date}

Orders: {hideNumbers ? "***" : item.orders.toLocaleString()}

Revenue: {hideNumbers ? "£***" : formatGBP(item.revenue)}

Customers: {hideNumbers ? "***" : item.uniqueCustomers}

); } return null; }; if (loading && !data) { return (
); } if (!data) { return (
No growth data available
); } const { summary, customerInsights, timeSeries, topGrowingProducts } = data; // Prepare pie chart data const segmentData = [ { name: "New", value: customerInsights.newCustomers, color: SEGMENT_COLORS.new, }, { name: "Returning", value: customerInsights.returningCustomers, color: SEGMENT_COLORS.returning, }, ]; return (
{/* Header */}

Store Growth

{data.period.start} to {data.period.end} ({data.period.granularity})

{/* Summary Cards */}
{/* Orders */}
Orders
{formatNumber(summary.currentPeriod.orders)}
vs {formatNumber(summary.previousPeriod.orders)} prev
{/* Revenue */}
Revenue
{formatCurrency(summary.currentPeriod.revenue)}
vs {formatCurrency(summary.previousPeriod.revenue)} prev
{/* Avg Order Value */}
Avg Order
{formatCurrency(summary.currentPeriod.avgOrderValue)}
vs {formatCurrency(summary.previousPeriod.avgOrderValue)} prev
{/* Customers */}
Customers
{formatNumber(summary.currentPeriod.customers)}
vs {formatNumber(summary.previousPeriod.customers)} prev
{/* Orders & Revenue Chart */} Orders & Revenue Trend Performance over the selected time period {loading || refreshing ? (
) : timeSeries.length > 0 ? (
(hideNumbers ? "***" : v)} /> hideNumbers ? "***" : `£${(v / 1000).toFixed(0)}k` } /> } />
) : (
No data available for the selected period
)}
{/* Customer Breakdown & Top Products */}
{/* Customer Segments */} Customer Breakdown New vs returning customers
{formatNumber(customerInsights.newCustomers)}
New
{formatNumber(customerInsights.returningCustomers)}
Returning
{formatNumber(customerInsights.totalCustomers)}
Total
{hideNumbers ? "***" : customerInsights.avgOrdersPerCustomer.toFixed(1)}
Avg Orders/Customer
{formatCurrency(customerInsights.avgSpentPerCustomer)}
Avg Spent/Customer
{/* Top Growing Products */} Top Growing Products Highest revenue growth vs previous period {topGrowingProducts.length > 0 ? (
{topGrowingProducts.slice(0, 5).map((product, index) => (
{index + 1}
{product.productName}
{formatCurrency(product.currentPeriodRevenue)}
= 0 ? "text-green-600" : "text-red-600" }`} > {hideNumbers ? "***" : `${product.revenueGrowth >= 0 ? "+" : ""}${product.revenueGrowth.toFixed(0)}%`}
))}
) : (
No product growth data available
)}
); }