"use client"; export const dynamic = "force-dynamic"; import React, { Suspense, lazy, useState, useEffect, Component, ReactNode } from "react"; import { Button } from "@/components/ui/button"; import Link from "next/link"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Skeleton } from "@/components/ui/skeleton"; import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { AlertCircle, RefreshCw } from "lucide-react"; // Error Boundary Component interface ErrorBoundaryState { hasError: boolean; error: Error | null; } interface ErrorBoundaryProps { children: ReactNode; fallback?: ReactNode; componentName?: string; } class ErrorBoundary extends Component { private retryCount = 0; private maxRetries = 2; constructor(props: ErrorBoundaryProps) { super(props); this.state = { hasError: false, error: null }; } static getDerivedStateFromError(error: Error): ErrorBoundaryState { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { console.error(`Error loading ${this.props.componentName || 'component'}:`, error, errorInfo); // Log to error tracking service if available if (typeof window !== 'undefined' && (window as any).gtag) { (window as any).gtag('event', 'exception', { description: `Failed to load ${this.props.componentName || 'component'}: ${error.message}`, fatal: false, }); } } handleRetry = () => { if (this.retryCount < this.maxRetries) { this.retryCount++; this.setState({ hasError: false, error: null }); // Force a re-render by updating the key or reloading the component // The lazy import will be retried when the component re-mounts } else { // After max retries, suggest a full page reload window.location.reload(); } }; render() { if (this.state.hasError) { if (this.props.fallback) { return this.props.fallback; } return ( Failed to load {this.props.componentName || 'component'}

{this.state.error?.message || 'An unexpected error occurred while loading this component.'}

{this.retryCount < this.maxRetries && (

Retry attempt {this.retryCount + 1} of {this.maxRetries + 1}

)}
); } return this.props.children; } } // Lazy load admin components with error handling const AdminAnalytics = lazy(() => import("@/components/admin/AdminAnalytics").catch((err) => { console.error("Failed to load AdminAnalytics:", err); throw err; }) ); const InviteVendorCard = lazy(() => import("@/components/admin/InviteVendorCard").catch((err) => { console.error("Failed to load InviteVendorCard:", err); throw err; }) ); const BanUserCard = lazy(() => import("@/components/admin/BanUserCard").catch((err) => { console.error("Failed to load BanUserCard:", err); throw err; }) ); const InvitationsListCard = lazy(() => import("@/components/admin/InvitationsListCard").catch((err) => { console.error("Failed to load InvitationsListCard:", err); throw err; }) ); const VendorsCard = lazy(() => import("@/components/admin/VendorsCard").catch((err) => { console.error("Failed to load VendorsCard:", err); throw err; }) ); // Loading skeleton with timeout warning function AdminComponentSkeleton({ showSlowWarning = false }: { showSlowWarning?: boolean }) { return (
{showSlowWarning && ( Taking longer than expected The component is still loading. This may be due to a slow connection. Please wait... )} {/* Subtle loading indicator */}
{/* Header skeleton */}
{/* Metric cards grid skeleton */}
{[1, 2, 3, 4, 5, 6, 7, 8].map((i) => (
{/* Chart area skeleton */}
{[...Array(7)].map((_, idx) => { // Deterministic heights to avoid hydration mismatches const heights = [45, 65, 55, 80, 50, 70, 60]; return ( ); })}
))}
); } // Suspense wrapper with timeout function SuspenseWithTimeout({ children, fallback, timeout = 5000, timeoutFallback }: { children: ReactNode; fallback: ReactNode; timeout?: number; timeoutFallback?: ReactNode; }) { const [showTimeoutWarning, setShowTimeoutWarning] = useState(false); useEffect(() => { const timer = setTimeout(() => { setShowTimeoutWarning(true); }, timeout); return () => clearTimeout(timer); }, [timeout]); return ( {children} ); } // Loading skeleton for management cards function ManagementCardsSkeleton({ showSlowWarning = false }: { showSlowWarning?: boolean }) { return (
{showSlowWarning && (
Taking longer than expected The components are still loading. This may be due to a slow connection. Please wait...
)} {/* Subtle loading indicator */}
{[1, 2, 3, 4].map((i) => ( {/* Form elements skeleton for interactive cards */} {i <= 2 ? ( <> ) : ( /* List items skeleton for list cards */ <> {[1, 2, 3].map((j) => (
))} )}
))}
); } export default function AdminPage() { const [activeTab, setActiveTab] = useState("analytics"); const [prefetchedTabs, setPrefetchedTabs] = useState>(new Set()); // Prefetch components on tab hover or focus for better performance const prefetchTabComponents = (tab: string) => { // Avoid prefetching if already done if (prefetchedTabs.has(tab)) return; const startTime = performance.now(); if (tab === "analytics") { // Prefetch analytics component import("@/components/admin/AdminAnalytics") .then(() => { const loadTime = performance.now() - startTime; console.log(`[Performance] AdminAnalytics prefetched in ${loadTime.toFixed(2)}ms`); }) .catch(() => { }); } else if (tab === "management") { // Prefetch management components Promise.all([ import("@/components/admin/VendorsCard"), import("@/components/admin/InviteVendorCard"), import("@/components/admin/BanUserCard"), import("@/components/admin/InvitationsListCard"), ]) .then(() => { const loadTime = performance.now() - startTime; console.log(`[Performance] Management components prefetched in ${loadTime.toFixed(2)}ms`); }) .catch(() => { }); } setPrefetchedTabs(prev => new Set(prev).add(tab)); }; // Prefetch on hover const handleTabHover = (tab: string) => { prefetchTabComponents(tab); }; // Prefetch on focus (keyboard navigation) const handleTabFocus = (tab: string) => { prefetchTabComponents(tab); }; // Prefetch the active tab immediately if not already prefetched useEffect(() => { prefetchTabComponents(activeTab); // eslint-disable-next-line react-hooks/exhaustive-deps }, [activeTab]); return (

Admin Dashboard

Platform analytics and vendor management

handleTabHover("analytics")} onFocus={() => handleTabFocus("analytics")} > Analytics handleTabHover("management")} onFocus={() => handleTabFocus("management")} > Management } timeout={5000} timeoutFallback={} >
} timeout={5000} timeoutFallback={} >
); }