@burdenoff/microfe-kadaikodi 2026.704.2 → 2026.704.4

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.
Files changed (77) hide show
  1. package/dist/kadaikodi/KadaikodiRoutes.js +30 -26
  2. package/dist/kadaikodi/KadaikodiRoutes.js.map +1 -1
  3. package/dist/kadaikodi/hooks/useKadaikodiApi.js +76 -6
  4. package/dist/kadaikodi/hooks/useKadaikodiApi.js.map +1 -1
  5. package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js +45 -107
  6. package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js.map +1 -1
  7. package/dist/kadaikodi/pages/admin/AdminDashboard.js +30 -32
  8. package/dist/kadaikodi/pages/admin/AdminDashboard.js.map +1 -1
  9. package/dist/kadaikodi/pages/admin/AdminFinancialPage.js +137 -120
  10. package/dist/kadaikodi/pages/admin/AdminFinancialPage.js.map +1 -1
  11. package/dist/kadaikodi/pages/admin/AdminOrdersPage.js +2 -2
  12. package/dist/kadaikodi/pages/admin/AdminOrdersPage.js.map +1 -1
  13. package/dist/kadaikodi/pages/admin/AdminProfilePage.js.map +1 -1
  14. package/dist/kadaikodi/pages/admin/AdminSettingsPage.js +332 -276
  15. package/dist/kadaikodi/pages/admin/AdminSettingsPage.js.map +1 -1
  16. package/dist/kadaikodi/pages/admin/CartManagementPage.js +278 -283
  17. package/dist/kadaikodi/pages/admin/CartManagementPage.js.map +1 -1
  18. package/dist/kadaikodi/pages/admin/UserManagementPage.js +310 -366
  19. package/dist/kadaikodi/pages/admin/UserManagementPage.js.map +1 -1
  20. package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js +105 -111
  21. package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
  22. package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.js +290 -257
  23. package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.js.map +1 -1
  24. package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js +84 -70
  25. package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
  26. package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js +270 -228
  27. package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js.map +1 -1
  28. package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.js +194 -173
  29. package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.js.map +1 -1
  30. package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js +202 -139
  31. package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js.map +1 -1
  32. package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js +232 -0
  33. package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js.map +1 -0
  34. package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js +84 -79
  35. package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js.map +1 -1
  36. package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js.map +1 -1
  37. package/dist/kadaikodi/pages/common/HelpSupportPage.js +310 -317
  38. package/dist/kadaikodi/pages/common/HelpSupportPage.js.map +1 -1
  39. package/dist/kadaikodi/pages/common/NotificationCenterPage.js.map +1 -1
  40. package/dist/kadaikodi/pages/common/SettingsPage.js +502 -586
  41. package/dist/kadaikodi/pages/common/SettingsPage.js.map +1 -1
  42. package/dist/kadaikodi/pages/customer/BookingDetailsPage.js +243 -143
  43. package/dist/kadaikodi/pages/customer/BookingDetailsPage.js.map +1 -1
  44. package/dist/kadaikodi/pages/customer/CartDetailPage.js +4 -4
  45. package/dist/kadaikodi/pages/customer/CartDetailPage.js.map +1 -1
  46. package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js +2 -2
  47. package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js.map +1 -1
  48. package/dist/kadaikodi/pages/customer/CheckoutPage.js +4 -4
  49. package/dist/kadaikodi/pages/customer/CheckoutPage.js.map +1 -1
  50. package/dist/kadaikodi/pages/customer/CustomerDashboard.js +6 -6
  51. package/dist/kadaikodi/pages/customer/CustomerDashboard.js.map +1 -1
  52. package/dist/kadaikodi/pages/customer/CustomerProfilePage.js +189 -199
  53. package/dist/kadaikodi/pages/customer/CustomerProfilePage.js.map +1 -1
  54. package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js +6 -4
  55. package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js.map +1 -1
  56. package/dist/kadaikodi/pages/customer/FavoritesPage.js +6 -6
  57. package/dist/kadaikodi/pages/customer/FavoritesPage.js.map +1 -1
  58. package/dist/kadaikodi/pages/customer/OrderHistoryPage.js +4 -4
  59. package/dist/kadaikodi/pages/customer/OrderHistoryPage.js.map +1 -1
  60. package/dist/kadaikodi/pages/customer/OrderTrackingPage.js +409 -304
  61. package/dist/kadaikodi/pages/customer/OrderTrackingPage.js.map +1 -1
  62. package/dist/kadaikodi/pages/customer/ReviewsPage.js +209 -162
  63. package/dist/kadaikodi/pages/customer/ReviewsPage.js.map +1 -1
  64. package/dist/kadaikodi/pages/customer/SavedAddressesPage.js.map +1 -1
  65. package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js.map +1 -1
  66. package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js.map +1 -1
  67. package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.js.map +1 -1
  68. package/dist/kadaikodi/pages/investor/InvestorProfilePage.js +441 -514
  69. package/dist/kadaikodi/pages/investor/InvestorProfilePage.js.map +1 -1
  70. package/dist/kadaikodi/pages/worker/TaskDetailsPage.js +207 -186
  71. package/dist/kadaikodi/pages/worker/TaskDetailsPage.js.map +1 -1
  72. package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js.map +1 -1
  73. package/dist/kadaikodi/pages/worker/WorkerProfilePage.js +340 -272
  74. package/dist/kadaikodi/pages/worker/WorkerProfilePage.js.map +1 -1
  75. package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js +122 -75
  76. package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js.map +1 -1
  77. 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(\n (o) => o.status === 'pending' || o.status === 'confirmed'\n ).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 = 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 categoryRows = useMemo(() => {\n const rows = analytics?.revenueByCategory ?? [];\n const total = rows.reduce((sum, r) => sum + r.revenue, 0);\n return rows.map((r) => ({ ...r, percentage: total > 0 ? (r.revenue / total) * 100 : 0 }));\n }, [analytics]);\n\n const topCarts = analytics?.topProviders ?? [];\n const customerGrowth = analytics?.customerGrowth ?? [];\n const categoryDistribution = analytics?.categoryDistribution ?? [];\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&apos;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.toLocaleString('en-IN')}\n label=\"Total Orders\"\n />\n <MetricsCard\n icon={<Users className=\"h-5 w-5\" />}\n value={stats.activeCustomers.toLocaleString('en-IN')}\n label=\"Active Customers\"\n />\n <MetricsCard\n icon={<Store className=\"h-5 w-5\" />}\n value={stats.activeProviders.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\">Top Performing Carts</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-right text-xs font-medium text-text-secondary uppercase\">\n Revenue\n </th>\n <th className=\"px-4 py-3 text-right text-xs font-medium text-text-secondary uppercase\">\n Orders\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-right font-medium text-text-primary\">\n {fmtCur(cart.revenue)}\n </td>\n <td className=\"px-4 py-3 text-sm text-right text-text-primary\">\n {cart.orders.toLocaleString('en-IN')}\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.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.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 <div>\n <h3 className=\"text-lg font-semibold text-text-primary mb-4\">Revenue by Category</h3>\n {categoryRows.length > 0 ? (\n <div className=\"space-y-3\">\n {categoryRows.map((row, i) => (\n <div\n key={row.category}\n className=\"flex items-center justify-between p-4 rounded-lg border border-border-subtle bg-bg-sunken/30\"\n >\n <div className=\"flex items-center gap-3\">\n {medalIcon(i)}\n <div>\n <p className=\"font-medium text-text-primary capitalize\">\n {row.category}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {row.orders.toLocaleString('en-IN')} orders\n </p>\n </div>\n </div>\n <div className=\"text-right\">\n <p className=\"font-bold text-text-primary\">{fmtCur(row.revenue)}</p>\n <p className=\"text-sm text-text-secondary\">\n {row.percentage.toFixed(1)}%\n </p>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Category revenue will appear here once orders are recorded.\n </p>\n )}\n </div>\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.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.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 <h3 className=\"text-lg font-semibold text-text-primary mb-4\">Customer Growth</h3>\n {customerGrowth.length > 0 ? (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b border-border-subtle\">\n <th className=\"px-4 py-2 text-left text-xs font-medium text-text-secondary uppercase\">\n Month\n </th>\n <th className=\"px-4 py-2 text-right text-xs font-medium text-text-secondary uppercase\">\n New Customers\n </th>\n <th className=\"px-4 py-2 text-right text-xs font-medium text-text-secondary uppercase\">\n Total Customers\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {customerGrowth.map((row) => (\n <tr key={row.month}>\n <td className=\"px-4 py-2 text-sm font-medium text-text-primary\">\n {row.month}\n </td>\n <td className=\"px-4 py-2 text-sm text-right text-text-primary\">\n +{row.newCustomers.toLocaleString('en-IN')}\n </td>\n <td className=\"px-4 py-2 text-sm text-right text-text-primary\">\n {row.totalCustomers.toLocaleString('en-IN')}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Customer growth trends will appear here as your customer base builds up.\n </p>\n )}\n </div>\n\n {categoryDistribution.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 {categoryDistribution.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 {row.category}\n </span>\n <span className=\"text-sm text-text-secondary\">\n {row.count.toLocaleString('en-IN')} ({row.percentage.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\">Today&apos;s Activity</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.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, 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&apos;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&apos;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":";;;;;;;;;;;AAgDA,SAAgB,IAAqB;CACnC,IAAM,EAAE,kBAAe,GAAc,EAE/B,EAAE,MAAM,GAAO,WAAW,MAAiB,GAAmB,EAC9D,EAAE,MAAM,GAAW,WAAW,MAAqB,GAAmB,EACtE,EAAE,MAAM,IAAY,EAAE,EAAE,WAAW,MAAqB,GAAc,EACtE,EAAE,MAAM,IAAS,EAAE,EAAE,WAAW,MAAkB,EAAU,EAAE,CAAC,EAE/D,CAAC,GAAW,KAAgB,EAAiB,WAAW,EAExD,IAAU,KAAgB,KAAoB,KAAoB,GAElE,KAAU,MACV,KAAU,MAAiB,KAAK,IAAS,KAAU,QAAQ,EAAE,CAAC,MAC9D,KAAU,MAAe,KAAK,IAAS,KAAQ,QAAQ,EAAE,CAAC,KACvD,EAAe,GAAQ,EAAE,uBAAuB,GAAG,CAAC,EAIvD,IAAa,QAAc;EAC/B,IAAM,IAAQ,EAAO,QACf,IAAY,EAAO,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC,QAC3D,IAAY,EAAO,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC,QAC3D,IAAU,EAAO,QAAQ,MAAM,EAAE,WAAW,aAAa,EAAE,WAAW,YAAY,CAAC,QACnF,oBAAe,IAAI,MAAM;AAO/B,SANA,EAAa,SAAS,GAAG,GAAG,GAAG,EAAE,EAM1B;GAAE;GAAO;GAAW;GAAW;GAAS,aAL3B,EAAO,QACxB,MAAM,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,IAAI,EAAa,SAAS,CACjE,CAAC;GAG0D,eAD1D,KAAS,EAAM,cAAc,IAAI,EAAM,eAAe,EAAM,cAAc;GACD;IAC1E,CAAC,GAAQ,EAAM,CAAC,EAEb,IAAe,QAAc,EAAU,QAAQ,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAU,CAAC,EAEpF,IAAW,GAAW,gBAAgB,EAAE,EACxC,IAAgB,GAAW,gBAAgB,aAAa,GAIxD,IAAmB,QAAc;EACrC,IAAM,IAAU,OAAO,QAAQ,GAAW,wBAAwB,EAAE,CAAC,EAC/D,IAAQ,EAAQ,QAAQ,GAAK,GAAG,OAAW,IAAM,GAAO,EAAE;AAChE,SAAO,EACJ,KAAK,CAAC,GAAU,QAAY;GAC3B;GACA;GACA,YAAY,IAAQ,IAAK,IAAQ,IAAS,MAAM;GACjD,EAAE,CACF,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;IACnC,CAAC,EAAU,CAAC,EAET,KAAkB,MAAc,EAAE,QAAQ,MAAM,IAAI,CAAC,aAAa,EAElE,KAAO,GAAc,MAAmB,IAAQ,IAAK,IAAO,IAAS,MAAM,GAE3E,KAAa,MACb,IAAQ,IAAU,kBAAC,GAAD,EAAO,WAAU,oCAAqC,CAAA,GACrE,kBAAC,GAAD,EAAW,WAAU,+BAAgC,CAAA;AAG9D,KAAI,KAAW,CAAC,EACd,QACE,kBAAC,GAAD;EAAY,OAAM;EAAqB,aAAY;YACjD,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD,EAAS,WAAU,mDAAoD,CAAA,EACvE,kBAAC,KAAD;IAAG,WAAU;cAAsB;IAAwB,CAAA,CACvD;;EACK,CAAA;CAIjB,IAAM,IAAsE;EAC1E;GAAE,KAAK;GAAY,OAAO;GAAY,MAAM;GAAW;EACvD;GAAE,KAAK;GAAW,OAAO;GAAW,MAAM;GAAa;EACvD;GAAE,KAAK;GAAS,OAAO;GAAS,MAAM;GAAO;EAC7C;GAAE,KAAK;GAAe,OAAO;GAAe,MAAM;GAAK;EACxD;AAED,QACE,kBAAC,GAAD;EAAY,OAAM;EAAqB,aAAY;YAAnD;GACE,kBAAC,GAAD;IAAa,WAAU;cAAO;IAKhB,CAAA;GAEd,kBAAC,GAAD;IACE,YAAW;IACX,WAAU;IACV,OAAO;KACL;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,eAAe,EAAa,WAAW;MACxC;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,eAAe,EAAa,UAAU;MACvC;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa;MACb,eAAe,EAAW,eAAe;MACzC,MAAM,MAAiB;MACxB;KACF;IACD,CAAA;GAEF,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,QAAD;KAAM,WAAU;eAAhB,CAA8C,mCAC7B,IAAI,MAAM,EAAC,eAAe,QAAQ,CAC5C;;IACH,CAAA;GAGN,kBAAC,GAAD;IAAe,WAAU;cAAzB,CACE,kBAAC,MAAD;KAAI,WAAU;eAA+C;KAAgB,CAAA,EAC7E,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD;OACE,UAAA;OACA,MAAM,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA;OACzC,OAAO,EAAO,EAAM,aAAa;OACjC,OAAM;OACN,CAAA;MACF,kBAAC,GAAD;OACE,MAAM,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA;OACzC,QAAQ,EAAM,eAAe,GAAG,eAAe,QAAQ;OACvD,OAAM;OACN,CAAA;MACF,kBAAC,GAAD;OACE,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;OACnC,QAAQ,EAAM,mBAAmB,GAAG,eAAe,QAAQ;OAC3D,OAAM;OACN,CAAA;MACF,kBAAC,GAAD;OACE,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;OACnC,QAAQ,EAAM,mBAAmB,GAAG,eAAe,QAAQ;OAC3D,OAAM;OACN,YAAY,GAAG,EAAa;OAC5B,CAAA;MACE;OACQ;;GAGhB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAK,KAAK,MAAQ;OACjB,IAAM,IAAU,EAAI;AACpB,cACE,kBAAC,UAAD;QAEE,MAAK;QACL,eAAe,EAAa,EAAI,IAAI;QACpC,WAAW,EACT,gHACA,MAAc,EAAI,MACd,gCACA,iEACL;kBATH,CAWE,kBAAC,GAAD,EAAS,WAAU,WAAY,CAAA,EAC/B,kBAAC,QAAD;SAAM,WAAU;mBAAoB,EAAI;SAAa,CAAA,CAC9C;UAZF,EAAI,IAYF;QAEX;MACE,CAAA;KACF,CAAA,EAEN,kBAAC,OAAD;KAAK,WAAU;eAAf;MAEG,MAAc,cACb,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;QAAI,WAAU;kBAA+C;QAExD,CAAA,EACJ,EAAW,QAAQ,IAClB,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACE,kBAAC,KAAD;YAAG,WAAU;sBAAmC;YAAoB,CAAA;WACpE,kBAAC,KAAD;YAAG,WAAU;sBACV,EAAW,UAAU,eAAe,QAAQ;YAC3C,CAAA;WACJ,kBAAC,KAAD;YAAG,WAAU;sBAAb,CACG,EAAI,EAAW,WAAW,EAAW,MAAM,CAAC,QAAQ,EAAE,EAAC,aACtD;;WACA;;SACN,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACE,kBAAC,KAAD;YAAG,WAAU;sBAAmC;YAAkB,CAAA;WAClE,kBAAC,KAAD;YAAG,WAAU;sBACV,EAAW,QAAQ,eAAe,QAAQ;YACzC,CAAA;WACJ,kBAAC,KAAD;YAAG,WAAU;sBAAb,CACG,EAAI,EAAW,SAAS,EAAW,MAAM,CAAC,QAAQ,EAAE,EAAC,aACpD;;WACA;;SACN,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACE,kBAAC,KAAD;YAAG,WAAU;sBAAiC;YAAoB,CAAA;WAClE,kBAAC,KAAD;YAAG,WAAU;sBACV,EAAW,UAAU,eAAe,QAAQ;YAC3C,CAAA;WACJ,kBAAC,KAAD;YAAG,WAAU;sBAAb,CACG,EAAI,EAAW,WAAW,EAAW,MAAM,CAAC,QAAQ,EAAE,EAAC,aACtD;;WACA;;SACF;YAEN,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAEvC,CAAA,CAEF,EAAA,CAAA,EAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;QAAI,WAAU;kBAA+C;QAExD,CAAA,EACJ,EAAS,SAAS,IACjB,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,SAAD;SAAO,WAAU;mBAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;UAAI,WAAU;oBAAd;WACE,kBAAC,MAAD;YAAI,WAAU;sBAAwE;YAEjF,CAAA;WACL,kBAAC,MAAD;YAAI,WAAU;sBAAwE;YAEjF,CAAA;WACL,kBAAC,MAAD;YAAI,WAAU;sBAAyE;YAElF,CAAA;WACF;aACC,CAAA,EACR,kBAAC,SAAD;UAAO,WAAU;oBACd,EAAS,KAAK,GAAM,MACnB,kBAAC,MAAD;WAAkB,WAAU;qBAA5B;YACE,kBAAC,MAAD;aAAI,WAAU;uBACZ,kBAAC,OAAD;cAAK,WAAU;wBAAf,CACG,EAAU,EAAE,EACb,kBAAC,QAAD;eAAM,WAAU;yBACb,EAAK;eACD,CAAA,CACH;;aACH,CAAA;YACL,kBAAC,MAAD;aAAI,WAAU;uBACX,EAAe,EAAK,SAAS;aAC3B,CAAA;YACL,kBAAC,MAAD;aAAI,WAAU;uBACZ,kBAAC,QAAD;cAAM,WAAU;wBAAhB,CACE,kBAAC,GAAD,EAAM,WAAU,iEAAkE,CAAA,GAChF,EAAK,UAAU,GAAG,QAAQ,EAAE,CACzB;;aACJ,CAAA;YACF;aAlBI,EAAK,GAkBT,CACL;UACI,CAAA,CACF;;QACJ,CAAA,GAEN,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAEvC,CAAA,CAEF,EAAA,CAAA,CACF;;MAIP,MAAc,aACb,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,MAAD;WAAI,WAAU;qBAA6C;WAAkB,CAAA,EAC7E,kBAAC,KAAD;WAAG,WAAU;qBACV,EAAO,EAAM,aAAa;WACzB,CAAA,CACA;;SACN,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,MAAD;WAAI,WAAU;qBAA+C;WAAiB,CAAA,EAC9E,kBAAC,KAAD;WAAG,WAAU;sBACT,EAAM,eAAe,GAAG,eAAe,QAAQ;WAC/C,CAAA,CACA;;SACN,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,MAAD;WAAI,WAAU;qBAAoD;WAE7D,CAAA,EACL,kBAAC,KAAD;WAAG,WAAU;qBACV,EAAO,EAAW,cAAc;WAC/B,CAAA,CACA;;SACF;WAEN,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAGvC,CAAA,CACA;;MAIP,MAAc,WACb,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,OAAD;WAAK,WAAU;qBAAf,CACE,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,EACjD,kBAAC,MAAD;YAAI,WAAU;sBAA0C;YAAqB,CAAA,CACzE;cACN,kBAAC,KAAD;WAAG,WAAU;sBACT,EAAM,mBAAmB,GAAG,eAAe,QAAQ;WACnD,CAAA,CACA;aACN,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,OAAD;WAAK,WAAU;qBAAf,CACE,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,EACjD,kBAAC,MAAD;YAAI,WAAU;sBAA0C;YAAuB,CAAA,CAC3E;cACN,kBAAC,KAAD;WAAG,WAAU;sBACT,EAAM,mBAAmB,GAAG,eAAe,QAAQ;WACnD,CAAA,CACA;YACF;;QAEN,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,OAAD;WAAK,WAAU;qBAAf,CACE,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,EACjD,kBAAC,MAAD;YAAI,WAAU;sBAA0C;YAAoB,CAAA,CACxE;;UACN,kBAAC,KAAD;WAAG,WAAU;qBACV,EAAc,eAAe,QAAQ;WACpC,CAAA;UACJ,kBAAC,KAAD;WAAG,WAAU;qBAAmC;WAE5C,CAAA;UACA;;QAEL,EAAiB,SAAS,KACzB,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBAA+C;SAExD,CAAA,EACL,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAiB,KAAK,MACrB,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAe,EAAI,SAAS;WACxB,CAAA,EACP,kBAAC,QAAD;WAAM,WAAU;qBAAhB;aACI,EAAI,SAAS,GAAG,eAAe,QAAQ;YAAC;aACxC,EAAI,cAAc,GAAG,QAAQ,EAAE;YAAC;YAC7B;aACH;aACN,kBAAC,OAAD;UAAK,WAAU;oBACb,kBAAC,OAAD;WACE,WAAU;WACV,OAAO,EAAE,OAAO,GAAG,EAAI,WAAW,IAAI;WACtC,CAAA;UACE,CAAA,CACF,EAAA,EAhBI,EAAI,SAgBR,CACN;SACE,CAAA,CACF,EAAA,CAAA;QAEJ;;MAIP,MAAc,iBACb,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACE,kBAAC,OAAD;YAAK,WAAU;sBAAf,CACE,kBAAC,GAAD,EAAM,WAAU,+BAAgC,CAAA,EAChD,kBAAC,MAAD;aAAI,WAAU;uBAA0C;aAEnD,CAAA,CACD;;WACN,kBAAC,KAAD;YAAG,WAAU;sBAAb,CACE,kBAAC,GAAD,EAAM,WAAU,6DAA8D,CAAA,EAC7E,EAAM,YAAY,IAAI,EAAM,UAAU,QAAQ,EAAE,GAAG,IAClD;;WACJ,kBAAC,KAAD;YAAG,WAAU;sBAAmC;YAA+B,CAAA;WAC3E;;SACN,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACE,kBAAC,OAAD;YAAK,WAAU;sBAAf,CACE,kBAAC,GAAD,EAAY,WAAU,+BAAgC,CAAA,EACtD,kBAAC,MAAD;aAAI,WAAU;uBAA0C;aAAoB,CAAA,CACxE;;WACN,kBAAC,KAAD;YAAG,WAAU;sBACV,EAAW,QAAQ,IAChB,GAAG,EAAI,EAAW,WAAW,EAAW,MAAM,CAAC,QAAQ,EAAE,CAAC,KAC1D;YACF,CAAA;WACJ,kBAAC,KAAD;YAAG,WAAU;sBAAmC;YAAoB,CAAA;WAChE;;SACN,kBAAC,OAAD;UAAK,WAAU;oBAAf;WACE,kBAAC,OAAD;YAAK,WAAU;sBAAf,CACE,kBAAC,GAAD,EAAW,WAAU,+BAAgC,CAAA,EACrD,kBAAC,MAAD;aAAI,WAAU;uBAA0C;aAAsB,CAAA,CAC1E;;WACN,kBAAC,KAAD;YAAG,WAAU;sBACV,EAAW,QAAQ,IAChB,GAAG,EAAI,EAAW,WAAW,EAAW,MAAM,CAAC,QAAQ,EAAE,CAAC,KAC1D;YACF,CAAA;WACJ,kBAAC,KAAD;YAAG,WAAU;sBAAmC;YAAoB,CAAA;WAChE;;SACF;WAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBAA+C;SAExD,CAAA,EACL,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;UAAG,WAAU;oBAAmC;UAAgB,CAAA,EAChE,kBAAC,KAAD;UAAG,WAAU;oBACV,EAAW,YAAY,eAAe,QAAQ;UAC7C,CAAA,CACA,EAAA,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;UAAG,WAAU;oBAAmC;UAAkB,CAAA,EAClE,kBAAC,KAAD;UAAG,WAAU;qBACT,EAAM,iBAAiB,GAAG,eAAe,QAAQ;UACjD,CAAA,CACA,EAAA,CAAA,CACF;WACF;UACF;;MAEJ;OACF;;GACK"}
