@burdenoff/microfe-kadaikodi 2026.704.3 → 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 +34 -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 +84 -6
- 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/AdminProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminSettingsPage.js +332 -276
- package/dist/kadaikodi/pages/admin/AdminSettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/CartManagementPage.js +564 -729
- package/dist/kadaikodi/pages/admin/CartManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/UserManagementPage.js +310 -366
- package/dist/kadaikodi/pages/admin/UserManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js +201 -120
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.js +290 -257
- package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js +173 -194
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js +270 -228
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.js +194 -173
- package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js +428 -347
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js +332 -0
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js.map +1 -0
- 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 +294 -162
- 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 +310 -317
- package/dist/kadaikodi/pages/common/HelpSupportPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/NotificationCenterPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/SettingsPage.js +502 -586
- package/dist/kadaikodi/pages/common/SettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js +239 -156
- 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/CustomerDashboard.js +5 -5
- package/dist/kadaikodi/pages/customer/CustomerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CustomerProfilePage.js +189 -199
- package/dist/kadaikodi/pages/customer/CustomerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js +272 -230
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/FavoritesPage.js +150 -413
- 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 +411 -305
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/ReviewsPage.js +310 -406
- package/dist/kadaikodi/pages/customer/ReviewsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/SavedAddressesPage.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 +441 -514
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js +428 -431
- 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 +360 -288
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js +303 -281
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -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 // 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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"}
|
|
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 * chart and list is derived from real hook data (useDashboardStats +\n * useProviders + useOrders + useAdminAnalytics). Revenue-by-category, order\n * trends and top-merchant revenue are DERIVED by joining real orders to their\n * providers — nothing is fabricated. Where a metric has no honest backend\n * source it is omitted rather than invented.\n */\n\nimport { useMemo } from 'react';\nimport {\n Users,\n Store,\n ShoppingBag,\n IndianRupee,\n ArrowRight,\n Star,\n Settings,\n BarChart3,\n UserCheck,\n ShieldCheck,\n Loader2,\n} from 'lucide-react';\nimport { GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { StatCard, DonutChart, AreaChart } from '../../components/viz';\nimport type { LabeledValue, Segment } from '../../components/viz';\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/* Helpers */\n/* ------------------------------------------------------------------ */\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 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 // Pending merchant approvals — providers not yet VERIFIED.\n const pendingProviders = useMemo(() => providers.filter((p) => !p.isVerified), [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 // ── Order trend (last 30 days) — real per-day order counts + GMV. ──────────\n const { orderTrend, gmvTrend, ordersToday } = useMemo(() => {\n const today = dayKey(new Date());\n const start = today - 29 * DAY_MS;\n const counts = new Map<number, number>();\n const gmv = new Map<number, number>();\n for (let t = start; t <= today; t += DAY_MS) {\n counts.set(t, 0);\n gmv.set(t, 0);\n }\n let todayCount = 0;\n for (const o of orders) {\n const t = dayKey(new Date(o.orderDate));\n if (counts.has(t)) {\n counts.set(t, (counts.get(t) ?? 0) + 1);\n gmv.set(t, (gmv.get(t) ?? 0) + (o.total ?? 0));\n }\n if (t === today) todayCount += 1;\n }\n const oTrend: LabeledValue[] = [...counts.entries()].map(([t, v]) => ({\n label: dayLabel(t),\n value: v,\n }));\n const gTrend: LabeledValue[] = [...gmv.entries()].map(([t, v]) => ({\n label: dayLabel(t),\n value: v,\n }));\n return { orderTrend: oTrend, gmvTrend: gTrend, ordersToday: todayCount };\n }, [orders]);\n\n // ── Revenue by category — derived by joining real orders → provider. ───────\n const revenueSegments = useMemo<Segment[]>(() => {\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 let entries = [...byCat.entries()].filter(([, v]) => v > 0).sort((a, b) => b[1] - a[1]);\n // Fall back to real category *counts* if no order revenue is available yet.\n if (entries.length === 0 && analytics?.categoryDistribution) {\n entries = Object.entries(analytics.categoryDistribution).sort((a, b) => b[1] - a[1]);\n }\n const top = entries.slice(0, 5);\n const restTotal = entries.slice(5).reduce((s, [, v]) => s + v, 0);\n const segs: Segment[] = top.map(([c, v]) => ({ label: titleCase(c), value: v }));\n if (restTotal > 0) segs.push({ label: 'Others', value: restTotal });\n return segs;\n }, [orders, providers, analytics]);\n\n const revenueIsCurrency = useMemo(() => {\n // If we derived from orders (real ₹), format as currency; if we fell back to\n // category counts, the donut represents cart counts.\n const catOf = new Set(providers.map((p) => p.id));\n return orders.some((o) => catOf.has(o.cartId) && (o.total ?? 0) > 0);\n }, [orders, providers]);\n\n const revenueTotal = useMemo(\n () => revenueSegments.reduce((s, seg) => s + seg.value, 0),\n [revenueSegments]\n );\n\n // ── Top merchants — backend ranking + derived real revenue when available. ─\n const topMerchants = useMemo(() => {\n const revByProvider = new Map<string, number>();\n for (const o of orders) revByProvider.set(o.cartId, (revByProvider.get(o.cartId) ?? 0) + (o.total ?? 0));\n const ranked = analytics?.topProviders ?? [];\n return ranked.slice(0, 5).map((p) => ({\n id: p.id,\n name: p.name,\n category: titleCase(p.category),\n rating: p.rating ?? 0,\n revenue: revByProvider.get(p.id) ?? 0,\n }));\n }, [analytics, orders]);\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=\"Platform Overview\" description=\"Loading platform control room...\">\n <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-4\">\n {Array.from({ length: 4 }).map((_, i) => (\n <div\n key={i}\n className=\"h-32 animate-pulse rounded-[var(--radius-card)] border border-border-subtle bg-bg-sunken/40\"\n />\n ))}\n </div>\n <div className=\"mt-6 flex items-center gap-2 text-text-secondary\">\n <Loader2 className=\"h-4 w-4 animate-spin\" /> Loading platform data…\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Platform Overview\"\n description={`Welcome, ${firstName}! Monitor and manage the whole Kadaikodi marketplace.`}\n actions={\n pendingProviders.length > 0 ? (\n <button\n type=\"button\"\n onClick={() => navigateTo('/admin/carts')}\n className=\"flex items-center gap-2 rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle px-3 py-2 text-sm font-medium text-status-warning-text transition-colors hover:bg-status-warning-bg-subtle/70\"\n >\n <ShieldCheck className=\"h-4 w-4\" />\n {pendingProviders.length} pending approval{pendingProviders.length === 1 ? '' : 's'}\n </button>\n ) : undefined\n }\n >\n <PagePurpose className=\"mb-6\">\n The control room for the whole Kadaikodi marketplace — track GMV, merchants, orders and\n customers at a glance, watch how demand is trending, and clear pending merchant approvals\n first. Everything below is live platform data.\n </PagePurpose>\n\n {/* KPI row — real dashboard stats + real trend sparklines */}\n <div className=\"mb-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <StatCard\n label=\"GMV (Total Revenue)\"\n value={fmtCur(stats?.totalRevenue ?? 0)}\n icon={<IndianRupee className=\"h-4 w-4\" />}\n sparkline={gmvTrend.map((d) => d.value)}\n sparklineVariant=\"area\"\n />\n <StatCard\n label=\"Active Merchants\"\n value={(stats?.activeProviders ?? 0).toLocaleString('en-IN')}\n icon={<Store className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Total Orders\"\n value={(stats?.totalOrders ?? 0).toLocaleString('en-IN')}\n icon={<ShoppingBag className=\"h-4 w-4\" />}\n sparkline={orderTrend.map((d) => d.value)}\n sparklineVariant=\"area\"\n />\n <StatCard\n label=\"Active Customers\"\n value={(stats?.activeCustomers ?? 0).toLocaleString('en-IN')}\n icon={<Users className=\"h-4 w-4\" />}\n />\n </div>\n\n {/* Main analytics grid: Revenue donut · Order-trend area · side column */}\n <div className=\"mb-8 grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Revenue by Category */}\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <h3 className=\"mb-4 text-base font-semibold text-text-primary\">\n {revenueIsCurrency ? 'Revenue by Category' : 'Carts by Category'}\n </h3>\n {revenueSegments.length > 0 ? (\n <DonutChart\n segments={revenueSegments}\n centerLabel={\n revenueIsCurrency ? fmtCur(revenueTotal) : revenueTotal.toLocaleString('en-IN')\n }\n centerCaption={revenueIsCurrency ? 'revenue' : 'carts'}\n valueFormatter={\n revenueIsCurrency ? (v) => fmtCur(v) : (v) => v.toLocaleString('en-IN')\n }\n />\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Category revenue will appear here as orders come in.\n </p>\n )}\n </GlassCard>\n\n {/* Order Trends */}\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 Trends</h3>\n <span className=\"rounded-full bg-[var(--color-accent-soft)] px-2.5 py-0.5 text-xs font-medium text-text-primary\">\n Today: {ordersToday.toLocaleString('en-IN')}\n </span>\n </div>\n {orders.length > 0 ? (\n <AreaChart\n series={orderTrend}\n height={200}\n valueFormatter={(v) => v.toLocaleString('en-IN')}\n title=\"Orders 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 {/* Side column: Top Merchants + Pending Approvals */}\n <div className=\"flex flex-col gap-6\">\n <GlassCard treatment=\"plain\" className=\"p-6\">\n <h3 className=\"mb-4 text-base font-semibold text-text-primary\">Top Merchants</h3>\n {topMerchants.length > 0 ? (\n <ul className=\"space-y-3\">\n {topMerchants.map((m, i) => (\n <li key={m.id} className=\"flex items-center gap-3\">\n <span className=\"flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-xs font-bold text-text-secondary\">\n {i + 1}\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{m.name}</p>\n <p className=\"truncate text-xs text-text-secondary\">{m.category}</p>\n </div>\n <div className=\"shrink-0 text-right\">\n {m.revenue > 0 ? (\n <p className=\"text-sm font-semibold text-text-primary\">{fmtCur(m.revenue)}</p>\n ) : null}\n <p className=\"flex items-center justify-end gap-1 text-xs text-text-secondary\">\n <Star className=\"h-3 w-3 fill-status-warning-text text-status-warning-text\" />\n {m.rating.toFixed(1)}\n </p>\n </div>\n </li>\n ))}\n </ul>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Top merchants will be ranked here once orders start flowing.\n </p>\n )}\n </GlassCard>\n\n <GlassCard treatment={pendingProviders.length > 0 ? 'glass' : 'plain'} className=\"p-6\">\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <h3 className=\"text-base font-semibold text-text-primary\">\n Pending Merchant Approvals\n </h3>\n <p className=\"mt-1 text-3xl font-bold tabular-nums text-text-primary\">\n {pendingProviders.length.toLocaleString('en-IN')}\n <span className=\"ml-1 text-base font-normal text-text-secondary\">pending</span>\n </p>\n </div>\n <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary\">\n <UserCheck className=\"h-5 w-5\" />\n </span>\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo('/admin/carts')}\n className=\"mt-4 w-full rounded-lg bg-action-primary-bg py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n Review\n </button>\n </GlassCard>\n </div>\n </div>\n\n {/* Recent Orders */}\n <div className=\"mb-8\">\n <div className=\"mb-4 flex items-center justify-between\">\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 transition-colors hover:text-text-primary\"\n >\n View all orders\n <ArrowRight className=\"h-4 w-4\" />\n </button>\n </div>\n {recentOrders.length > 0 ? (\n <div className=\"divide-y divide-border rounded-lg border border-border-subtle bg-bg-surface\">\n {recentOrders.map((order) => (\n <div key={order.id} className=\"flex items-start gap-3 px-4 py-3\">\n <div className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-text-secondary\">\n <ShoppingBag className=\"h-4 w-4\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-col justify-between gap-2 sm:flex-row sm:items-center\">\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 w-fit items-center rounded-full px-2 py-0.5 text-xs font-medium capitalize',\n orderStatusBadge(order.status)\n )}\n >\n {order.status.replace(/_/g, ' ')}\n </span>\n </div>\n <div className=\"mt-1 flex flex-wrap items-center gap-3 text-xs text-text-secondary\">\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 {/* Management Links */}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {[\n {\n icon: Store,\n label: 'Merchant Management',\n desc: 'Approve, verify 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 Reports',\n desc: 'Revenue, categories and trends',\n path: '/admin/financial',\n },\n {\n icon: ShoppingBag,\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 text-left shadow-sm transition-all sm:p-6',\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=\"text-sm font-semibold text-text-primary sm:text-base\">\n {link.label}\n </h3>\n <p className=\"text-xs text-text-secondary sm:text-sm\">{link.desc}</p>\n </div>\n </button>\n );\n })}\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|