@burdenoff/microfe-kadaikodi 2026.704.4 → 2026.704.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/kadaikodi/KadaikodiRoutes.js +30 -26
- package/dist/kadaikodi/KadaikodiRoutes.js.map +1 -1
- package/dist/kadaikodi/components/viz/AllocationBar.js +68 -0
- package/dist/kadaikodi/components/viz/AllocationBar.js.map +1 -0
- package/dist/kadaikodi/components/viz/AreaChart.js +102 -0
- package/dist/kadaikodi/components/viz/AreaChart.js.map +1 -0
- package/dist/kadaikodi/components/viz/AvatarStack.js +36 -0
- package/dist/kadaikodi/components/viz/AvatarStack.js.map +1 -0
- package/dist/kadaikodi/components/viz/BarChart.js +83 -0
- package/dist/kadaikodi/components/viz/BarChart.js.map +1 -0
- package/dist/kadaikodi/components/viz/CertificateCard.js +4 -0
- package/dist/kadaikodi/components/viz/DonutChart.js +109 -0
- package/dist/kadaikodi/components/viz/DonutChart.js.map +1 -0
- package/dist/kadaikodi/components/viz/HBarFunnel.js +54 -0
- package/dist/kadaikodi/components/viz/HBarFunnel.js.map +1 -0
- package/dist/kadaikodi/components/viz/Heatmap.js +3 -0
- package/dist/kadaikodi/components/viz/KanbanBoard.js +50 -0
- package/dist/kadaikodi/components/viz/KanbanBoard.js.map +1 -0
- package/dist/kadaikodi/components/viz/LineChart.js +4 -0
- package/dist/kadaikodi/components/viz/OrgTree.js +2 -0
- package/dist/kadaikodi/components/viz/PathSteps.js +3 -0
- package/dist/kadaikodi/components/viz/ProgressRing.js +68 -0
- package/dist/kadaikodi/components/viz/ProgressRing.js.map +1 -0
- package/dist/kadaikodi/components/viz/RatingStars.js +51 -0
- package/dist/kadaikodi/components/viz/RatingStars.js.map +1 -0
- package/dist/kadaikodi/components/viz/SegmentedTabs.js +69 -0
- package/dist/kadaikodi/components/viz/SegmentedTabs.js.map +1 -0
- package/dist/kadaikodi/components/viz/SkillBar.js +3 -0
- package/dist/kadaikodi/components/viz/Sparkline.js +74 -0
- package/dist/kadaikodi/components/viz/Sparkline.js.map +1 -0
- package/dist/kadaikodi/components/viz/StatCard.js +60 -0
- package/dist/kadaikodi/components/viz/StatCard.js.map +1 -0
- package/dist/kadaikodi/components/viz/StepProgress.js +64 -0
- package/dist/kadaikodi/components/viz/StepProgress.js.map +1 -0
- package/dist/kadaikodi/components/viz/Timeline.js +66 -0
- package/dist/kadaikodi/components/viz/Timeline.js.map +1 -0
- package/dist/kadaikodi/components/viz/index.js +23 -0
- package/dist/kadaikodi/components/viz/lib/Avatar.js +30 -0
- package/dist/kadaikodi/components/viz/lib/Avatar.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/CartesianFrame.js +119 -0
- package/dist/kadaikodi/components/viz/lib/CartesianFrame.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/ResponsiveSvg.js +35 -0
- package/dist/kadaikodi/components/viz/lib/ResponsiveSvg.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/format.js +21 -0
- package/dist/kadaikodi/components/viz/lib/format.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/geometry.js +61 -0
- package/dist/kadaikodi/components/viz/lib/geometry.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/hooks.js +39 -0
- package/dist/kadaikodi/components/viz/lib/hooks.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/palette.js +27 -0
- package/dist/kadaikodi/components/viz/lib/palette.js.map +1 -0
- package/dist/kadaikodi/hooks/useKadaikodiApi.js +18 -10
- package/dist/kadaikodi/hooks/useKadaikodiApi.js.map +1 -1
- package/dist/kadaikodi/pages/HomePage.js +373 -631
- package/dist/kadaikodi/pages/HomePage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js +304 -169
- package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminDashboard.js +255 -271
- package/dist/kadaikodi/pages/admin/AdminDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminFinancialPage.js +185 -125
- package/dist/kadaikodi/pages/admin/AdminFinancialPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.js +141 -102
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/CartManagementPage.js +558 -718
- package/dist/kadaikodi/pages/admin/CartManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/UserManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js +142 -55
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js +129 -164
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js +379 -361
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js +266 -166
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.js +373 -0
- package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.js.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js +288 -161
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js +180 -181
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/HelpSupportPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/SettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js +17 -34
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CartDetailPage.js +405 -248
- package/dist/kadaikodi/pages/customer/CartDetailPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js +258 -232
- package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CheckoutPage.js +254 -205
- package/dist/kadaikodi/pages/customer/CheckoutPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js +270 -230
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/FavoritesPage.js +149 -412
- package/dist/kadaikodi/pages/customer/FavoritesPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/OrderHistoryPage.js +173 -134
- package/dist/kadaikodi/pages/customer/OrderHistoryPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js +176 -175
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/ReviewsPage.js +295 -438
- package/dist/kadaikodi/pages/customer/ReviewsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/shared.js +181 -0
- package/dist/kadaikodi/pages/customer/shared.js.map +1 -0
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js +438 -311
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js +320 -293
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.js +159 -91
- package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorDashboard.js +137 -107
- package/dist/kadaikodi/pages/investor/InvestorDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js +157 -135
- package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.js +280 -206
- package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js +424 -448
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerDashboard.js +328 -445
- package/dist/kadaikodi/pages/worker/WorkerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js +141 -164
- package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js +300 -296
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js +284 -309
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminAnalyticsPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/admin/AdminAnalyticsPage.tsx"],"sourcesContent":["/**\n * Admin Analytics Page\n * @module kadaikodi/pages/admin\n *\n * Platform analytics wired to the live backend (useDashboardStats +\n * useAdminAnalytics + useProviders + useOrders). Every figure is real or\n * derived from real records — order-status distribution is counted from\n * loaded orders, category/growth breakdowns come from the analytics hook.\n * Metrics with no honest source (operating costs, delivery time, etc.) are\n * omitted rather than fabricated.\n */\n\nimport { useMemo, useState } from 'react';\nimport {\n Users,\n ShoppingBag,\n IndianRupee,\n BarChart3,\n Zap,\n Loader2,\n Star,\n Award,\n Store,\n TrendingUp,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { MetricsCard } from '../../components/MetricsCard';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport {\n useDashboardStats,\n useAdminAnalytics,\n useProviders,\n useOrders,\n} from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency } from '../../utils/formatters';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\ntype TabKey = 'overview' | 'revenue' | 'users' | 'performance';\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function AdminAnalyticsPage() {\n const { navigateTo } = useKadaikodi();\n\n const { data: stats, isLoading: statsLoading } = useDashboardStats();\n const { data: analytics, isLoading: analyticsLoading } = useAdminAnalytics();\n const { data: providers = [], isLoading: providersLoading } = useProviders();\n const { data: orders = [], isLoading: ordersLoading } = useOrders({});\n\n const [activeTab, setActiveTab] = useState<TabKey>('overview');\n\n const loading = statsLoading || analyticsLoading || providersLoading || ordersLoading;\n\n const fmtCur = (amount: number) => {\n if (amount >= 10000000) return `₹${(amount / 10000000).toFixed(1)}Cr`;\n if (amount >= 100000) return `₹${(amount / 100000).toFixed(1)}L`;\n return formatCurrency(amount, { minimumFractionDigits: 0 });\n };\n\n // Order status distribution — counted from real loaded orders.\n const orderStats = useMemo(() => {\n const total = orders.length;\n const completed = orders.filter((o) => o.status === 'delivered').length;\n const cancelled = orders.filter((o) => o.status === 'cancelled').length;\n const pending = orders.filter((o) => o.status === 'pending' || o.status === 'confirmed').length;\n const startOfToday = new Date();\n startOfToday.setHours(0, 0, 0, 0);\n const ordersToday = orders.filter(\n (o) => new Date(o.orderDate).getTime() >= startOfToday.getTime()\n ).length;\n const avgOrderValue =\n stats && stats.totalOrders > 0 ? stats.totalRevenue / stats.totalOrders : 0;\n return { total, completed, cancelled, pending, ordersToday, avgOrderValue };\n }, [orders, stats]);\n\n const pendingCarts = useMemo(() => providers.filter((p) => !p.isOpen).length, [providers]);\n\n const topCarts = analytics?.topProviders ?? [];\n const customerTotal = analytics?.customerGrowth?.customers ?? 0;\n\n // Cart distribution per category with a real, derived share percentage.\n // The backend exposes counts per category, not revenue per category.\n const categoryDistRows = useMemo(() => {\n const entries = Object.entries(analytics?.categoryDistribution ?? {});\n const total = entries.reduce((sum, [, count]) => sum + count, 0);\n return entries\n .map(([category, count]) => ({\n category,\n count,\n percentage: total > 0 ? (count / total) * 100 : 0,\n }))\n .sort((a, b) => b.count - a.count);\n }, [analytics]);\n\n const prettyCategory = (c: string) => c.replace(/_/g, ' ').toLowerCase();\n\n const pct = (part: number, whole: number) => (whole > 0 ? (part / whole) * 100 : 0);\n\n const medalIcon = (index: number) => {\n if (index < 3) return <Award className=\"h-5 w-5 text-status-warning-text\" />;\n return <BarChart3 className=\"h-5 w-5 text-text-secondary\" />;\n };\n\n if (loading || !stats) {\n return (\n <PageLayout title=\"Platform Analytics\" description=\"Loading analytics...\">\n <div className=\"flex flex-col items-center justify-center py-20\">\n <Loader2 className=\"h-10 w-10 animate-spin text-text-secondary mb-4\" />\n <p className=\"text-text-secondary\">Loading analytics...</p>\n </div>\n </PageLayout>\n );\n }\n\n const tabs: Array<{ key: TabKey; label: string; icon: typeof BarChart3 }> = [\n { key: 'overview', label: 'Overview', icon: BarChart3 },\n { key: 'revenue', label: 'Revenue', icon: IndianRupee },\n { key: 'users', label: 'Users', icon: Users },\n { key: 'performance', label: 'Performance', icon: Zap },\n ];\n\n return (\n <PageLayout title=\"Platform Analytics\" description=\"Comprehensive platform metrics and trends\">\n <PagePurpose className=\"mb-6\">\n Your bird's-eye view of how Kadaikodi is performing. Spot revenue and order trends, see\n which carts and categories drive the most business, and understand where customers are\n growing — so you can decide where to invest and which carts to promote. Switch tabs to drill\n into revenue, users, and operational performance.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"kadaikodi-admin-analytics\"\n className=\"mb-6\"\n steps={[\n {\n id: 'review-carts',\n label: 'Review top-performing carts',\n description: 'See which carts drive the most revenue and orders.',\n onClick: () => setActiveTab('overview'),\n },\n {\n id: 'check-revenue',\n label: 'Break down revenue by category',\n description: 'Find your strongest categories in the Revenue tab.',\n onClick: () => setActiveTab('revenue'),\n },\n {\n id: 'manage-carts',\n label: 'Approve pending carts',\n description: 'Onboard the carts waiting for review.',\n onClick: () => navigateTo('/admin/carts'),\n done: pendingCarts === 0,\n },\n ]}\n />\n\n <div className=\"flex justify-end mb-6\">\n <span className=\"text-sm text-text-secondary\">\n Last updated: {new Date().toLocaleString('en-IN')}\n </span>\n </div>\n\n {/* Key Metrics — the one emphasis zone for this page */}\n <EmphasisPanel className=\"mb-8\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">Key Metrics</h2>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4\">\n <MetricsCard\n featured\n icon={<IndianRupee className=\"h-5 w-5\" />}\n value={fmtCur(stats.totalRevenue)}\n label=\"Total Revenue\"\n />\n <MetricsCard\n icon={<ShoppingBag className=\"h-5 w-5\" />}\n value={(stats.totalOrders ?? 0).toLocaleString('en-IN')}\n label=\"Total Orders\"\n />\n <MetricsCard\n icon={<Users className=\"h-5 w-5\" />}\n value={(stats.activeCustomers ?? 0).toLocaleString('en-IN')}\n label=\"Active Customers\"\n />\n <MetricsCard\n icon={<Store className=\"h-5 w-5\" />}\n value={(stats.activeProviders ?? 0).toLocaleString('en-IN')}\n label=\"Active Carts\"\n trendValue={`${pendingCarts} pending`}\n />\n </div>\n </EmphasisPanel>\n\n {/* Tabs */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface mb-8\">\n <div className=\"border-b border-border-subtle\">\n <nav className=\"flex -mb-px overflow-x-auto\">\n {tabs.map((tab) => {\n const TabIcon = tab.icon;\n return (\n <button\n key={tab.key}\n type=\"button\"\n onClick={() => setActiveTab(tab.key)}\n className={cn(\n 'flex items-center gap-2 py-3 px-4 sm:px-6 text-sm font-medium whitespace-nowrap border-b-2 transition-colors',\n activeTab === tab.key\n ? 'border-primary text-primary'\n : 'border-transparent text-text-secondary hover:text-text-primary'\n )}\n >\n <TabIcon className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">{tab.label}</span>\n </button>\n );\n })}\n </nav>\n </div>\n\n <div className=\"p-4 sm:p-6\">\n {/* Overview Tab */}\n {activeTab === 'overview' && (\n <div className=\"space-y-8\">\n <div>\n <h3 className=\"text-lg font-semibold text-text-primary mb-4\">\n Order Status Distribution\n </h3>\n {orderStats.total > 0 ? (\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-4\">\n <div className=\"rounded-lg border border-status-success-text/30 bg-status-success-bg-subtle p-4\">\n <p className=\"text-sm text-status-success-text\">Completed Orders</p>\n <p className=\"text-2xl font-bold text-status-success-text\">\n {orderStats.completed.toLocaleString('en-IN')}\n </p>\n <p className=\"text-sm text-status-success-text/80\">\n {pct(orderStats.completed, orderStats.total).toFixed(1)}% of total\n </p>\n </div>\n <div className=\"rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle p-4\">\n <p className=\"text-sm text-status-warning-text\">Pending Orders</p>\n <p className=\"text-2xl font-bold text-status-warning-text\">\n {orderStats.pending.toLocaleString('en-IN')}\n </p>\n <p className=\"text-sm text-status-warning-text/80\">\n {pct(orderStats.pending, orderStats.total).toFixed(1)}% of total\n </p>\n </div>\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle p-4\">\n <p className=\"text-sm text-status-error-text\">Cancelled Orders</p>\n <p className=\"text-2xl font-bold text-status-error-text\">\n {orderStats.cancelled.toLocaleString('en-IN')}\n </p>\n <p className=\"text-sm text-status-error-text/80\">\n {pct(orderStats.cancelled, orderStats.total).toFixed(1)}% of total\n </p>\n </div>\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Order breakdowns will appear here once orders are placed.\n </p>\n )}\n </div>\n\n <div>\n <h3 className=\"text-lg font-semibold text-text-primary mb-4\">\n Top Performing Carts\n </h3>\n {topCarts.length > 0 ? (\n <div className=\"rounded-lg border border-border-subtle overflow-hidden\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b border-border-subtle bg-bg-sunken/50\">\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase\">\n Cart Name\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase\">\n Category\n </th>\n <th className=\"px-4 py-3 text-right text-xs font-medium text-text-secondary uppercase\">\n Rating\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {topCarts.map((cart, i) => (\n <tr key={cart.id} className=\"hover:bg-accent/50 transition-colors\">\n <td className=\"px-4 py-3\">\n <div className=\"flex items-center gap-2\">\n {medalIcon(i)}\n <span className=\"text-sm font-medium text-text-primary\">\n {cart.name}\n </span>\n </div>\n </td>\n <td className=\"px-4 py-3 text-sm text-left text-text-secondary capitalize\">\n {prettyCategory(cart.category)}\n </td>\n <td className=\"px-4 py-3 text-sm text-right text-text-primary\">\n <span className=\"flex items-center justify-end gap-1\">\n <Star className=\"h-3.5 w-3.5 fill-status-warning-text text-status-warning-text\" />\n {(cart.rating ?? 0).toFixed(1)}\n </span>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Top-performing carts will be ranked here once orders start flowing.\n </p>\n )}\n </div>\n </div>\n )}\n\n {/* Revenue Tab */}\n {activeTab === 'revenue' && (\n <div className=\"space-y-8\">\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <div className=\"rounded-lg border border-border-focus/30 bg-[var(--color-accent-soft)] p-6\">\n <h4 className=\"text-sm font-medium text-text-primary mb-2\">Total Revenue</h4>\n <p className=\"text-2xl font-bold text-text-primary\">\n {fmtCur(stats.totalRevenue)}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-6\">\n <h4 className=\"text-sm font-medium text-text-secondary mb-2\">Total Orders</h4>\n <p className=\"text-2xl font-bold text-text-primary\">\n {(stats.totalOrders ?? 0).toLocaleString('en-IN')}\n </p>\n </div>\n <div className=\"rounded-lg border border-status-success-text/30 bg-status-success-bg-subtle p-6\">\n <h4 className=\"text-sm font-medium text-status-success-text mb-2\">\n Average Order Value\n </h4>\n <p className=\"text-2xl font-bold text-status-success-text\">\n {fmtCur(orderStats.avgOrderValue)}\n </p>\n </div>\n </div>\n\n <p className=\"text-sm text-text-secondary\">\n Revenue is not broken down by category by the platform backend. See the Users tab\n for how carts are distributed across categories.\n </p>\n </div>\n )}\n\n {/* Users Tab */}\n {activeTab === 'users' && (\n <div className=\"space-y-8\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Users className=\"h-5 w-5 text-text-secondary\" />\n <h4 className=\"text-sm font-medium text-text-secondary\">Active Customers</h4>\n </div>\n <p className=\"text-3xl font-bold text-text-primary\">\n {(stats.activeCustomers ?? 0).toLocaleString('en-IN')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Store className=\"h-5 w-5 text-text-secondary\" />\n <h4 className=\"text-sm font-medium text-text-secondary\">Active Cart Owners</h4>\n </div>\n <p className=\"text-3xl font-bold text-text-primary\">\n {(stats.activeProviders ?? 0).toLocaleString('en-IN')}\n </p>\n </div>\n </div>\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/20 p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Users className=\"h-5 w-5 text-text-secondary\" />\n <h3 className=\"text-sm font-medium text-text-secondary\">Total Customers</h3>\n </div>\n <p className=\"text-3xl font-bold text-text-primary\">\n {customerTotal.toLocaleString('en-IN')}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Customers on the platform to date.\n </p>\n </div>\n\n {categoryDistRows.length > 0 && (\n <div>\n <h3 className=\"text-lg font-semibold text-text-primary mb-4\">\n Cart Category Distribution\n </h3>\n <div className=\"space-y-3\">\n {categoryDistRows.map((row) => (\n <div key={row.category}>\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"text-sm font-medium text-text-primary capitalize\">\n {prettyCategory(row.category)}\n </span>\n <span className=\"text-sm text-text-secondary\">\n {(row.count ?? 0).toLocaleString('en-IN')} (\n {(row.percentage ?? 0).toFixed(1)}%)\n </span>\n </div>\n <div className=\"w-full bg-bg-sunken rounded-full h-2\">\n <div\n className=\"bg-action-primary-bg h-2 rounded-full transition-all duration-300\"\n style={{ width: `${row.percentage}%` }}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Performance Tab */}\n {activeTab === 'performance' && (\n <div className=\"space-y-8\">\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Star className=\"h-4 w-4 text-text-secondary\" />\n <h4 className=\"text-sm font-medium text-text-secondary\">\n Customer Satisfaction\n </h4>\n </div>\n <p className=\"text-3xl font-bold text-text-primary flex items-center gap-1\">\n <Star className=\"h-6 w-6 fill-status-warning-text text-status-warning-text\" />\n {stats.avgRating > 0 ? stats.avgRating.toFixed(1) : '—'}\n </p>\n <p className=\"text-sm text-text-secondary mt-1\">Average rating across carts</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <TrendingUp className=\"h-4 w-4 text-text-secondary\" />\n <h4 className=\"text-sm font-medium text-text-secondary\">Completion Rate</h4>\n </div>\n <p className=\"text-3xl font-bold text-text-primary\">\n {orderStats.total > 0\n ? `${pct(orderStats.completed, orderStats.total).toFixed(1)}%`\n : '—'}\n </p>\n <p className=\"text-sm text-text-secondary mt-1\">Orders delivered</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <BarChart3 className=\"h-4 w-4 text-text-secondary\" />\n <h4 className=\"text-sm font-medium text-text-secondary\">Cancellation Rate</h4>\n </div>\n <p className=\"text-3xl font-bold text-text-primary\">\n {orderStats.total > 0\n ? `${pct(orderStats.cancelled, orderStats.total).toFixed(1)}%`\n : '—'}\n </p>\n <p className=\"text-sm text-text-secondary mt-1\">Orders cancelled</p>\n </div>\n </div>\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <h3 className=\"text-lg font-semibold text-text-primary mb-4\">\n Today's Activity\n </h3>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <p className=\"text-sm text-text-secondary mb-2\">Orders Today</p>\n <p className=\"text-3xl font-bold text-text-primary\">\n {orderStats.ordersToday.toLocaleString('en-IN')}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary mb-2\">Pending Orders</p>\n <p className=\"text-3xl font-bold text-status-warning-text\">\n {(stats.pendingOrders ?? 0).toLocaleString('en-IN')}\n </p>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AdminAnalyticsPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/admin/AdminAnalyticsPage.tsx"],"sourcesContent":["/**\n * Admin Analytics Page\n * @module kadaikodi/pages/admin\n *\n * Platform analytics wired to the live backend (useDashboardStats +\n * useAdminAnalytics + useProviders + useOrders). Every figure is real or\n * derived from real records — order-status distribution is counted from\n * loaded orders, category/growth breakdowns come from the analytics hook.\n * Metrics with no honest source (operating costs, delivery time, etc.) are\n * omitted rather than fabricated.\n */\n\nimport { useMemo, useState } from 'react';\nimport {\n Users,\n ShoppingBag,\n IndianRupee,\n BarChart3,\n Zap,\n Loader2,\n Star,\n Award,\n Store,\n TrendingUp,\n} from 'lucide-react';\nimport { EmphasisPanel, GlassCard, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { MetricsCard } from '../../components/MetricsCard';\nimport { DonutChart, AreaChart, HBarFunnel } from '../../components/viz';\nimport type { LabeledValue, Segment } from '../../components/viz';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport {\n useDashboardStats,\n useAdminAnalytics,\n useProviders,\n useOrders,\n} from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency } from '../../utils/formatters';\n\n/* ------------------------------------------------------------------ */\n/* Types + helpers */\n/* ------------------------------------------------------------------ */\n\ntype TabKey = 'overview' | 'revenue' | 'users' | 'performance';\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\nconst titleCase = (s: string) =>\n s\n .replace(/_/g, ' ')\n .toLowerCase()\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n\nconst dayKey = (d: Date) => {\n const x = new Date(d);\n x.setHours(0, 0, 0, 0);\n return x.getTime();\n};\n\nconst dayLabel = (t: number) =>\n new Date(t).toLocaleDateString('en-IN', { day: 'numeric', month: 'short' });\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function AdminAnalyticsPage() {\n const { navigateTo } = useKadaikodi();\n\n const { data: stats, isLoading: statsLoading } = useDashboardStats();\n const { data: analytics, isLoading: analyticsLoading } = useAdminAnalytics();\n const { data: providers = [], isLoading: providersLoading } = useProviders();\n const { data: orders = [], isLoading: ordersLoading } = useOrders({});\n\n const [activeTab, setActiveTab] = useState<TabKey>('overview');\n\n const loading = statsLoading || analyticsLoading || providersLoading || ordersLoading;\n\n const fmtCur = (amount: number) => {\n if (amount >= 10000000) return `₹${(amount / 10000000).toFixed(1)}Cr`;\n if (amount >= 100000) return `₹${(amount / 100000).toFixed(1)}L`;\n return formatCurrency(amount, { minimumFractionDigits: 0 });\n };\n\n // Order status distribution — counted from real loaded orders.\n const orderStats = useMemo(() => {\n const total = orders.length;\n const completed = orders.filter((o) => o.status === 'delivered').length;\n const cancelled = orders.filter((o) => o.status === 'cancelled').length;\n const pending = orders.filter((o) => o.status === 'pending' || o.status === 'confirmed').length;\n const startOfToday = new Date();\n startOfToday.setHours(0, 0, 0, 0);\n const ordersToday = orders.filter(\n (o) => new Date(o.orderDate).getTime() >= startOfToday.getTime()\n ).length;\n const avgOrderValue =\n stats && stats.totalOrders > 0 ? stats.totalRevenue / stats.totalOrders : 0;\n return { total, completed, cancelled, pending, ordersToday, avgOrderValue };\n }, [orders, stats]);\n\n const pendingCarts = useMemo(() => providers.filter((p) => !p.isOpen).length, [providers]);\n\n const topCarts = analytics?.topProviders ?? [];\n const customerTotal = analytics?.customerGrowth?.customers ?? 0;\n\n // Cart distribution per category with a real, derived share percentage.\n // The backend exposes counts per category, not revenue per category.\n const categoryDistRows = useMemo(() => {\n const entries = Object.entries(analytics?.categoryDistribution ?? {});\n const total = entries.reduce((sum, [, count]) => sum + count, 0);\n return entries\n .map(([category, count]) => ({\n category,\n count,\n percentage: total > 0 ? (count / total) * 100 : 0,\n }))\n .sort((a, b) => b.count - a.count);\n }, [analytics]);\n\n const prettyCategory = (c: string) => c.replace(/_/g, ' ').toLowerCase();\n\n const pct = (part: number, whole: number) => (whole > 0 ? (part / whole) * 100 : 0);\n\n // ── Category distribution donut — real cart counts per category. ───────────\n const categorySegments = useMemo<Segment[]>(\n () =>\n Object.entries(analytics?.categoryDistribution ?? {})\n .sort((a, b) => b[1] - a[1])\n .map(([c, count]) => ({ label: titleCase(c), value: count })),\n [analytics]\n );\n const totalCarts = useMemo(\n () => categorySegments.reduce((s, seg) => s + seg.value, 0),\n [categorySegments]\n );\n\n // ── GMV + order-volume over time — real per-day figures from real orders. ──\n const { gmvTrend, volumeTrend } = useMemo(() => {\n const today = dayKey(new Date());\n const start = today - 29 * DAY_MS;\n const gmv = new Map<number, number>();\n const vol = new Map<number, number>();\n for (let t = start; t <= today; t += DAY_MS) {\n gmv.set(t, 0);\n vol.set(t, 0);\n }\n for (const o of orders) {\n const t = dayKey(new Date(o.orderDate));\n if (gmv.has(t)) {\n gmv.set(t, (gmv.get(t) ?? 0) + (o.total ?? 0));\n vol.set(t, (vol.get(t) ?? 0) + 1);\n }\n }\n const g: LabeledValue[] = [...gmv.entries()].map(([t, v]) => ({ label: dayLabel(t), value: v }));\n const v: LabeledValue[] = [...vol.entries()].map(([t, val]) => ({\n label: dayLabel(t),\n value: val,\n }));\n return { gmvTrend: g, volumeTrend: v };\n }, [orders]);\n\n // ── Top categories by revenue — derived by joining real orders → provider. ─\n const topCategoryRevenue = useMemo<LabeledValue[]>(() => {\n const catOf = new Map(providers.map((p) => [p.id, p.category]));\n const byCat = new Map<string, number>();\n for (const o of orders) {\n const cat = catOf.get(o.cartId) ?? 'OTHER';\n byCat.set(cat, (byCat.get(cat) ?? 0) + (o.total ?? 0));\n }\n return [...byCat.entries()]\n .filter(([, v]) => v > 0)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 6)\n .map(([c, v]) => ({ label: titleCase(c), value: v }));\n }, [orders, providers]);\n\n const medalIcon = (index: number) => {\n if (index < 3) return <Award className=\"h-5 w-5 text-status-warning-text\" />;\n return <BarChart3 className=\"h-5 w-5 text-text-secondary\" />;\n };\n\n if (loading || !stats) {\n return (\n <PageLayout title=\"Platform Analytics\" description=\"Loading analytics...\">\n <div className=\"flex flex-col items-center justify-center py-20\">\n <Loader2 className=\"h-10 w-10 animate-spin text-text-secondary mb-4\" />\n <p className=\"text-text-secondary\">Loading analytics...</p>\n </div>\n </PageLayout>\n );\n }\n\n const tabs: Array<{ key: TabKey; label: string; icon: typeof BarChart3 }> = [\n { key: 'overview', label: 'Overview', icon: BarChart3 },\n { key: 'revenue', label: 'Revenue', icon: IndianRupee },\n { key: 'users', label: 'Users', icon: Users },\n { key: 'performance', label: 'Performance', icon: Zap },\n ];\n\n return (\n <PageLayout title=\"Platform Analytics\" description=\"Comprehensive platform metrics and trends\">\n <PagePurpose className=\"mb-6\">\n Your bird's-eye view of how Kadaikodi is performing. Spot revenue and order trends, see\n which carts and categories drive the most business, and understand where customers are\n growing — so you can decide where to invest and which carts to promote. Switch tabs to drill\n into revenue, users, and operational performance.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"kadaikodi-admin-analytics\"\n className=\"mb-6\"\n steps={[\n {\n id: 'review-carts',\n label: 'Review top-performing carts',\n description: 'See which carts drive the most revenue and orders.',\n onClick: () => setActiveTab('overview'),\n },\n {\n id: 'check-revenue',\n label: 'Break down revenue by category',\n description: 'Find your strongest categories in the Revenue tab.',\n onClick: () => setActiveTab('revenue'),\n },\n {\n id: 'manage-carts',\n label: 'Approve pending carts',\n description: 'Onboard the carts waiting for review.',\n onClick: () => navigateTo('/admin/carts'),\n done: pendingCarts === 0,\n },\n ]}\n />\n\n <div className=\"flex justify-end mb-6\">\n <span className=\"text-sm text-text-secondary\">\n Last updated: {new Date().toLocaleString('en-IN')}\n </span>\n </div>\n\n {/* Key Metrics — the one emphasis zone for this page */}\n <EmphasisPanel className=\"mb-8\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">Key Metrics</h2>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4\">\n <MetricsCard\n featured\n icon={<IndianRupee className=\"h-5 w-5\" />}\n value={fmtCur(stats.totalRevenue)}\n label=\"Total Revenue\"\n />\n <MetricsCard\n icon={<ShoppingBag className=\"h-5 w-5\" />}\n value={(stats.totalOrders ?? 0).toLocaleString('en-IN')}\n label=\"Total Orders\"\n />\n <MetricsCard\n icon={<Users className=\"h-5 w-5\" />}\n value={(stats.activeCustomers ?? 0).toLocaleString('en-IN')}\n label=\"Active Customers\"\n />\n <MetricsCard\n icon={<Store className=\"h-5 w-5\" />}\n value={(stats.activeProviders ?? 0).toLocaleString('en-IN')}\n label=\"Active Carts\"\n trendValue={`${pendingCarts} pending`}\n />\n </div>\n </EmphasisPanel>\n\n {/* Real-chart grid — the mockup's analytics dashboard, all live data */}\n <div className=\"mb-8 grid grid-cols-1 gap-6 lg:grid-cols-2\">\n {/* Category Distribution */}\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <h3 className=\"mb-4 text-base font-semibold text-text-primary\">Category Distribution</h3>\n {categorySegments.length > 0 ? (\n <DonutChart\n segments={categorySegments}\n centerLabel={totalCarts.toLocaleString('en-IN')}\n centerCaption=\"carts\"\n valueFormatter={(v) => v.toLocaleString('en-IN')}\n />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Category breakdown will appear here as carts are onboarded.\n </p>\n )}\n </GlassCard>\n\n {/* GMV over time */}\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <div className=\"mb-4 flex items-center justify-between gap-2\">\n <h3 className=\"text-base font-semibold text-text-primary\">GMV over time</h3>\n <span className=\"text-xs text-text-muted\">Last 30 days</span>\n </div>\n {orders.length > 0 ? (\n <AreaChart\n series={gmvTrend}\n height={200}\n valueFormatter={(v) => fmtCur(v)}\n title=\"Gross merchandise value per day over the last 30 days\"\n />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n GMV will chart here once orders are placed.\n </p>\n )}\n </GlassCard>\n\n {/* Order Volume over time (real substitute for un-derivable customer-growth series) */}\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <div className=\"mb-4 flex items-center justify-between gap-2\">\n <h3 className=\"text-base font-semibold text-text-primary\">Order Volume</h3>\n <span className=\"text-xs text-text-muted\">Last 30 days</span>\n </div>\n {orders.length > 0 ? (\n <AreaChart\n series={volumeTrend}\n height={200}\n valueFormatter={(v) => v.toLocaleString('en-IN')}\n title=\"Order volume per day over the last 30 days\"\n />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Order volume will chart here once orders are placed.\n </p>\n )}\n </GlassCard>\n\n {/* Top Categories by Revenue */}\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <h3 className=\"mb-4 text-base font-semibold text-text-primary\">\n Top Categories by Revenue\n </h3>\n {topCategoryRevenue.length > 0 ? (\n <HBarFunnel\n stages={topCategoryRevenue}\n showConversion={false}\n valueFormatter={(v) => fmtCur(v)}\n />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Category revenue will rank here as orders come in.\n </p>\n )}\n </GlassCard>\n </div>\n\n {/* Tabs */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface mb-8\">\n <div className=\"border-b border-border-subtle\">\n <nav className=\"flex -mb-px overflow-x-auto\">\n {tabs.map((tab) => {\n const TabIcon = tab.icon;\n return (\n <button\n key={tab.key}\n type=\"button\"\n onClick={() => setActiveTab(tab.key)}\n className={cn(\n 'flex items-center gap-2 py-3 px-4 sm:px-6 text-sm font-medium whitespace-nowrap border-b-2 transition-colors',\n activeTab === tab.key\n ? 'border-primary text-primary'\n : 'border-transparent text-text-secondary hover:text-text-primary'\n )}\n >\n <TabIcon className=\"h-4 w-4\" />\n <span className=\"hidden sm:inline\">{tab.label}</span>\n </button>\n );\n })}\n </nav>\n </div>\n\n <div className=\"p-4 sm:p-6\">\n {/* Overview Tab */}\n {activeTab === 'overview' && (\n <div className=\"space-y-8\">\n <div>\n <h3 className=\"text-lg font-semibold text-text-primary mb-4\">\n Order Status Distribution\n </h3>\n {orderStats.total > 0 ? (\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-4\">\n <div className=\"rounded-lg border border-status-success-text/30 bg-status-success-bg-subtle p-4\">\n <p className=\"text-sm text-status-success-text\">Completed Orders</p>\n <p className=\"text-2xl font-bold text-status-success-text\">\n {orderStats.completed.toLocaleString('en-IN')}\n </p>\n <p className=\"text-sm text-status-success-text/80\">\n {pct(orderStats.completed, orderStats.total).toFixed(1)}% of total\n </p>\n </div>\n <div className=\"rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle p-4\">\n <p className=\"text-sm text-status-warning-text\">Pending Orders</p>\n <p className=\"text-2xl font-bold text-status-warning-text\">\n {orderStats.pending.toLocaleString('en-IN')}\n </p>\n <p className=\"text-sm text-status-warning-text/80\">\n {pct(orderStats.pending, orderStats.total).toFixed(1)}% of total\n </p>\n </div>\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle p-4\">\n <p className=\"text-sm text-status-error-text\">Cancelled Orders</p>\n <p className=\"text-2xl font-bold text-status-error-text\">\n {orderStats.cancelled.toLocaleString('en-IN')}\n </p>\n <p className=\"text-sm text-status-error-text/80\">\n {pct(orderStats.cancelled, orderStats.total).toFixed(1)}% of total\n </p>\n </div>\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Order breakdowns will appear here once orders are placed.\n </p>\n )}\n </div>\n\n <div>\n <h3 className=\"text-lg font-semibold text-text-primary mb-4\">\n Top Performing Carts\n </h3>\n {topCarts.length > 0 ? (\n <div className=\"rounded-lg border border-border-subtle overflow-hidden\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b border-border-subtle bg-bg-sunken/50\">\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase\">\n Cart Name\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase\">\n Category\n </th>\n <th className=\"px-4 py-3 text-right text-xs font-medium text-text-secondary uppercase\">\n Rating\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {topCarts.map((cart, i) => (\n <tr key={cart.id} className=\"hover:bg-accent/50 transition-colors\">\n <td className=\"px-4 py-3\">\n <div className=\"flex items-center gap-2\">\n {medalIcon(i)}\n <span className=\"text-sm font-medium text-text-primary\">\n {cart.name}\n </span>\n </div>\n </td>\n <td className=\"px-4 py-3 text-sm text-left text-text-secondary capitalize\">\n {prettyCategory(cart.category)}\n </td>\n <td className=\"px-4 py-3 text-sm text-right text-text-primary\">\n <span className=\"flex items-center justify-end gap-1\">\n <Star className=\"h-3.5 w-3.5 fill-status-warning-text text-status-warning-text\" />\n {(cart.rating ?? 0).toFixed(1)}\n </span>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Top-performing carts will be ranked here once orders start flowing.\n </p>\n )}\n </div>\n </div>\n )}\n\n {/* Revenue Tab */}\n {activeTab === 'revenue' && (\n <div className=\"space-y-8\">\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <div className=\"rounded-lg border border-border-focus/30 bg-[var(--color-accent-soft)] p-6\">\n <h4 className=\"text-sm font-medium text-text-primary mb-2\">Total Revenue</h4>\n <p className=\"text-2xl font-bold text-text-primary\">\n {fmtCur(stats.totalRevenue)}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-6\">\n <h4 className=\"text-sm font-medium text-text-secondary mb-2\">Total Orders</h4>\n <p className=\"text-2xl font-bold text-text-primary\">\n {(stats.totalOrders ?? 0).toLocaleString('en-IN')}\n </p>\n </div>\n <div className=\"rounded-lg border border-status-success-text/30 bg-status-success-bg-subtle p-6\">\n <h4 className=\"text-sm font-medium text-status-success-text mb-2\">\n Average Order Value\n </h4>\n <p className=\"text-2xl font-bold text-status-success-text\">\n {fmtCur(orderStats.avgOrderValue)}\n </p>\n </div>\n </div>\n\n {topCategoryRevenue.length > 0 ? (\n <div>\n <h4 className=\"mb-3 text-sm font-semibold text-text-primary\">\n Revenue by Category\n </h4>\n <HBarFunnel\n stages={topCategoryRevenue}\n showConversion={false}\n valueFormatter={(v) => fmtCur(v)}\n />\n <p className=\"mt-3 text-xs text-text-muted\">\n Derived by attributing each order's value to its cart's category.\n </p>\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Revenue by category will appear here as orders come in.\n </p>\n )}\n </div>\n )}\n\n {/* Users Tab */}\n {activeTab === 'users' && (\n <div className=\"space-y-8\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Users className=\"h-5 w-5 text-text-secondary\" />\n <h4 className=\"text-sm font-medium text-text-secondary\">Active Customers</h4>\n </div>\n <p className=\"text-3xl font-bold text-text-primary\">\n {(stats.activeCustomers ?? 0).toLocaleString('en-IN')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Store className=\"h-5 w-5 text-text-secondary\" />\n <h4 className=\"text-sm font-medium text-text-secondary\">Active Cart Owners</h4>\n </div>\n <p className=\"text-3xl font-bold text-text-primary\">\n {(stats.activeProviders ?? 0).toLocaleString('en-IN')}\n </p>\n </div>\n </div>\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/20 p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Users className=\"h-5 w-5 text-text-secondary\" />\n <h3 className=\"text-sm font-medium text-text-secondary\">Total Customers</h3>\n </div>\n <p className=\"text-3xl font-bold text-text-primary\">\n {customerTotal.toLocaleString('en-IN')}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Customers on the platform to date.\n </p>\n </div>\n\n {categoryDistRows.length > 0 && (\n <div>\n <h3 className=\"text-lg font-semibold text-text-primary mb-4\">\n Cart Category Distribution\n </h3>\n <div className=\"space-y-3\">\n {categoryDistRows.map((row) => (\n <div key={row.category}>\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"text-sm font-medium text-text-primary capitalize\">\n {prettyCategory(row.category)}\n </span>\n <span className=\"text-sm text-text-secondary\">\n {(row.count ?? 0).toLocaleString('en-IN')} (\n {(row.percentage ?? 0).toFixed(1)}%)\n </span>\n </div>\n <div className=\"w-full bg-bg-sunken rounded-full h-2\">\n <div\n className=\"bg-action-primary-bg h-2 rounded-full transition-all duration-300\"\n style={{ width: `${row.percentage}%` }}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Performance Tab */}\n {activeTab === 'performance' && (\n <div className=\"space-y-8\">\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-6\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <Star className=\"h-4 w-4 text-text-secondary\" />\n <h4 className=\"text-sm font-medium text-text-secondary\">\n Customer Satisfaction\n </h4>\n </div>\n <p className=\"text-3xl font-bold text-text-primary flex items-center gap-1\">\n <Star className=\"h-6 w-6 fill-status-warning-text text-status-warning-text\" />\n {stats.avgRating > 0 ? stats.avgRating.toFixed(1) : '—'}\n </p>\n <p className=\"text-sm text-text-secondary mt-1\">Average rating across carts</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <TrendingUp className=\"h-4 w-4 text-text-secondary\" />\n <h4 className=\"text-sm font-medium text-text-secondary\">Completion Rate</h4>\n </div>\n <p className=\"text-3xl font-bold text-text-primary\">\n {orderStats.total > 0\n ? `${pct(orderStats.completed, orderStats.total).toFixed(1)}%`\n : '—'}\n </p>\n <p className=\"text-sm text-text-secondary mt-1\">Orders delivered</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 mb-2\">\n <BarChart3 className=\"h-4 w-4 text-text-secondary\" />\n <h4 className=\"text-sm font-medium text-text-secondary\">Cancellation Rate</h4>\n </div>\n <p className=\"text-3xl font-bold text-text-primary\">\n {orderStats.total > 0\n ? `${pct(orderStats.cancelled, orderStats.total).toFixed(1)}%`\n : '—'}\n </p>\n <p className=\"text-sm text-text-secondary mt-1\">Orders cancelled</p>\n </div>\n </div>\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <h3 className=\"text-lg font-semibold text-text-primary mb-4\">\n Today's Activity\n </h3>\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n <div>\n <p className=\"text-sm text-text-secondary mb-2\">Orders Today</p>\n <p className=\"text-3xl font-bold text-text-primary\">\n {orderStats.ordersToday.toLocaleString('en-IN')}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary mb-2\">Pending Orders</p>\n <p className=\"text-3xl font-bold text-status-warning-text\">\n {(stats.pendingOrders ?? 0).toLocaleString('en-IN')}\n </p>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|