@@ -11,7 +11,7 @@ import { jsx as T, jsxs as E } from "react/jsx-runtime";
11
11
  import { CTAOverflowMenu as D, EmphasisPanel as O, NextSteps as k, PagePurpose as A } from "@burdenoff/fe-libs/ui";
12
12
  //#region src/kadaikodi/pages/admin/AdminDashboard.tsx
13
13
  function j() {
14
- let { navigateTo: j, currentUser: M } = e(), N = M?.firstName ?? M?.name ?? "Admin", { data: P, isLoading: F } = o(), { data: I = [], isLoading: L } = c(), { data: R = [], isLoading: z } = s({}), { data: B } = a(), V = F || L || z, H = (e) => l(e, { minimumFractionDigits: 0 }), U = d(() => I.filter((e) => !e.isOpen).length, [I]), W = d(() => [...R].sort((e, t) => new Date(t.orderDate).getTime() - new Date(e.orderDate).getTime()).slice(0, 6), [R]), G = (e) => e === "delivered" ? "bg-status-success-bg-subtle text-status-success-text" : e === "cancelled" ? "bg-status-error-bg-subtle text-status-error-text" : "bg-status-warning-bg-subtle text-status-warning-text";
14
+ let { navigateTo: j, currentUser: M } = e(), N = M?.firstName ?? M?.name ?? "Admin", { data: P, isLoading: F } = o(), { data: I = [], isLoading: L } = c(), { data: R = [], isLoading: z } = s({}), { data: B } = a(), V = F || L || z, H = (e) => l(e, { minimumFractionDigits: 0 }), U = d(() => I.filter((e) => !e.isOpen).length, [I]), W = d(() => [...R].sort((e, t) => new Date(t.orderDate).getTime() - new Date(e.orderDate).getTime()).slice(0, 6), [R]), G = (e) => e.replace(/_/g, " ").toLowerCase(), K = B?.topProviders ?? [], q = Object.entries(B?.categoryDistribution ?? {}).sort((e, t) => t[1] - e[1]), J = (e) => e === "delivered" ? "bg-status-success-bg-subtle text-status-success-text" : e === "cancelled" ? "bg-status-error-bg-subtle text-status-error-text" : "bg-status-warning-bg-subtle text-status-warning-text";
15
15
  return V ? /* @__PURE__ */ T(n, {
16
16
  title: "Admin Dashboard",
17
17
  description: "Loading...",
@@ -130,17 +130,17 @@ function j() {
130
130
  children: [
131
131
  /* @__PURE__ */ T(r, {
132
132
  icon: /* @__PURE__ */ T(w, { className: "h-5 w-5" }),
133
- value: P.activeCustomers.toLocaleString("en-IN"),
133
+ value: (P.activeCustomers ?? 0).toLocaleString("en-IN"),
134
134
  label: "Active Customers"
135
135
  }),
136
136
  /* @__PURE__ */ T(r, {
137
137
  icon: /* @__PURE__ */ T(C, { className: "h-5 w-5" }),
138
- value: P.activeProviders.toLocaleString("en-IN"),
138
+ value: (P.activeProviders ?? 0).toLocaleString("en-IN"),
139
139
  label: "Active Carts"
140
140
  }),
141
141
  /* @__PURE__ */ T(r, {
142
142
  icon: /* @__PURE__ */ T(x, { className: "h-5 w-5" }),
143
- value: P.totalOrders.toLocaleString("en-IN"),
143
+ value: (P.totalOrders ?? 0).toLocaleString("en-IN"),
144
144
  label: "Total Orders"
145
145
  }),
146
146
  /* @__PURE__ */ T(r, {
@@ -181,7 +181,7 @@ function j() {
181
181
  children: "Pending Orders"
182
182
  }), /* @__PURE__ */ T("p", {
183
183
  className: "text-xl font-bold text-status-warning-text",
184
- children: P.pendingOrders.toLocaleString("en-IN")
184
+ children: (P.pendingOrders ?? 0).toLocaleString("en-IN")
185
185
  })]
186
186
  }),
187
187
  /* @__PURE__ */ E("div", {
@@ -226,14 +226,14 @@ function j() {
226
226
  className: "text-sm font-medium text-text-primary",
227
227
  children: ["Order from ", e.cartName]
228
228
  }), /* @__PURE__ */ T("span", {
229
- className: t("inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium capitalize w-fit", G(e.status)),
229
+ className: t("inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium capitalize w-fit", J(e.status)),
230
230
  children: e.status.replace(/_/g, " ")
231
231
  })]
232
232
  }), /* @__PURE__ */ E("div", {
233
233
  className: "flex flex-wrap items-center mt-1 text-xs text-text-secondary gap-3",
234
234
  children: [/* @__PURE__ */ T("span", { children: u(e.orderDate) }), /* @__PURE__ */ E("span", {
235
235
  className: "flex items-center gap-1",
236
- children: [/* @__PURE__ */ T(v, { className: "h-3 w-3" }), e.total.toLocaleString("en-IN")]
236
+ children: [/* @__PURE__ */ T(v, { className: "h-3 w-3" }), (e.total ?? 0).toLocaleString("en-IN")]
237
237
  })]
238
238
  })]
