"use client"; import React, { useState, useEffect } from "react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Button } from "@/components/ui/button"; import { AlertCircle, BarChart, RefreshCw, Users, ShoppingCart, TrendingUp, TrendingDown, DollarSign, Package } from "lucide-react"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; // API response data structure interface AnalyticsData { vendors?: { total?: number; newToday?: number; newThisWeek?: number; activeToday?: number; active?: number; stores?: number; dailyGrowth?: { date: string; count: number }[]; }; orders?: { total?: number; totalToday?: number; totalThisWeek?: number; pending?: number; completed?: number; dailyOrders?: { date: string; count: number }[]; }; revenue?: { total?: number; today?: number; thisWeek?: number; dailyRevenue?: { date: string; amount: number }[]; }; engagement?: { totalMessages?: number; activeChats?: number; dailyMessages?: { date: string; count: number }[]; }; products?: { total?: number; recent?: number; }; stores?: { total?: number; active?: number; }; sessions?: { total?: number; active?: number; }; } export default function AdminAnalytics() { const [analyticsData, setAnalyticsData] = useState(null); const [loading, setLoading] = useState(true); const [dateRange, setDateRange] = useState("7days"); const [errorMessage, setErrorMessage] = useState(null); const [refreshing, setRefreshing] = useState(false); const fetchAnalyticsData = async () => { try { setLoading(true); setErrorMessage(null); const token = document.cookie .split("; ") .find((row) => row.startsWith("Authorization=")) ?.split("=")[1]; const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/admin/analytics?range=${dateRange}`, { method: "GET", headers: { Authorization: `Bearer ${token}`, }, }); if (!response.ok) { throw new Error("Failed to fetch analytics data"); } const data = await response.json(); setAnalyticsData(data); } catch (error) { console.error("Error fetching analytics data:", error); setErrorMessage("Failed to load analytics data. Please try again."); } finally { setLoading(false); setRefreshing(false); } }; useEffect(() => { fetchAnalyticsData(); }, [dateRange]); const handleRefresh = () => { setRefreshing(true); fetchAnalyticsData(); }; if (loading && !analyticsData) { return (
); } // Chart component for line/area charts const Chart = ({ data, valueKey = "count", color = "#3b82f6", height = 200 }: { data: any[]; valueKey?: string; color?: string; height?: number }) => { if (!data || data.length === 0) { return (
No data available
); } // Find min and max for scaling const values = data.map(d => d[valueKey] || 0); const max = Math.max(...values, 1); const min = Math.min(...values, 0); const range = max - min || 1; return (
{data.map((item, index) => { const value = item[valueKey] || 0; const normalizedHeight = ((value - min) / range) * 90 + 10; // Scale to 10%-100% return (
{valueKey === "amount" ? new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value) : value}
{new Date(item.date).toLocaleDateString('en-US', {month: 'short', day: 'numeric'})}
); })}
{/* X-axis labels */}
{new Date(data[0]?.date).toLocaleDateString('en-US', {month: 'short', day: 'numeric'})} {new Date(data[data.length - 1]?.date).toLocaleDateString('en-US', {month: 'short', day: 'numeric'})}
); }; // Trend indicator component for metric cards const TrendIndicator = ({ current, previous }: { current: number, previous: number }) => { if (!current || !previous) return null; const percentChange = ((current - previous) / previous) * 100; if (Math.abs(percentChange) < 0.1) return null; return (
= 0 ? 'text-green-500' : 'text-red-500'}`}> {percentChange >= 0 ? : } {Math.abs(percentChange).toFixed(1)}%
); }; // Format currency const formatCurrency = (value: number) => { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }).format(value); }; return (
{errorMessage && ( Error {errorMessage} )}

Dashboard Analytics

Overview of your marketplace performance

{/* Orders Card */}
Total Orders
{analyticsData?.orders?.total?.toLocaleString() || '0'}
Today: {analyticsData?.orders?.totalToday || 0}
{analyticsData?.orders?.dailyOrders && (
)}
{/* Revenue Card */}
Total Revenue
{formatCurrency(analyticsData?.revenue?.total || 0)}
Today: {formatCurrency(analyticsData?.revenue?.today || 0)}
{analyticsData?.revenue?.dailyRevenue && (
)}
{/* Vendors Card */}
Vendors
{analyticsData?.vendors?.total?.toLocaleString() || '0'}
New Today: {analyticsData?.vendors?.newToday || 0}
{analyticsData?.vendors?.dailyGrowth && (
)}
{/* Products Card */}
Products
{analyticsData?.products?.total?.toLocaleString() || '0'}
New This Week: {analyticsData?.products?.recent || 0}
Orders Revenue Vendors Engagement Order Trends Daily order volume over the selected time period {analyticsData?.orders?.dailyOrders ? ( ) : (
No order data available
)}
Total Orders
{analyticsData?.orders?.total?.toLocaleString() || '0'}
Pending Orders
{analyticsData?.orders?.pending?.toLocaleString() || '0'}
Completed Orders
{analyticsData?.orders?.completed?.toLocaleString() || '0'}
Revenue Trends Daily revenue over the selected time period {analyticsData?.revenue?.dailyRevenue ? ( ) : (
No revenue data available
)}
Total Revenue
{formatCurrency(analyticsData?.revenue?.total || 0)}
Today's Revenue
{formatCurrency(analyticsData?.revenue?.today || 0)}
This Week's Revenue
{formatCurrency(analyticsData?.revenue?.thisWeek || 0)}
Vendor Growth New vendor registrations over time {analyticsData?.vendors?.dailyGrowth ? ( ) : (
No vendor data available
)}
Total Vendors
{analyticsData?.vendors?.total?.toLocaleString() || '0'}
New Today
{analyticsData?.vendors?.newToday?.toLocaleString() || '0'}
New This Week
{analyticsData?.vendors?.newThisWeek?.toLocaleString() || '0'}
User Engagement Chat and message activity {analyticsData?.engagement?.dailyMessages ? ( ) : (
No engagement data available
)}
Total Messages
{analyticsData?.engagement?.totalMessages?.toLocaleString() || '0'}
Active Chats
{analyticsData?.engagement?.activeChats?.toLocaleString() || '0'}
Sessions
{analyticsData?.sessions?.active?.toLocaleString() || '0'} / {analyticsData?.sessions?.total?.toLocaleString() || '0'}
); }