239
239
  })]
@@ -252,26 +252,30 @@ function j() {
252
252
  className: "flex items-center gap-2 mb-4",
253
253
  children: [/* @__PURE__ */ T(g, { className: "h-5 w-5 text-text-secondary" }), /* @__PURE__ */ T("h3", {
254
254
  className: "text-lg font-semibold text-text-primary",
255
- children: "Revenue by Category"
255
+ children: "Carts by Category"
256
256
  })]
257
- }), B && B.revenueByCategory.length > 0 ? /* @__PURE__ */ T("div", {
257
+ }), q.length > 0 ? /* @__PURE__ */ T("div", {
258
258
  className: "space-y-3",
259
- children: B.revenueByCategory.map((e) => /* @__PURE__ */ E("div", {
259
+ children: q.map(([e, t]) => /* @__PURE__ */ E("div", {
260
260
  className: "flex items-center justify-between rounded-lg bg-bg-sunken/50 p-3",
261
- children: [/* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T("p", {
261
+ children: [/* @__PURE__ */ T("p", {
262
262
  className: "text-sm font-medium text-text-primary capitalize",
263
- children: e.category
263
+ children: G(e)
264
264
  }), /* @__PURE__ */ E("p", {
265
- className: "text-xs text-text-secondary",
266
- children: [e.orders.toLocaleString("en-IN"), " orders"]
267
- })] }), /* @__PURE__ */ T("p", {
268
265
  className: "text-sm font-semibold text-text-primary",
269
- children: H(e.revenue)
266
+ children: [
267
+ (t ?? 0).toLocaleString("en-IN"),
268
+ " ",
269
+ /* @__PURE__ */ T("span", {
270
+ className: "text-xs font-normal text-text-secondary",
271
+ children: t === 1 ? "cart" : "carts"
272
+ })
273
+ ]
270
274
  })]
271
- }, e.category))
275
+ }, e))
272
276
  }) : /* @__PURE__ */ T("p", {
273
277
  className: "text-sm text-text-secondary",
274
- children: "Category revenue will appear here once orders are recorded."
278
+ children: "Cart categories will appear here as carts are onboarded."
275
279
  })]
276
280
  }), /* @__PURE__ */ E("div", {
277
281
  className: "rounded-lg border border-border-subtle bg-bg-surface p-6",
@@ -281,25 +285,19 @@ function j() {
281
285
  className: "text-lg font-semibold text-text-primary",
282
286
  children: "Top Carts"
283
287
  })]
284
- }), B && B.topProviders.length > 0 ? /* @__PURE__ */ T("div", {
288
+ }), K.length > 0 ? /* @__PURE__ */ T("div", {
285
289
  className: "space-y-3",
286
- children: B.topProviders.map((e) => /* @__PURE__ */ E("div", {
290
+ children: K.map((e) => /* @__PURE__ */ E("div", {
287
291
  className: "flex items-center justify-between rounded-lg bg-bg-sunken/50 p-3",
288
292
  children: [/* @__PURE__ */ E("div", { children: [/* @__PURE__ */ T("p", {
289
293
  className: "text-sm font-medium text-text-primary",
290
294
  children: e.name
291
- }), /* @__PURE__ */ E("p", {
292
- className: "text-xs text-text-secondary flex items-center gap-1",
293
- children: [
294
- /* @__PURE__ */ T(S, { className: "h-3 w-3 fill-status-warning-text text-status-warning-text" }),
295
- e.rating.toFixed(1),
296
- " · ",
297
- e.orders.toLocaleString("en-IN"),
298
- " orders"
299
- ]
300
- })] }), /* @__PURE__ */ T("p", {
301
- className: "text-sm font-semibold text-text-primary",
302
- children: H(e.revenue)
295
+ }), /* @__PURE__ */ T("p", {
296
+ className: "text-xs text-text-secondary capitalize",
297
+ children: G(e.category)
298
+ })] }), /* @__PURE__ */ E("p", {
299
+ className: "text-sm font-semibold text-text-primary flex items-center gap-1",
300
+ children: [/* @__PURE__ */ T(S, { className: "h-3.5 w-3.5 fill-status-warning-text text-status-warning-text" }), (e.rating ?? 0).toFixed(1)]
303
301
  })]
304
302
  }, e.id))
305
303
  }) : /* @__PURE__ */ T("p", {
@@ -1 +1 @@
1
- {"version":3,"file":"AdminDashboard.js","names":[],"sources":["../../../../src/kadaikodi/pages/admin/AdminDashboard.tsx"],"sourcesContent":["/**\n * Admin Dashboard Page\n * @module kadaikodi/pages/admin\n *\n * Platform control room wired to the live Kadaikodi backend. Every stat,\n * activity row and breakdown is derived from real hook data\n * (useDashboardStats + useProviders + useOrders + useAdminAnalytics).\n * Where a metric has no honest backend source it is omitted rather than faked.\n */\n\nimport { useMemo } from 'react';\nimport {\n Users,\n Store,\n ShoppingBag,\n IndianRupee,\n Activity,\n ArrowRight,\n Star,\n Settings,\n BarChart3,\n Award,\n FileText,\n AlertTriangle,\n Loader2,\n} from 'lucide-react';\nimport { CTAOverflowMenu, EmphasisPanel, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { MetricsCard } from '../../components/MetricsCard';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport {\n useDashboardStats,\n useProviders,\n useOrders,\n useAdminAnalytics,\n} from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency, formatRelativeTime } from '../../utils/formatters';\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function AdminDashboard() {\n const { navigateTo, currentUser } = useKadaikodi();\n const firstName = currentUser?.firstName ?? currentUser?.name ?? 'Admin';\n\n const { data: stats, isLoading: statsLoading } = useDashboardStats();\n const { data: providers = [], isLoading: providersLoading } = useProviders();\n const { data: orders = [], isLoading: ordersLoading } = useOrders({});\n const { data: analytics } = useAdminAnalytics();\n\n const isLoading = statsLoading || providersLoading || ordersLoading;\n\n const fmtCur = (amount: number) => formatCurrency(amount, { minimumFractionDigits: 0 });\n\n // Carts awaiting activation/verification — real derivation from provider status.\n const pendingCarts = useMemo(() => providers.filter((p) => !p.isOpen).length, [providers]);\n\n // Most recent orders across the platform → honest \"recent activity\" feed.\n const recentOrders = useMemo(\n () =>\n [...orders]\n .sort((a, b) => new Date(b.orderDate).getTime() - new Date(a.orderDate).getTime())\n .slice(0, 6),\n [orders]\n );\n\n const orderStatusBadge = (status: string) => {\n if (status === 'delivered') return 'bg-status-success-bg-subtle text-status-success-text';\n if (status === 'cancelled') return 'bg-status-error-bg-subtle text-status-error-text';\n return 'bg-status-warning-bg-subtle text-status-warning-text';\n };\n\n /* ---- Loading state ---- */\n if (isLoading) {\n return (\n <PageLayout title=\"Admin Dashboard\" description=\"Loading...\">\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 admin dashboard...</p>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Admin Dashboard\"\n description={`Welcome, ${firstName}! Monitor and manage the platform.`}\n actions={\n pendingCarts > 0 ? (\n <div className=\"flex items-center gap-2 rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-3 py-2\">\n <AlertTriangle className=\"h-4 w-4 text-status-error-text\" />\n <span className=\"text-sm font-medium text-status-error-text\">\n {pendingCarts} carts awaiting review\n </span>\n </div>\n ) : undefined\n }\n >\n <PagePurpose className=\"mb-6\">\n The control room for the whole Kadaikodi marketplace — approve new carts, keep an eye on\n users, orders and platform revenue, and act on anything that needs attention. Clear pending\n approvals first, then review platform health below.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"kadaikodi-admin-dashboard\"\n className=\"mb-6\"\n steps={[\n {\n id: 'approvals',\n label: 'Review pending cart approvals',\n description: 'Vet and approve new carts waiting to go live.',\n onClick: () => navigateTo('/admin/carts'),\n done: pendingCarts === 0,\n },\n {\n id: 'users',\n label: 'Manage users',\n description: 'Review accounts, roles and access across the platform.',\n onClick: () => navigateTo('/admin/users'),\n },\n {\n id: 'financial',\n label: 'Check financial health',\n description: 'Track revenue, commission and payouts.',\n onClick: () => navigateTo('/admin/financial'),\n },\n ]}\n />\n\n {/* Hero — the one emphasis zone: pending approvals + primary action + overflow */}\n <EmphasisPanel className=\"mb-8\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Quick Actions</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {pendingCarts > 0\n ? `${pendingCarts} carts awaiting your review.`\n : 'All caught up — nothing pending review.'}\n </p>\n </div>\n <CTAOverflowMenu\n primary={{\n label: `Review Carts${pendingCarts > 0 ? ` (${pendingCarts})` : ''}`,\n icon: <Store className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/carts'),\n }}\n actions={[\n {\n label: 'Manage Carts',\n icon: <Store className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/carts'),\n },\n {\n label: 'User Management',\n icon: <Users className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/users'),\n },\n {\n label: 'Order Management',\n icon: <ShoppingBag className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/orders'),\n },\n {\n label: 'Financial Analytics',\n icon: <IndianRupee className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/financial'),\n },\n {\n label: 'Analytics',\n icon: <BarChart3 className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/analytics'),\n },\n {\n label: 'Settings',\n icon: <Settings className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/settings'),\n },\n {\n label: 'Reports',\n icon: <FileText className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/analytics'),\n },\n ]}\n />\n </div>\n </EmphasisPanel>\n\n {/* Platform Overview — real dashboard stats */}\n {stats && (\n <div className=\"mb-8\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">Platform Overview</h2>\n <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-4\">\n <MetricsCard\n icon={<Users className=\"h-5 w-5\" />}\n value={stats.activeCustomers.toLocaleString('en-IN')}\n label=\"Active Customers\"\n />\n <MetricsCard\n icon={<Store className=\"h-5 w-5\" />}\n value={stats.activeProviders.toLocaleString('en-IN')}\n label=\"Active Carts\"\n />\n <MetricsCard\n icon={<ShoppingBag className=\"h-5 w-5\" />}\n value={stats.totalOrders.toLocaleString('en-IN')}\n label=\"Total Orders\"\n />\n <MetricsCard\n featured\n icon={<IndianRupee className=\"h-5 w-5\" />}\n value={fmtCur(stats.totalRevenue)}\n label=\"Total Revenue\"\n />\n </div>\n\n <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-4 mt-4\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <p className=\"text-xs text-text-secondary\">Total Carts</p>\n <p className=\"text-xl font-bold text-text-primary\">\n {providers.length.toLocaleString('en-IN')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <p className=\"text-xs text-text-secondary\">Pending Cart Approvals</p>\n <p className=\"text-xl font-bold text-status-error-text\">\n {pendingCarts.toLocaleString('en-IN')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <p className=\"text-xs text-text-secondary\">Pending Orders</p>\n <p className=\"text-xl font-bold text-status-warning-text\">\n {stats.pendingOrders.toLocaleString('en-IN')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <p className=\"text-xs text-text-secondary\">Average Rating</p>\n <p className=\"text-xl font-bold text-text-primary flex items-center gap-1\">\n <Star className=\"h-4 w-4 fill-status-warning-text text-status-warning-text\" />\n {stats.avgRating > 0 ? stats.avgRating.toFixed(1) : '—'}\n </p>\n </div>\n </div>\n </div>\n )}\n\n {/* Recent Activity — real recent orders */}\n <div className=\"mb-8\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Recent Orders</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/admin/orders')}\n className=\"flex items-center gap-1 text-sm font-medium text-text-secondary hover:text-text-primary transition-colors\"\n >\n View all orders\n <ArrowRight className=\"h-4 w-4\" />\n </button>\n </div>\n {recentOrders.length > 0 ? (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface divide-y divide-border\">\n {recentOrders.map((order) => (\n <div key={order.id} className=\"flex items-start gap-3 px-4 py-3\">\n <div className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-sunken mt-0.5 text-text-secondary\">\n <ShoppingBag className=\"h-4 w-4\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">\n Order from {order.cartName}\n </p>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium capitalize w-fit',\n orderStatusBadge(order.status)\n )}\n >\n {order.status.replace(/_/g, ' ')}\n </span>\n </div>\n <div className=\"flex flex-wrap items-center mt-1 text-xs text-text-secondary gap-3\">\n <span>{formatRelativeTime(order.orderDate)}</span>\n <span className=\"flex items-center gap-1\">\n <IndianRupee className=\"h-3 w-3\" />\n {order.total.toLocaleString('en-IN')}\n </span>\n </div>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No orders yet\"\n description=\"Orders placed across the platform will appear here as they come in.\"\n />\n )}\n </div>\n\n {/* Revenue by Category & Top Carts — real admin analytics */}\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 mb-4\">\n <BarChart3 className=\"h-5 w-5 text-text-secondary\" />\n <h3 className=\"text-lg font-semibold text-text-primary\">Revenue by Category</h3>\n </div>\n {analytics && analytics.revenueByCategory.length > 0 ? (\n <div className=\"space-y-3\">\n {analytics.revenueByCategory.map((row) => (\n <div\n key={row.category}\n className=\"flex items-center justify-between rounded-lg bg-bg-sunken/50 p-3\"\n >\n <div>\n <p className=\"text-sm font-medium text-text-primary capitalize\">\n {row.category}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {row.orders.toLocaleString('en-IN')} orders\n </p>\n </div>\n <p className=\"text-sm font-semibold text-text-primary\">{fmtCur(row.revenue)}</p>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Category revenue will appear here once orders are recorded.\n </p>\n )}\n </div>\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 mb-4\">\n <Award className=\"h-5 w-5 text-text-secondary\" />\n <h3 className=\"text-lg font-semibold text-text-primary\">Top Carts</h3>\n </div>\n {analytics && analytics.topProviders.length > 0 ? (\n <div className=\"space-y-3\">\n {analytics.topProviders.map((cart) => (\n <div\n key={cart.id}\n className=\"flex items-center justify-between rounded-lg bg-bg-sunken/50 p-3\"\n >\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{cart.name}</p>\n <p className=\"text-xs text-text-secondary flex items-center gap-1\">\n <Star className=\"h-3 w-3 fill-status-warning-text text-status-warning-text\" />\n {cart.rating.toFixed(1)} · {cart.orders.toLocaleString('en-IN')} orders\n </p>\n </div>\n <p className=\"text-sm font-semibold text-text-primary\">{fmtCur(cart.revenue)}</p>\n </div>\n ))}\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 {/* Management Links */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n {[\n {\n icon: Store,\n label: 'Cart Management',\n desc: 'Approve, manage, and monitor carts',\n path: '/admin/carts',\n },\n {\n icon: Users,\n label: 'User Management',\n desc: 'Manage users and permissions',\n path: '/admin/users',\n },\n {\n icon: BarChart3,\n label: 'Analytics & Reports',\n desc: 'View detailed platform analytics',\n path: '/admin/analytics',\n },\n {\n icon: IndianRupee,\n label: 'Financial Analytics',\n desc: 'View revenue, investments, and financial metrics',\n path: '/admin/financial',\n },\n {\n icon: Activity,\n label: 'Order Management',\n desc: 'Handle orders and customer issues',\n path: '/admin/orders',\n },\n {\n icon: Settings,\n label: 'Platform Settings',\n desc: 'Configure platform-wide settings',\n path: '/admin/settings',\n },\n ].map((link) => {\n const LinkIcon = link.icon;\n return (\n <button\n key={link.label}\n type=\"button\"\n onClick={() => navigateTo(link.path)}\n className={cn(\n 'flex items-center gap-4 rounded-lg border border-border-subtle bg-bg-surface p-4 sm:p-6 text-left shadow-sm transition-all',\n 'hover:bg-accent hover:shadow-md'\n )}\n >\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary\">\n <LinkIcon className=\"h-5 w-5\" />\n </div>\n <div className=\"min-w-0\">\n <h3 className=\"font-semibold text-text-primary text-sm sm:text-base\">\n {link.label}\n </h3>\n <p className=\"text-xs sm:text-sm text-text-secondary\">{link.desc}</p>\n </div>\n </button>\n );\n })}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdminDashboard.js","names":[],"sources":["../../../../src/kadaikodi/pages/admin/AdminDashboard.tsx"],"sourcesContent":["/**\n * Admin Dashboard Page\n * @module kadaikodi/pages/admin\n *\n * Platform control room wired to the live Kadaikodi backend. Every stat,\n * activity row and breakdown is derived from real hook data\n * (useDashboardStats + useProviders + useOrders + useAdminAnalytics).\n * Where a metric has no honest backend source it is omitted rather than faked.\n */\n\nimport { useMemo } from 'react';\nimport {\n Users,\n Store,\n ShoppingBag,\n IndianRupee,\n Activity,\n ArrowRight,\n Star,\n Settings,\n BarChart3,\n Award,\n FileText,\n AlertTriangle,\n Loader2,\n} from 'lucide-react';\nimport { CTAOverflowMenu, EmphasisPanel, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { MetricsCard } from '../../components/MetricsCard';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport {\n useDashboardStats,\n useProviders,\n useOrders,\n useAdminAnalytics,\n} from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency, formatRelativeTime } from '../../utils/formatters';\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function AdminDashboard() {\n const { navigateTo, currentUser } = useKadaikodi();\n const firstName = currentUser?.firstName ?? currentUser?.name ?? 'Admin';\n\n const { data: stats, isLoading: statsLoading } = useDashboardStats();\n const { data: providers = [], isLoading: providersLoading } = useProviders();\n const { data: orders = [], isLoading: ordersLoading } = useOrders({});\n const { data: analytics } = useAdminAnalytics();\n\n const isLoading = statsLoading || providersLoading || ordersLoading;\n\n const fmtCur = (amount: number) => formatCurrency(amount, { minimumFractionDigits: 0 });\n\n // Carts awaiting activation/verification — real derivation from provider status.\n const pendingCarts = useMemo(() => providers.filter((p) => !p.isOpen).length, [providers]);\n\n // Most recent orders across the platform → honest \"recent activity\" feed.\n const recentOrders = useMemo(\n () =>\n [...orders]\n .sort((a, b) => new Date(b.orderDate).getTime() - new Date(a.orderDate).getTime())\n .slice(0, 6),\n [orders]\n );\n\n // Admin analytics — only fields the backend actually returns.\n const prettyCategory = (c: string) => c.replace(/_/g, ' ').toLowerCase();\n const topProviders = analytics?.topProviders ?? [];\n const categoryRows = Object.entries(analytics?.categoryDistribution ?? {}).sort(\n (a, b) => b[1] - a[1]\n );\n\n const orderStatusBadge = (status: string) => {\n if (status === 'delivered') return 'bg-status-success-bg-subtle text-status-success-text';\n if (status === 'cancelled') return 'bg-status-error-bg-subtle text-status-error-text';\n return 'bg-status-warning-bg-subtle text-status-warning-text';\n };\n\n /* ---- Loading state ---- */\n if (isLoading) {\n return (\n <PageLayout title=\"Admin Dashboard\" description=\"Loading...\">\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 admin dashboard...</p>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Admin Dashboard\"\n description={`Welcome, ${firstName}! Monitor and manage the platform.`}\n actions={\n pendingCarts > 0 ? (\n <div className=\"flex items-center gap-2 rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-3 py-2\">\n <AlertTriangle className=\"h-4 w-4 text-status-error-text\" />\n <span className=\"text-sm font-medium text-status-error-text\">\n {pendingCarts} carts awaiting review\n </span>\n </div>\n ) : undefined\n }\n >\n <PagePurpose className=\"mb-6\">\n The control room for the whole Kadaikodi marketplace — approve new carts, keep an eye on\n users, orders and platform revenue, and act on anything that needs attention. Clear pending\n approvals first, then review platform health below.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"kadaikodi-admin-dashboard\"\n className=\"mb-6\"\n steps={[\n {\n id: 'approvals',\n label: 'Review pending cart approvals',\n description: 'Vet and approve new carts waiting to go live.',\n onClick: () => navigateTo('/admin/carts'),\n done: pendingCarts === 0,\n },\n {\n id: 'users',\n label: 'Manage users',\n description: 'Review accounts, roles and access across the platform.',\n onClick: () => navigateTo('/admin/users'),\n },\n {\n id: 'financial',\n label: 'Check financial health',\n description: 'Track revenue, commission and payouts.',\n onClick: () => navigateTo('/admin/financial'),\n },\n ]}\n />\n\n {/* Hero — the one emphasis zone: pending approvals + primary action + overflow */}\n <EmphasisPanel className=\"mb-8\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">Quick Actions</h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {pendingCarts > 0\n ? `${pendingCarts} carts awaiting your review.`\n : 'All caught up — nothing pending review.'}\n </p>\n </div>\n <CTAOverflowMenu\n primary={{\n label: `Review Carts${pendingCarts > 0 ? ` (${pendingCarts})` : ''}`,\n icon: <Store className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/carts'),\n }}\n actions={[\n {\n label: 'Manage Carts',\n icon: <Store className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/carts'),\n },\n {\n label: 'User Management',\n icon: <Users className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/users'),\n },\n {\n label: 'Order Management',\n icon: <ShoppingBag className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/orders'),\n },\n {\n label: 'Financial Analytics',\n icon: <IndianRupee className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/financial'),\n },\n {\n label: 'Analytics',\n icon: <BarChart3 className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/analytics'),\n },\n {\n label: 'Settings',\n icon: <Settings className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/settings'),\n },\n {\n label: 'Reports',\n icon: <FileText className=\"h-4 w-4\" />,\n onSelect: () => navigateTo('/admin/analytics'),\n },\n ]}\n />\n </div>\n </EmphasisPanel>\n\n {/* Platform Overview — real dashboard stats */}\n {stats && (\n <div className=\"mb-8\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-4\">Platform Overview</h2>\n <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-4\">\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 />\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 featured\n icon={<IndianRupee className=\"h-5 w-5\" />}\n value={fmtCur(stats.totalRevenue)}\n label=\"Total Revenue\"\n />\n </div>\n\n <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-4 mt-4\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <p className=\"text-xs text-text-secondary\">Total Carts</p>\n <p className=\"text-xl font-bold text-text-primary\">\n {providers.length.toLocaleString('en-IN')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <p className=\"text-xs text-text-secondary\">Pending Cart Approvals</p>\n <p className=\"text-xl font-bold text-status-error-text\">\n {pendingCarts.toLocaleString('en-IN')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <p className=\"text-xs text-text-secondary\">Pending Orders</p>\n <p className=\"text-xl font-bold text-status-warning-text\">\n {(stats.pendingOrders ?? 0).toLocaleString('en-IN')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <p className=\"text-xs text-text-secondary\">Average Rating</p>\n <p className=\"text-xl font-bold text-text-primary flex items-center gap-1\">\n <Star className=\"h-4 w-4 fill-status-warning-text text-status-warning-text\" />\n {stats.avgRating > 0 ? stats.avgRating.toFixed(1) : '—'}\n </p>\n </div>\n </div>\n </div>\n )}\n\n {/* Recent Activity — real recent orders */}\n <div className=\"mb-8\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Recent Orders</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/admin/orders')}\n className=\"flex items-center gap-1 text-sm font-medium text-text-secondary hover:text-text-primary transition-colors\"\n >\n View all orders\n <ArrowRight className=\"h-4 w-4\" />\n </button>\n </div>\n {recentOrders.length > 0 ? (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface divide-y divide-border\">\n {recentOrders.map((order) => (\n <div key={order.id} className=\"flex items-start gap-3 px-4 py-3\">\n <div className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-sunken mt-0.5 text-text-secondary\">\n <ShoppingBag className=\"h-4 w-4\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">\n Order from {order.cartName}\n </p>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium capitalize w-fit',\n orderStatusBadge(order.status)\n )}\n >\n {order.status.replace(/_/g, ' ')}\n </span>\n </div>\n <div className=\"flex flex-wrap items-center mt-1 text-xs text-text-secondary gap-3\">\n <span>{formatRelativeTime(order.orderDate)}</span>\n <span className=\"flex items-center gap-1\">\n <IndianRupee className=\"h-3 w-3\" />\n {(order.total ?? 0).toLocaleString('en-IN')}\n </span>\n </div>\n </div>\n </div>\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No orders yet\"\n description=\"Orders placed across the platform will appear here as they come in.\"\n />\n )}\n </div>\n\n {/* Carts by Category & Top Carts — real admin analytics */}\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 mb-4\">\n <BarChart3 className=\"h-5 w-5 text-text-secondary\" />\n <h3 className=\"text-lg font-semibold text-text-primary\">Carts by Category</h3>\n </div>\n {categoryRows.length > 0 ? (\n <div className=\"space-y-3\">\n {categoryRows.map(([category, count]) => (\n <div\n key={category}\n className=\"flex items-center justify-between rounded-lg bg-bg-sunken/50 p-3\"\n >\n <p className=\"text-sm font-medium text-text-primary capitalize\">\n {prettyCategory(category)}\n </p>\n <p className=\"text-sm font-semibold text-text-primary\">\n {(count ?? 0).toLocaleString('en-IN')}{' '}\n <span className=\"text-xs font-normal text-text-secondary\">\n {count === 1 ? 'cart' : 'carts'}\n </span>\n </p>\n </div>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Cart categories will appear here as carts are onboarded.\n </p>\n )}\n </div>\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-6\">\n <div className=\"flex items-center gap-2 mb-4\">\n <Award className=\"h-5 w-5 text-text-secondary\" />\n <h3 className=\"text-lg font-semibold text-text-primary\">Top Carts</h3>\n </div>\n {topProviders.length > 0 ? (\n <div className=\"space-y-3\">\n {topProviders.map((cart) => (\n <div\n key={cart.id}\n className=\"flex items-center justify-between rounded-lg bg-bg-sunken/50 p-3\"\n >\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{cart.name}</p>\n <p className=\"text-xs text-text-secondary capitalize\">\n {prettyCategory(cart.category)}\n </p>\n </div>\n <p className=\"text-sm font-semibold text-text-primary flex items-center 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 </p>\n </div>\n ))}\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 {/* Management Links */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n {[\n {\n icon: Store,\n label: 'Cart Management',\n desc: 'Approve, manage, and monitor carts',\n path: '/admin/carts',\n },\n {\n icon: Users,\n label: 'User Management',\n desc: 'Manage users and permissions',\n path: '/admin/users',\n },\n {\n icon: BarChart3,\n label: 'Analytics & Reports',\n desc: 'View detailed platform analytics',\n path: '/admin/analytics',\n },\n {\n icon: IndianRupee,\n label: 'Financial Analytics',\n desc: 'View revenue, investments, and financial metrics',\n path: '/admin/financial',\n },\n {\n icon: Activity,\n label: 'Order Management',\n desc: 'Handle orders and customer issues',\n path: '/admin/orders',\n },\n {\n icon: Settings,\n label: 'Platform Settings',\n desc: 'Configure platform-wide settings',\n path: '/admin/settings',\n },\n ].map((link) => {\n const LinkIcon = link.icon;\n return (\n <button\n key={link.label}\n type=\"button\"\n onClick={() => navigateTo(link.path)}\n className={cn(\n 'flex items-center gap-4 rounded-lg border border-border-subtle bg-bg-surface p-4 sm:p-6 text-left shadow-sm transition-all',\n 'hover:bg-accent hover:shadow-md'\n )}\n >\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary\">\n <LinkIcon className=\"h-5 w-5\" />\n </div>\n <div className=\"min-w-0\">\n <h3 className=\"font-semibold text-text-primary text-sm sm:text-base\">\n {link.label}\n </h3>\n <p className=\"text-xs sm:text-sm text-text-secondary\">{link.desc}</p>\n </div>\n </button>\n );\n })}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}