@burdenoff/microfe-kadaikodi 2026.704.4 → 2026.710.1
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/generated/global-operations.d.ts +2 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-types.d.ts +23527 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/wspace-operations.d.ts +2 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-types.d.ts +57851 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -1
- package/dist/kadaikodi/KadaikodiRoot.d.ts +5 -0
- package/dist/kadaikodi/KadaikodiRoot.d.ts.map +1 -0
- package/dist/kadaikodi/KadaikodiRoutes.d.ts +4 -0
- package/dist/kadaikodi/KadaikodiRoutes.d.ts.map +1 -0
- package/dist/kadaikodi/KadaikodiRoutes.js +30 -26
- package/dist/kadaikodi/KadaikodiRoutes.js.map +1 -1
- package/dist/kadaikodi/components/CartCard.d.ts +18 -0
- package/dist/kadaikodi/components/CartCard.d.ts.map +1 -0
- package/dist/kadaikodi/components/EmptyState.d.ts +17 -0
- package/dist/kadaikodi/components/EmptyState.d.ts.map +1 -0
- package/dist/kadaikodi/components/InvestmentCard.d.ts +18 -0
- package/dist/kadaikodi/components/InvestmentCard.d.ts.map +1 -0
- package/dist/kadaikodi/components/MetricsCard.d.ts +16 -0
- package/dist/kadaikodi/components/MetricsCard.d.ts.map +1 -0
- package/dist/kadaikodi/components/OrderCard.d.ts +18 -0
- package/dist/kadaikodi/components/OrderCard.d.ts.map +1 -0
- package/dist/kadaikodi/components/PageLayout.d.ts +12 -0
- package/dist/kadaikodi/components/PageLayout.d.ts.map +1 -0
- package/dist/kadaikodi/components/RatingDisplay.d.ts +12 -0
- package/dist/kadaikodi/components/RatingDisplay.d.ts.map +1 -0
- package/dist/kadaikodi/components/StatusBadge.d.ts +9 -0
- package/dist/kadaikodi/components/StatusBadge.d.ts.map +1 -0
- package/dist/kadaikodi/components/index.d.ts +13 -0
- package/dist/kadaikodi/components/index.d.ts.map +1 -0
- package/dist/kadaikodi/components/viz/AllocationBar.d.ts +21 -0
- package/dist/kadaikodi/components/viz/AllocationBar.d.ts.map +1 -0
- 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.d.ts +18 -0
- package/dist/kadaikodi/components/viz/AreaChart.d.ts.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.d.ts +13 -0
- package/dist/kadaikodi/components/viz/AvatarStack.d.ts.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.d.ts +17 -0
- package/dist/kadaikodi/components/viz/BarChart.d.ts.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.d.ts +14 -0
- package/dist/kadaikodi/components/viz/CertificateCard.d.ts.map +1 -0
- package/dist/kadaikodi/components/viz/CertificateCard.js +4 -0
- package/dist/kadaikodi/components/viz/DonutChart.d.ts +20 -0
- package/dist/kadaikodi/components/viz/DonutChart.d.ts.map +1 -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.d.ts +17 -0
- package/dist/kadaikodi/components/viz/HBarFunnel.d.ts.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.d.ts +26 -0
- package/dist/kadaikodi/components/viz/Heatmap.d.ts.map +1 -0
- package/dist/kadaikodi/components/viz/Heatmap.js +3 -0
- package/dist/kadaikodi/components/viz/KanbanBoard.d.ts +17 -0
- package/dist/kadaikodi/components/viz/KanbanBoard.d.ts.map +1 -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.d.ts +20 -0
- package/dist/kadaikodi/components/viz/LineChart.d.ts.map +1 -0
- package/dist/kadaikodi/components/viz/LineChart.js +4 -0
- package/dist/kadaikodi/components/viz/OrgTree.d.ts +14 -0
- package/dist/kadaikodi/components/viz/OrgTree.d.ts.map +1 -0
- package/dist/kadaikodi/components/viz/OrgTree.js +2 -0
- package/dist/kadaikodi/components/viz/PathSteps.d.ts +17 -0
- package/dist/kadaikodi/components/viz/PathSteps.d.ts.map +1 -0
- package/dist/kadaikodi/components/viz/PathSteps.js +3 -0
- package/dist/kadaikodi/components/viz/ProgressRing.d.ts +20 -0
- package/dist/kadaikodi/components/viz/ProgressRing.d.ts.map +1 -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.d.ts +14 -0
- package/dist/kadaikodi/components/viz/RatingStars.d.ts.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.d.ts +26 -0
- package/dist/kadaikodi/components/viz/SegmentedTabs.d.ts.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.d.ts +17 -0
- package/dist/kadaikodi/components/viz/SkillBar.d.ts.map +1 -0
- package/dist/kadaikodi/components/viz/SkillBar.js +3 -0
- package/dist/kadaikodi/components/viz/Sparkline.d.ts +16 -0
- package/dist/kadaikodi/components/viz/Sparkline.d.ts.map +1 -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.d.ts +22 -0
- package/dist/kadaikodi/components/viz/StatCard.d.ts.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.d.ts +17 -0
- package/dist/kadaikodi/components/viz/StepProgress.d.ts.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.d.ts +21 -0
- package/dist/kadaikodi/components/viz/Timeline.d.ts.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.d.ts +35 -0
- package/dist/kadaikodi/components/viz/index.d.ts.map +1 -0
- package/dist/kadaikodi/components/viz/index.js +23 -0
- package/dist/kadaikodi/components/viz/lib/Avatar.d.ts +15 -0
- package/dist/kadaikodi/components/viz/lib/Avatar.d.ts.map +1 -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.d.ts +44 -0
- package/dist/kadaikodi/components/viz/lib/CartesianFrame.d.ts.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.d.ts +27 -0
- package/dist/kadaikodi/components/viz/lib/ResponsiveSvg.d.ts.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.d.ts +10 -0
- package/dist/kadaikodi/components/viz/lib/format.d.ts.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.d.ts +41 -0
- package/dist/kadaikodi/components/viz/lib/geometry.d.ts.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.d.ts +18 -0
- package/dist/kadaikodi/components/viz/lib/hooks.d.ts.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.d.ts +31 -0
- package/dist/kadaikodi/components/viz/lib/palette.d.ts.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/components/viz/lib/types.d.ts +27 -0
- package/dist/kadaikodi/components/viz/lib/types.d.ts.map +1 -0
- package/dist/kadaikodi/context/KadaikodiContext.d.ts +16 -0
- package/dist/kadaikodi/context/KadaikodiContext.d.ts.map +1 -0
- package/dist/kadaikodi/context/index.d.ts +6 -0
- package/dist/kadaikodi/context/index.d.ts.map +1 -0
- package/dist/kadaikodi/hooks/index.d.ts +2 -0
- package/dist/kadaikodi/hooks/index.d.ts.map +1 -0
- package/dist/kadaikodi/hooks/useKadaikodiApi.d.ts +169 -0
- package/dist/kadaikodi/hooks/useKadaikodiApi.d.ts.map +1 -0
- package/dist/kadaikodi/hooks/useKadaikodiApi.js +18 -10
- package/dist/kadaikodi/hooks/useKadaikodiApi.js.map +1 -1
- package/dist/kadaikodi/index.d.ts +11 -0
- package/dist/kadaikodi/index.d.ts.map +1 -0
- package/dist/kadaikodi/pages/HomePage.d.ts +14 -0
- package/dist/kadaikodi/pages/HomePage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/HomePage.js +373 -631
- package/dist/kadaikodi/pages/HomePage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.d.ts +13 -0
- package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.d.ts.map +1 -0
- 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.d.ts +13 -0
- package/dist/kadaikodi/pages/admin/AdminDashboard.d.ts.map +1 -0
- 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.d.ts +12 -0
- package/dist/kadaikodi/pages/admin/AdminFinancialPage.d.ts.map +1 -0
- 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.d.ts +11 -0
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.d.ts.map +1 -0
- 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.d.ts +11 -0
- package/dist/kadaikodi/pages/admin/AdminProfilePage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/admin/AdminSettingsPage.d.ts +10 -0
- package/dist/kadaikodi/pages/admin/AdminSettingsPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/admin/CartManagementPage.d.ts +13 -0
- package/dist/kadaikodi/pages/admin/CartManagementPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/admin/CartManagementPage.js +558 -718
- package/dist/kadaikodi/pages/admin/CartManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/UserManagementPage.d.ts +10 -0
- package/dist/kadaikodi/pages/admin/UserManagementPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/admin/UserManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.d.ts +13 -0
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.d.ts.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js +142 -55
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.d.ts +11 -0
- package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.d.ts +12 -0
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.d.ts.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js +129 -164
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.d.ts +12 -0
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.d.ts +11 -0
- package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.d.ts +11 -0
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js +379 -361
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.d.ts +2 -0
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js +266 -166
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.d.ts +2 -0
- package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.d.ts.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.d.ts +10 -0
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js +288 -161
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.d.ts +12 -0
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.d.ts.map +1 -0
- 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.d.ts +11 -0
- package/dist/kadaikodi/pages/common/HelpSupportPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/common/HelpSupportPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/NotificationCenterPage.d.ts +10 -0
- package/dist/kadaikodi/pages/common/NotificationCenterPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/common/SettingsPage.d.ts +19 -0
- package/dist/kadaikodi/pages/common/SettingsPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/common/SettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.d.ts +12 -0
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js +17 -34
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CartDetailPage.d.ts +13 -0
- package/dist/kadaikodi/pages/customer/CartDetailPage.d.ts.map +1 -0
- 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.d.ts +11 -0
- package/dist/kadaikodi/pages/customer/CartDiscoveryPage.d.ts.map +1 -0
- 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.d.ts +9 -0
- package/dist/kadaikodi/pages/customer/CheckoutPage.d.ts.map +1 -0
- 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.d.ts +10 -0
- package/dist/kadaikodi/pages/customer/CustomerDashboard.d.ts.map +1 -0
- package/dist/kadaikodi/pages/customer/CustomerProfilePage.d.ts +10 -0
- package/dist/kadaikodi/pages/customer/CustomerProfilePage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.d.ts +12 -0
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js +270 -230
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/FavoritesPage.d.ts +11 -0
- package/dist/kadaikodi/pages/customer/FavoritesPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/customer/FavoritesPage.js +149 -412
- package/dist/kadaikodi/pages/customer/FavoritesPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/OrderHistoryPage.d.ts +9 -0
- package/dist/kadaikodi/pages/customer/OrderHistoryPage.d.ts.map +1 -0
- 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.d.ts +9 -0
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js +176 -175
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/PaymentMethodsPage.d.ts +11 -0
- package/dist/kadaikodi/pages/customer/PaymentMethodsPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/customer/ReviewsPage.d.ts +12 -0
- package/dist/kadaikodi/pages/customer/ReviewsPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/customer/ReviewsPage.js +295 -438
- package/dist/kadaikodi/pages/customer/ReviewsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/SavedAddressesPage.d.ts +10 -0
- package/dist/kadaikodi/pages/customer/SavedAddressesPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/customer/shared.d.ts +41 -0
- package/dist/kadaikodi/pages/customer/shared.d.ts.map +1 -0
- 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.d.ts +13 -0
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.d.ts.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.d.ts +10 -0
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.d.ts.map +1 -0
- 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.d.ts +11 -0
- package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.d.ts.map +1 -0
- 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.d.ts +10 -0
- package/dist/kadaikodi/pages/investor/InvestorDashboard.d.ts.map +1 -0
- 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.d.ts +10 -0
- package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.d.ts.map +1 -0
- 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.d.ts +11 -0
- package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.d.ts.map +1 -0
- 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.d.ts +20 -0
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.d.ts +18 -0
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js +424 -448
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerDashboard.d.ts +14 -0
- package/dist/kadaikodi/pages/worker/WorkerDashboard.d.ts.map +1 -0
- 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.d.ts +18 -0
- package/dist/kadaikodi/pages/worker/WorkerOrdersPage.d.ts.map +1 -0
- 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.d.ts +18 -0
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js +300 -296
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.d.ts +16 -0
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.d.ts.map +1 -0
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js +284 -309
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js.map +1 -1
- package/dist/kadaikodi/store/index.d.ts +6 -0
- package/dist/kadaikodi/store/index.d.ts.map +1 -0
- package/dist/kadaikodi/store/kadaikodiStore.d.ts +60 -0
- package/dist/kadaikodi/store/kadaikodiStore.d.ts.map +1 -0
- package/dist/kadaikodi/types/index.d.ts +464 -0
- package/dist/kadaikodi/types/index.d.ts.map +1 -0
- package/dist/kadaikodi/utils/cn.d.ts +4 -0
- package/dist/kadaikodi/utils/cn.d.ts.map +1 -0
- package/dist/kadaikodi/utils/formatters.d.ts +78 -0
- package/dist/kadaikodi/utils/formatters.d.ts.map +1 -0
- package/dist/kadaikodi/utils/index.d.ts +8 -0
- package/dist/kadaikodi/utils/index.d.ts.map +1 -0
- package/dist/kadaikodi/utils/navigation.d.ts +20 -0
- package/dist/kadaikodi/utils/navigation.d.ts.map +1 -0
- package/dist/services/createSandboxAssistantTransport.d.ts +43 -0
- package/dist/services/createSandboxAssistantTransport.d.ts.map +1 -0
- package/dist/services/createSandboxAssistantTransport.js +15 -0
- package/dist/services/createSandboxAssistantTransport.js.map +1 -0
- package/package.json +5 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CartManagementPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/admin/CartManagementPage.tsx"],"sourcesContent":["/**\n * Cart Management Page\n * @module kadaikodi/pages/admin\n *\n * Full-featured cart management with 8 stats cards, 6 filter controls,\n * dual layout (mobile cards + desktop table), cart action modal\n * (view/approve/reject with reason/suspend/inspect), loading state.\n */\n\nimport { useState, useMemo } from 'react';\nimport {\n Search,\n Store,\n CheckCircle2,\n XCircle,\n Pause,\n Star,\n Eye,\n Loader2,\n X,\n AlertCircle,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useProviders, useUpdateProvider } from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency } from '../../utils/formatters';\nimport type { MockCart } from '../../types';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\ninterface ExtendedCart {\n id: string;\n name: string;\n description: string;\n category: string;\n image: string;\n ownerName: string;\n ownerEmail: string;\n ownerPhone: string;\n address: string;\n city: string;\n isActive: boolean;\n isVerified: boolean;\n rating: number;\n reviewCount: number;\n monthlyRevenue: number;\n monthlyOrders: number;\n complianceScore: number;\n documentsSubmitted: number;\n documentsRequired: number;\n inspectionStatus: 'pending' | 'scheduled' | 'completed' | 'failed';\n inspectionDate?: string;\n rejectionReason?: string;\n applicationDate: string;\n licenseNumber?: string;\n}\n\ninterface CartFilters {\n searchQuery: string;\n status: string;\n verificationStatus: string;\n category: string;\n location: string;\n sortBy: string;\n}\n\ninterface CartStats {\n totalCarts: number;\n activeCarts: number;\n pendingApproval: number;\n rejectedCarts: number;\n totalRevenue: number;\n averageRating: number;\n complianceRate: number;\n newApplications: number;\n}\n\ntype CartActionType = 'view' | 'approve' | 'reject' | 'suspend';\n\n/* ------------------------------------------------------------------ */\n/* Provider → admin cart view-model (real data, no fabricated fields) */\n/* ------------------------------------------------------------------ */\n\nfunction mapProviderToCart(p: MockCart): ExtendedCart {\n return {\n id: p.id,\n name: p.name,\n description: '',\n category: p.category,\n image: '',\n ownerName: '',\n ownerEmail: '',\n ownerPhone: '',\n address: p.location?.address ?? '',\n city: '',\n isActive: p.isOpen,\n isVerified: p.isVerified ?? false,\n rating: p.rating,\n reviewCount: p.totalRatings,\n monthlyRevenue: 0,\n monthlyOrders: 0,\n complianceScore: 0,\n documentsSubmitted: 0,\n documentsRequired: 0,\n inspectionStatus: p.isVerified ? 'completed' : 'pending',\n applicationDate: p.createdAt ?? new Date().toISOString(),\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function CartManagementPage() {\n const { navigateTo } = useKadaikodi();\n\n const { data: providers = [], isLoading: loading } = useProviders();\n const updateProvider = useUpdateProvider();\n const [statusMessage, setStatusMessage] = useState<{\n text: string;\n type: 'success' | 'error';\n } | null>(null);\n const showStatus = (text: string, type: 'success' | 'error') => {\n setStatusMessage({ text, type });\n setTimeout(() => setStatusMessage(null), 3500);\n };\n const [selectedCart, setSelectedCart] = useState<ExtendedCart | null>(null);\n const [showCartModal, setShowCartModal] = useState(false);\n const [actionType, setActionType] = useState<CartActionType>('view');\n const [rejectionReason, setRejectionReason] = useState('');\n\n const [filters, setFilters] = useState<CartFilters>({\n searchQuery: '',\n status: '',\n verificationStatus: '',\n category: '',\n location: '',\n sortBy: 'recent',\n });\n\n const allCarts = useMemo(() => providers.map(mapProviderToCart), [providers]);\n\n const stats: CartStats = useMemo(() => {\n const active = allCarts.filter((c) => c.isActive).length;\n const pending = allCarts.filter((c) => !c.isVerified).length;\n const avg = allCarts.length ? allCarts.reduce((s, c) => s + c.rating, 0) / allCarts.length : 0;\n return {\n totalCarts: allCarts.length,\n activeCarts: active,\n pendingApproval: pending,\n rejectedCarts: 0,\n totalRevenue: 0,\n averageRating: Number(avg.toFixed(1)),\n complianceRate: 0,\n newApplications: pending,\n };\n }, [allCarts]);\n\n const carts = useMemo(() => {\n let filtered = [...allCarts];\n\n if (filters.searchQuery) {\n const q = filters.searchQuery.toLowerCase();\n filtered = filtered.filter(\n (c) =>\n c.name.toLowerCase().includes(q) ||\n c.ownerName.toLowerCase().includes(q) ||\n c.description.toLowerCase().includes(q) ||\n c.address.toLowerCase().includes(q)\n );\n }\n if (filters.status) {\n if (filters.status === 'active') filtered = filtered.filter((c) => c.isActive);\n if (filters.status === 'inactive') filtered = filtered.filter((c) => !c.isActive);\n }\n if (filters.verificationStatus) {\n if (filters.verificationStatus === 'verified')\n filtered = filtered.filter((c) => c.isVerified);\n if (filters.verificationStatus === 'pending')\n filtered = filtered.filter((c) => !c.isVerified && c.inspectionStatus !== 'failed');\n if (filters.verificationStatus === 'rejected')\n filtered = filtered.filter((c) => c.inspectionStatus === 'failed');\n }\n if (filters.category) filtered = filtered.filter((c) => c.category === filters.category);\n if (filters.location)\n filtered = filtered.filter((c) =>\n c.city.toLowerCase().includes(filters.location.toLowerCase())\n );\n\n switch (filters.sortBy) {\n case 'name':\n filtered.sort((a, b) => a.name.localeCompare(b.name));\n break;\n case 'rating':\n filtered.sort((a, b) => b.rating - a.rating);\n break;\n case 'revenue':\n filtered.sort((a, b) => b.monthlyRevenue - a.monthlyRevenue);\n break;\n case 'compliance':\n filtered.sort((a, b) => b.complianceScore - a.complianceScore);\n break;\n default:\n filtered.sort(\n (a, b) => new Date(b.applicationDate).getTime() - new Date(a.applicationDate).getTime()\n );\n }\n\n return filtered;\n }, [allCarts, filters]);\n\n const handleFilterChange = (key: keyof CartFilters, value: string) => {\n setFilters((prev) => ({ ...prev, [key]: value }));\n };\n\n const handleCartAction = (cart: ExtendedCart, action: CartActionType) => {\n setSelectedCart(cart);\n setActionType(action);\n setRejectionReason('');\n setShowCartModal(true);\n };\n\n const executeCartAction = () => {\n if (!selectedCart || actionType === 'view') return;\n if (actionType === 'reject' && !rejectionReason.trim()) {\n showStatus('Please provide a rejection reason', 'error');\n return;\n }\n // Approval/rejection/suspension persist to the provider record. The backend\n // provider-status enum has no dedicated \"rejected\" value, so a rejected\n // application is archived out of the active marketplace.\n const status =\n actionType === 'approve' ? 'VERIFIED' : actionType === 'reject' ? 'ARCHIVED' : 'SUSPENDED';\n updateProvider.mutate(\n { id: selectedCart.id, input: { status } },\n {\n onSuccess: () => {\n const verb =\n actionType === 'approve'\n ? 'approved'\n : actionType === 'reject'\n ? 'rejected'\n : 'suspended';\n showStatus(`Cart \"${selectedCart.name}\" ${verb}.`, 'success');\n setShowCartModal(false);\n setRejectionReason('');\n },\n onError: () =>\n showStatus(`Could not ${actionType} \"${selectedCart.name}\". Please try again.`, 'error'),\n }\n );\n };\n\n const formatDate = (d: string) =>\n new Date(d).toLocaleDateString('en-IN', { year: 'numeric', month: 'short', day: 'numeric' });\n\n const verificationBadge = (cart: ExtendedCart) => {\n if (cart.isVerified)\n return (\n <span className=\"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-status-success-bg-subtle text-status-success-text\">\n Verified\n </span>\n );\n if (cart.inspectionStatus === 'pending')\n return (\n <span className=\"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-status-warning-bg-subtle text-status-warning-text\">\n Pending Review\n </span>\n );\n if (cart.inspectionStatus === 'scheduled')\n return (\n <span className=\"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-[var(--color-accent-soft)] text-text-primary\">\n Inspection Scheduled\n </span>\n );\n if (cart.inspectionStatus === 'failed')\n return (\n <span className=\"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-status-error-bg-subtle text-status-error-text\">\n Rejected\n </span>\n );\n return (\n <span className=\"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-bg-sunken text-text-secondary\">\n Under Review\n </span>\n );\n };\n\n const statusBadge = (isActive: boolean) =>\n isActive ? (\n <span className=\"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-status-success-bg-subtle text-status-success-text\">\n Active\n </span>\n ) : (\n <span className=\"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium bg-bg-sunken text-text-secondary\">\n Inactive\n </span>\n );\n\n const complianceBar = (score: number) => (\n <div className=\"w-full bg-bg-sunken rounded-full h-2\">\n <div\n className={cn(\n 'h-2 rounded-full',\n score >= 80\n ? 'bg-status-success-text'\n : score >= 60\n ? 'bg-status-warning-text'\n : 'bg-status-error-text'\n )}\n style={{ width: `${score}%` }}\n />\n </div>\n );\n\n if (loading) {\n return (\n <PageLayout title=\"Cart Management\" description=\"Loading carts...\">\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 carts...</p>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Cart Management\"\n description={`${stats.totalCarts} service providers on the platform`}\n actions={\n <span className=\"text-sm text-text-secondary\">\n {stats.pendingApproval} pending approval\n </span>\n }\n >\n <PagePurpose className=\"mb-6\">\n Where you onboard and oversee every cart (service provider) on Kadaikodi. Use this page to\n approve or reject new applications, verify legitimate businesses, suspend ones that break\n the rules, and keep an eye on each cart's performance and ratings — so customers only\n ever see trustworthy, active providers. Filter and search to zero in on what needs your\n attention.\n </PagePurpose>\n\n {statusMessage && (\n <div\n className={cn(\n 'mb-6 flex items-center gap-2 rounded-lg border p-3',\n statusMessage.type === 'success'\n ? 'border-status-success-text/30 bg-status-success-bg-subtle'\n : 'border-status-error-text/30 bg-status-error-bg-subtle'\n )}\n >\n {statusMessage.type === 'success' ? (\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertCircle className=\"h-4 w-4 text-status-error-text\" />\n )}\n <span\n className={cn(\n 'text-sm font-medium',\n statusMessage.type === 'success'\n ? 'text-status-success-text'\n : 'text-status-error-text'\n )}\n >\n {statusMessage.text}\n </span>\n </div>\n )}\n\n {/* 8 Stats Cards — the one emphasis zone for this page */}\n <EmphasisPanel className=\"mb-6\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">Provider Overview</h2>\n <div className=\"grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-8 gap-3\">\n {[\n { label: 'Total Carts', value: stats.totalCarts, cls: '' },\n {\n label: 'Active',\n value: stats.activeCarts,\n cls: 'bg-status-success-bg-subtle border-status-success-text/30',\n },\n {\n label: 'Pending',\n value: stats.pendingApproval,\n cls: 'bg-status-warning-bg-subtle border-status-warning-text/30',\n },\n {\n label: 'Rejected',\n value: stats.rejectedCarts,\n cls: 'bg-status-error-bg-subtle border-status-error-text/30',\n },\n {\n label: 'Total Revenue',\n value: formatCurrency(stats.totalRevenue, { minimumFractionDigits: 0 }),\n cls: 'col-span-2 min-w-fit',\n },\n { label: 'Avg Rating', value: `${stats.averageRating}`, cls: '' },\n {\n label: 'New Apps',\n value: stats.newApplications,\n cls: 'bg-[var(--color-accent-soft)] border-border-focus/30',\n },\n ].map((s) => (\n <div\n key={s.label}\n className={cn('rounded-lg border border-border-subtle bg-bg-surface p-3', s.cls)}\n >\n <p className=\"text-xs text-text-secondary\">{s.label}</p>\n <p className=\"text-lg font-bold text-text-primary\">{s.value}</p>\n </div>\n ))}\n </div>\n </EmphasisPanel>\n\n {/* 6 Filter Controls */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 mb-6\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3\">\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search carts...\"\n value={filters.searchQuery}\n onChange={(e) => handleFilterChange('searchQuery', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 pl-10 pr-4 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <select\n value={filters.status}\n onChange={(e) => handleFilterChange('status', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">All Status</option>\n <option value=\"active\">Active</option>\n <option value=\"inactive\">Inactive</option>\n </select>\n <select\n value={filters.verificationStatus}\n onChange={(e) => handleFilterChange('verificationStatus', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">All Verification</option>\n <option value=\"verified\">Verified</option>\n <option value=\"pending\">Pending</option>\n <option value=\"rejected\">Rejected</option>\n </select>\n <select\n value={filters.category}\n onChange={(e) => handleFilterChange('category', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">All Categories</option>\n <option value=\"Food & Beverage\">Food & Beverage</option>\n <option value=\"Beverages\">Beverages</option>\n <option value=\"Street Food\">Street Food</option>\n <option value=\"Fast Food\">Fast Food</option>\n </select>\n <input\n type=\"text\"\n placeholder=\"Location...\"\n value={filters.location}\n onChange={(e) => handleFilterChange('location', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n <select\n value={filters.sortBy}\n onChange={(e) => handleFilterChange('sortBy', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"recent\">Most Recent</option>\n <option value=\"name\">Name A-Z</option>\n <option value=\"rating\">Highest Rated</option>\n <option value=\"revenue\">Highest Revenue</option>\n <option value=\"compliance\">Best Compliance</option>\n </select>\n </div>\n </div>\n\n {/* Dual Layout */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface overflow-hidden\">\n {/* Mobile Card View */}\n <div className=\"block md:hidden space-y-4 p-4\">\n {carts.map((cart) => (\n <div\n key={cart.id}\n className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-4\"\n >\n <div className=\"flex items-center mb-3\">\n <div className=\"w-16 h-16 rounded-lg bg-bg-sunken flex items-center justify-center mr-3 shrink-0\">\n <Store className=\"h-7 w-7 text-text-secondary\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"font-medium text-text-primary text-lg truncate\">{cart.name}</h3>\n <p className=\"text-sm text-text-secondary truncate\">{cart.category}</p>\n <p className=\"text-sm text-text-secondary truncate\">{cart.address}</p>\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4 mb-3 text-sm\">\n <div>\n <p className=\"text-text-secondary font-medium\">Owner</p>\n <p className=\"text-text-primary\">{cart.ownerName}</p>\n <p className=\"text-text-secondary text-xs\">{cart.ownerPhone}</p>\n </div>\n <div>\n <p className=\"text-text-secondary font-medium\">Performance</p>\n <p className=\"text-text-primary\">\n {formatCurrency(cart.monthlyRevenue, { minimumFractionDigits: 0 })}/mo\n </p>\n <p className=\"text-text-secondary text-xs\">{cart.monthlyOrders} orders</p>\n </div>\n </div>\n <div className=\"flex flex-wrap gap-2 mb-3\">\n {statusBadge(cart.isActive)}\n {verificationBadge(cart)}\n {cart.rating > 0 && (\n <span className=\"inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium bg-status-warning-bg-subtle text-status-warning-text\">\n <Star className=\"h-3 w-3 fill-current\" />\n {cart.rating} ({cart.reviewCount})\n </span>\n )}\n </div>\n <div className=\"mb-3\">\n <div className=\"flex items-center justify-between text-sm mb-1\">\n <span className=\"text-text-secondary\">Compliance</span>\n <span className=\"font-medium text-text-primary\">{cart.complianceScore}%</span>\n </div>\n {complianceBar(cart.complianceScore)}\n <p className=\"text-xs text-text-secondary mt-1\">\n Docs: {cart.documentsSubmitted}/{cart.documentsRequired} • Applied:{' '}\n {formatDate(cart.applicationDate)}\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => handleCartAction(cart, 'view')}\n className=\"flex-1 rounded-lg border border-border-subtle px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n View Details\n </button>\n {!cart.isVerified && cart.inspectionStatus !== 'failed' && (\n <>\n <button\n type=\"button\"\n onClick={() => handleCartAction(cart, 'approve')}\n className=\"rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n Approve\n </button>\n <button\n type=\"button\"\n onClick={() => handleCartAction(cart, 'reject')}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n Reject\n </button>\n </>\n )}\n {cart.isActive && (\n <button\n type=\"button\"\n onClick={() => handleCartAction(cart, 'suspend')}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n Suspend\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n\n {/* Desktop Table View */}\n <div className=\"hidden md:block overflow-x-auto\">\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 tracking-wider\">\n Cart\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Owner\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Status\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Performance\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Compliance\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {carts.map((cart) => (\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-3\">\n <div className=\"w-12 h-12 rounded-lg bg-bg-sunken flex items-center justify-center shrink-0\">\n <Store className=\"h-5 w-5 text-text-secondary\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium text-text-primary truncate\">\n {cart.name}\n </p>\n <p className=\"text-xs text-text-secondary truncate\">{cart.category}</p>\n <p className=\"text-xs text-text-secondary truncate\">{cart.address}</p>\n </div>\n </div>\n </td>\n <td className=\"px-4 py-3 text-sm\">\n <p className=\"font-medium text-text-primary\">{cart.ownerName}</p>\n <p className=\"text-xs text-text-secondary\">{cart.ownerEmail}</p>\n <p className=\"text-xs text-text-secondary\">{cart.ownerPhone}</p>\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"space-y-1\">\n {statusBadge(cart.isActive)}\n <br />\n {verificationBadge(cart)}\n {cart.rating > 0 && (\n <div className=\"text-sm flex items-center gap-1 mt-1\">\n <Star className=\"h-3 w-3 fill-status-warning-text text-status-warning-text\" />\n {cart.rating}{' '}\n <span className=\"text-text-secondary\">({cart.reviewCount})</span>\n </div>\n )}\n </div>\n </td>\n <td className=\"px-4 py-3 text-sm\">\n <p className=\"text-text-primary\">\n {formatCurrency(cart.monthlyRevenue, { minimumFractionDigits: 0 })}/mo\n </p>\n <p className=\"text-text-secondary\">{cart.monthlyOrders} orders/mo</p>\n </td>\n <td className=\"px-4 py-3 text-sm\">\n <div className=\"flex items-center gap-2 mb-1\">\n <div className=\"w-16\">{complianceBar(cart.complianceScore)}</div>\n <span className=\"font-medium text-text-primary\">{cart.complianceScore}%</span>\n </div>\n <p className=\"text-xs text-text-secondary\">\n Docs: {cart.documentsSubmitted}/{cart.documentsRequired}\n </p>\n <p className=\"text-xs text-text-secondary\">\n Applied: {formatDate(cart.applicationDate)}\n </p>\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"flex flex-col gap-1\">\n <button\n type=\"button\"\n onClick={() => handleCartAction(cart, 'view')}\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-accent transition-colors inline-flex items-center gap-1 text-xs\"\n >\n <Eye className=\"h-4 w-4\" /> View\n </button>\n {!cart.isVerified && cart.inspectionStatus !== 'failed' && (\n <div className=\"flex gap-1\">\n <button\n type=\"button\"\n onClick={() => handleCartAction(cart, 'approve')}\n className=\"rounded p-1.5 text-text-secondary hover:text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <CheckCircle2 className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => handleCartAction(cart, 'reject')}\n className=\"rounded p-1.5 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <XCircle className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n {cart.isActive && (\n <button\n type=\"button\"\n onClick={() => handleCartAction(cart, 'suspend')}\n className=\"rounded p-1.5 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <Pause className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {carts.length === 0 && (\n <EmptyState\n illustration=\"empty-search\"\n title=\"No carts found\"\n description=\"No service providers match your current filters. Try clearing the filters or searching for a different name.\"\n action={\n <button\n type=\"button\"\n onClick={() =>\n setFilters({\n searchQuery: '',\n status: '',\n verificationStatus: '',\n category: '',\n location: '',\n sortBy: 'recent',\n })\n }\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Clear filters\n </button>\n }\n />\n )}\n </div>\n\n {/* Cart Action Modal */}\n {showCartModal && selectedCart && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\">\n <div className=\"w-full max-w-2xl rounded-lg border border-border-subtle bg-bg-surface shadow-lg max-h-[90vh] overflow-y-auto\">\n <div className=\"flex items-center justify-between p-4 border-b border-border-subtle\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {actionType === 'view'\n ? 'Cart Details'\n : actionType === 'approve'\n ? 'Approve Cart'\n : actionType === 'reject'\n ? 'Reject Cart'\n : 'Suspend Cart'}\n </h3>\n <button\n type=\"button\"\n onClick={() => setShowCartModal(false)}\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-accent transition-colors\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n <div className=\"p-4 space-y-4\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Cart Name</p>\n <p className=\"font-medium text-text-primary\">{selectedCart.name}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Category</p>\n <p className=\"font-medium text-text-primary\">{selectedCart.category}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Owner</p>\n <p className=\"font-medium text-text-primary\">{selectedCart.ownerName}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Contact</p>\n <p className=\"font-medium text-text-primary\">{selectedCart.ownerPhone}</p>\n </div>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Description</p>\n <p className=\"font-medium text-text-primary\">{selectedCart.description}</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Location</p>\n <p className=\"font-medium text-text-primary\">{selectedCart.address}</p>\n </div>\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Compliance Score</p>\n <p className=\"font-medium text-text-primary\">{selectedCart.complianceScore}%</p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Documents</p>\n <p className=\"font-medium text-text-primary\">\n {selectedCart.documentsSubmitted}/{selectedCart.documentsRequired}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Monthly Revenue</p>\n <p className=\"font-medium text-text-primary\">\n {formatCurrency(selectedCart.monthlyRevenue, { minimumFractionDigits: 0 })}\n </p>\n </div>\n </div>\n\n {selectedCart.rejectionReason && (\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle p-4\">\n <p className=\"text-sm font-medium text-status-error-text\">\n Previous Rejection Reason:\n </p>\n <p className=\"text-sm text-status-error-text/80\">\n {selectedCart.rejectionReason}\n </p>\n </div>\n )}\n\n {actionType === 'reject' && (\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n Rejection Reason *\n </label>\n <textarea\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface p-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] min-h-[100px]\"\n rows={4}\n value={rejectionReason}\n onChange={(e) => setRejectionReason(e.target.value)}\n placeholder=\"Please provide a detailed reason for rejection...\"\n />\n </div>\n )}\n\n {actionType === 'approve' && (\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\">\n This marks the cart as verified and active on the platform, so customers can\n start ordering from it.\n </p>\n </div>\n )}\n\n <div className=\"flex gap-3 pt-2\">\n <button\n type=\"button\"\n onClick={() => setShowCartModal(false)}\n className=\"flex-1 rounded-lg border border-border-subtle py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Cancel\n </button>\n {actionType !== 'view' && (\n <button\n type=\"button\"\n onClick={executeCartAction}\n disabled={\n updateProvider.isPending ||\n (actionType === 'reject' && !rejectionReason.trim())\n }\n className=\"flex-1 rounded-lg bg-action-primary-bg py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {updateProvider.isPending\n ? 'Working...'\n : actionType === 'approve'\n ? 'Approve Cart'\n : actionType === 'reject'\n ? 'Reject Cart'\n : 'Suspend Cart'}\n </button>\n )}\n </div>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CartManagementPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/admin/CartManagementPage.tsx"],"sourcesContent":["/**\n * Merchant (Cart) Management Page\n * @module kadaikodi/pages/admin\n *\n * Merchant management wired to the live backend (useProviders +\n * useUpdateProvider). Status tabs, the merchant table, expandable detail rows\n * and the approve / verify / suspend / reject actions all operate on real\n * provider records. Approve→VERIFIED, Suspend→SUSPENDED and Reject→ARCHIVED\n * persist via useUpdateProvider. Fields with no backend source (verification\n * documents, monthly revenue) are omitted rather than fabricated.\n */\n\nimport { Fragment, useState, useMemo } from 'react';\nimport {\n Search,\n Store,\n CheckCircle2,\n Star,\n Loader2,\n X,\n AlertCircle,\n ChevronDown,\n MapPin,\n Calendar,\n IndianRupee,\n FileText,\n} from 'lucide-react';\nimport { GlassCard, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { StatCard, SegmentedTabs } from '../../components/viz';\nimport { useProviders, useUpdateProvider } from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency } from '../../utils/formatters';\nimport type { MockCart } from '../../types';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\ntype MerchantStatus = 'verified' | 'pending' | 'inactive';\ntype StatusTab = 'all' | MerchantStatus;\ntype CartActionType = 'approve' | 'reject' | 'suspend';\n\ninterface MerchantVM {\n id: string;\n name: string;\n category: string;\n ownerId: string;\n address: string;\n rating: number;\n reviewCount: number;\n avgOrderValue: number;\n serviceTypes: string[];\n isOpen: boolean;\n isVerified: boolean;\n status: MerchantStatus;\n createdAt: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Provider → merchant view-model (real data only) */\n/* ------------------------------------------------------------------ */\n\nconst titleCase = (s: string) =>\n s\n .replace(/_/g, ' ')\n .toLowerCase()\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n\nfunction toMerchant(p: MockCart): MerchantVM {\n const status: MerchantStatus = p.isVerified ? 'verified' : p.isOpen ? 'pending' : 'inactive';\n return {\n id: p.id,\n name: p.name,\n category: p.category,\n ownerId: p.ownerId ?? '',\n address: p.location?.address ?? '',\n rating: p.rating,\n reviewCount: p.totalRatings,\n avgOrderValue: p.averageOrderValue ?? 0,\n serviceTypes: p.serviceTypes ?? [],\n isOpen: p.isOpen,\n isVerified: p.isVerified ?? false,\n status,\n createdAt: p.createdAt ?? new Date().toISOString(),\n };\n}\n\nconst STATUS_META: Record<MerchantStatus, { label: string; cls: string }> = {\n verified: { label: 'Verified', cls: 'bg-status-success-bg-subtle text-status-success-text' },\n pending: { label: 'Pending', cls: 'bg-status-warning-bg-subtle text-status-warning-text' },\n inactive: { label: 'Inactive', cls: 'bg-bg-sunken text-text-secondary' },\n};\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function CartManagementPage() {\n const { data: providers = [], isLoading: loading } = useProviders();\n const updateProvider = useUpdateProvider();\n\n const [statusMessage, setStatusMessage] = useState<{\n text: string;\n type: 'success' | 'error';\n } | null>(null);\n const showStatus = (text: string, type: 'success' | 'error') => {\n setStatusMessage({ text, type });\n setTimeout(() => setStatusMessage(null), 3500);\n };\n\n const [statusTab, setStatusTab] = useState<StatusTab>('all');\n const [searchQuery, setSearchQuery] = useState('');\n const [category, setCategory] = useState('');\n const [sortBy, setSortBy] = useState('recent');\n const [expandedId, setExpandedId] = useState<string | null>(null);\n\n const [selected, setSelected] = useState<MerchantVM | null>(null);\n const [actionType, setActionType] = useState<CartActionType>('approve');\n const [showModal, setShowModal] = useState(false);\n const [rejectionReason, setRejectionReason] = useState('');\n\n const merchants = useMemo(() => providers.map(toMerchant), [providers]);\n\n const counts = useMemo(\n () => ({\n all: merchants.length,\n verified: merchants.filter((m) => m.status === 'verified').length,\n pending: merchants.filter((m) => m.status === 'pending').length,\n inactive: merchants.filter((m) => m.status === 'inactive').length,\n }),\n [merchants]\n );\n\n const avgRating = useMemo(() => {\n const rated = merchants.filter((m) => m.rating > 0);\n if (rated.length === 0) return 0;\n return rated.reduce((s, m) => s + m.rating, 0) / rated.length;\n }, [merchants]);\n\n const categories = useMemo(\n () => Array.from(new Set(merchants.map((m) => m.category))).sort(),\n [merchants]\n );\n\n const rows = useMemo(() => {\n let list = [...merchants];\n if (statusTab !== 'all') list = list.filter((m) => m.status === statusTab);\n if (category) list = list.filter((m) => m.category === category);\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n list = list.filter(\n (m) =>\n m.name.toLowerCase().includes(q) ||\n m.category.toLowerCase().includes(q) ||\n m.address.toLowerCase().includes(q)\n );\n }\n switch (sortBy) {\n case 'name':\n list.sort((a, b) => a.name.localeCompare(b.name));\n break;\n case 'rating':\n list.sort((a, b) => b.rating - a.rating);\n break;\n case 'value':\n list.sort((a, b) => b.avgOrderValue - a.avgOrderValue);\n break;\n default:\n list.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n }\n return list;\n }, [merchants, statusTab, category, searchQuery, sortBy]);\n\n const fmtCur = (n: number) => formatCurrency(n, { minimumFractionDigits: 0 });\n const formatDate = (d: string) =>\n new Date(d).toLocaleDateString('en-IN', { year: 'numeric', month: 'short', day: 'numeric' });\n\n const openAction = (merchant: MerchantVM, action: CartActionType) => {\n setSelected(merchant);\n setActionType(action);\n setRejectionReason('');\n setShowModal(true);\n };\n\n const executeAction = () => {\n if (!selected) return;\n if (actionType === 'reject' && !rejectionReason.trim()) {\n showStatus('Please provide a rejection reason', 'error');\n return;\n }\n const status =\n actionType === 'approve' ? 'VERIFIED' : actionType === 'reject' ? 'ARCHIVED' : 'SUSPENDED';\n updateProvider.mutate(\n { id: selected.id, input: { status } },\n {\n onSuccess: () => {\n const verb =\n actionType === 'approve'\n ? 'approved & verified'\n : actionType === 'reject'\n ? 'rejected'\n : 'suspended';\n showStatus(`\"${selected.name}\" ${verb}.`, 'success');\n setShowModal(false);\n setRejectionReason('');\n },\n onError: () =>\n showStatus(`Could not ${actionType} \"${selected.name}\". Please try again.`, 'error'),\n }\n );\n };\n\n const StatusPill = ({ status }: { status: MerchantStatus }) => (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',\n STATUS_META[status].cls\n )}\n >\n {STATUS_META[status].label}\n </span>\n );\n\n const RowActions = ({ m, compact }: { m: MerchantVM; compact?: boolean }) => (\n <div className={cn('flex gap-2', compact ? 'flex-wrap' : 'items-center justify-end')}>\n {!m.isVerified && (\n <button\n type=\"button\"\n onClick={() => openAction(m, 'approve')}\n className=\"rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n Approve\n </button>\n )}\n {m.status !== 'inactive' && (\n <button\n type=\"button\"\n onClick={() => openAction(m, 'suspend')}\n className=\"rounded-lg border border-border-default px-3 py-1.5 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle\"\n >\n Suspend\n </button>\n )}\n </div>\n );\n\n const MerchantDetail = ({ m }: { m: MerchantVM }) => (\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/40 p-4\">\n <div className=\"grid grid-cols-1 gap-6 md:grid-cols-2\">\n <div>\n <h4 className=\"mb-3 text-sm font-semibold text-text-primary\">Business Details</h4>\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex gap-2\">\n <dt className=\"w-28 shrink-0 text-text-secondary\">Merchant</dt>\n <dd className=\"font-medium text-text-primary\">{m.name}</dd>\n </div>\n <div className=\"flex gap-2\">\n <dt className=\"w-28 shrink-0 text-text-secondary\">Category</dt>\n <dd className=\"text-text-primary\">{titleCase(m.category)}</dd>\n </div>\n {m.address && (\n <div className=\"flex gap-2\">\n <dt className=\"w-28 shrink-0 text-text-secondary\">Address</dt>\n <dd className=\"flex items-start gap-1 text-text-primary\">\n <MapPin className=\"mt-0.5 h-3.5 w-3.5 shrink-0 text-text-secondary\" />\n {m.address}\n </dd>\n </div>\n )}\n <div className=\"flex gap-2\">\n <dt className=\"w-28 shrink-0 text-text-secondary\">Applied</dt>\n <dd className=\"flex items-center gap-1 text-text-primary\">\n <Calendar className=\"h-3.5 w-3.5 text-text-secondary\" />\n {formatDate(m.createdAt)}\n </dd>\n </div>\n {m.ownerId && (\n <div className=\"flex gap-2\">\n <dt className=\"w-28 shrink-0 text-text-secondary\">Owner ID</dt>\n <dd className=\"truncate font-mono text-xs text-text-primary\">{m.ownerId}</dd>\n </div>\n )}\n </dl>\n </div>\n <div>\n <h4 className=\"mb-3 text-sm font-semibold text-text-primary\">Performance</h4>\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3\">\n <p className=\"text-xs text-text-secondary\">Rating</p>\n <p className=\"flex items-center gap-1 text-lg font-bold text-text-primary\">\n <Star className=\"h-4 w-4 fill-status-warning-text text-status-warning-text\" />\n {m.rating > 0 ? m.rating.toFixed(1) : '—'}\n </p>\n <p className=\"text-xs text-text-secondary\">{m.reviewCount} reviews</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3\">\n <p className=\"text-xs text-text-secondary\">Avg Order Value</p>\n <p className=\"flex items-center gap-0.5 text-lg font-bold text-text-primary\">\n <IndianRupee className=\"h-3.5 w-3.5\" />\n {m.avgOrderValue > 0 ? m.avgOrderValue.toLocaleString('en-IN') : '—'}\n </p>\n </div>\n </div>\n {m.serviceTypes.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1.5\">\n {m.serviceTypes.map((s) => (\n <span\n key={s}\n className=\"rounded-full bg-bg-surface px-2 py-0.5 text-xs text-text-secondary\"\n >\n {titleCase(s)}\n </span>\n ))}\n </div>\n )}\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-col items-start justify-between gap-3 border-t border-border-subtle pt-4 sm:flex-row sm:items-center\">\n <p className=\"flex items-center gap-1.5 text-xs text-text-muted\">\n <FileText className=\"h-3.5 w-3.5\" />\n Verification documents are not stored on the platform yet.\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {!m.isVerified && (\n <button\n type=\"button\"\n onClick={() => openAction(m, 'reject')}\n className=\"rounded-lg border border-status-error-text/40 px-3 py-1.5 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle\"\n >\n Reject\n </button>\n )}\n {!m.isVerified && (\n <button\n type=\"button\"\n onClick={() => openAction(m, 'approve')}\n className=\"rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n Approve Merchant\n </button>\n )}\n {m.status !== 'inactive' && (\n <button\n type=\"button\"\n onClick={() => openAction(m, 'suspend')}\n className=\"rounded-lg border border-border-default px-3 py-1.5 text-sm font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle\"\n >\n Suspend\n </button>\n )}\n </div>\n </div>\n </div>\n );\n\n if (loading) {\n return (\n <PageLayout title=\"Merchants\" description=\"Loading merchants...\">\n <div className=\"flex flex-col items-center justify-center py-20\">\n <Loader2 className=\"mb-4 h-10 w-10 animate-spin text-text-secondary\" />\n <p className=\"text-text-secondary\">Loading merchants...</p>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Merchants\"\n description={`${counts.all} merchants on the platform · ${counts.pending} awaiting review`}\n >\n <PagePurpose className=\"mb-6\">\n Onboard and oversee every merchant (cart) on Kadaikodi. Approve and verify legitimate\n businesses, suspend ones that break the rules, and keep an eye on ratings and performance —\n so customers only ever see trustworthy, active merchants.\n </PagePurpose>\n\n {statusMessage && (\n <div\n className={cn(\n 'mb-6 flex items-center gap-2 rounded-lg border p-3',\n statusMessage.type === 'success'\n ? 'border-status-success-text/30 bg-status-success-bg-subtle'\n : 'border-status-error-text/30 bg-status-error-bg-subtle'\n )}\n >\n {statusMessage.type === 'success' ? (\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertCircle className=\"h-4 w-4 text-status-error-text\" />\n )}\n <span\n className={cn(\n 'text-sm font-medium',\n statusMessage.type === 'success'\n ? 'text-status-success-text'\n : 'text-status-error-text'\n )}\n >\n {statusMessage.text}\n </span>\n </div>\n )}\n\n {/* KPI row */}\n <div className=\"mb-6 grid grid-cols-2 gap-4 lg:grid-cols-4\">\n <StatCard label=\"Total Merchants\" value={counts.all.toLocaleString('en-IN')} icon={<Store className=\"h-4 w-4\" />} />\n <StatCard label=\"Pending Review\" value={counts.pending.toLocaleString('en-IN')} icon={<AlertCircle className=\"h-4 w-4\" />} />\n <StatCard label=\"Verified\" value={counts.verified.toLocaleString('en-IN')} icon={<CheckCircle2 className=\"h-4 w-4\" />} />\n <StatCard label=\"Avg Rating\" value={avgRating > 0 ? avgRating.toFixed(1) : '—'} icon={<Star className=\"h-4 w-4\" />} />\n </div>\n\n {/* Tabs + search */}\n <div className=\"mb-6 flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"overflow-x-auto\">\n <SegmentedTabs\n aria-label=\"Filter merchants by status\"\n value={statusTab}\n onChange={(id) => setStatusTab(id as StatusTab)}\n tabs={[\n { id: 'all', label: 'All', count: counts.all },\n { id: 'pending', label: 'Pending', count: counts.pending },\n { id: 'verified', label: 'Verified', count: counts.verified },\n { id: 'inactive', label: 'Inactive', count: counts.inactive },\n ]}\n />\n </div>\n <div className=\"flex flex-col gap-3 sm:flex-row\">\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search merchants...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 pl-10 pr-4 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] sm:w-64\"\n />\n </div>\n <select\n value={category}\n onChange={(e) => setCategory(e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">All Categories</option>\n {categories.map((c) => (\n <option key={c} value={c}>\n {titleCase(c)}\n </option>\n ))}\n </select>\n <select\n value={sortBy}\n onChange={(e) => setSortBy(e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"recent\">Most Recent</option>\n <option value=\"name\">Name A–Z</option>\n <option value=\"rating\">Highest Rated</option>\n <option value=\"value\">Highest Avg Order</option>\n </select>\n </div>\n </div>\n\n {/* Merchant table / cards */}\n {rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-search\"\n title=\"No merchants found\"\n description=\"No merchants match your current filters. Try clearing the search or switching tabs.\"\n action={\n <button\n type=\"button\"\n onClick={() => {\n setSearchQuery('');\n setCategory('');\n setStatusTab('all');\n }}\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n Clear filters\n </button>\n }\n />\n ) : (\n <GlassCard treatment=\"plain\" className=\"overflow-hidden\">\n {/* Desktop table */}\n <div className=\"hidden overflow-x-auto md:block\">\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 uppercase tracking-wider text-text-secondary\">\n Merchant\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-text-secondary\">\n Category\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-text-secondary\">\n Status\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-text-secondary\">\n Rating\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-text-secondary\">\n Avg Order\n </th>\n <th className=\"px-4 py-3 text-right text-xs font-medium uppercase tracking-wider text-text-secondary\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {rows.map((m) => {\n const expanded = expandedId === m.id;\n return (\n <Fragment key={m.id}>\n <tr className=\"transition-colors hover:bg-accent/50\">\n <td className=\"px-4 py-3\">\n <button\n type=\"button\"\n onClick={() => setExpandedId(expanded ? null : m.id)}\n className=\"flex items-center gap-3 text-left\"\n >\n <ChevronDown\n className={cn(\n 'h-4 w-4 shrink-0 text-text-secondary transition-transform',\n expanded && 'rotate-180'\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 <Store className=\"h-5 w-5\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {m.name}\n </p>\n {m.address && (\n <p className=\"truncate text-xs text-text-secondary\">{m.address}</p>\n )}\n </div>\n </button>\n </td>\n <td className=\"px-4 py-3 text-sm text-text-secondary\">\n {titleCase(m.category)}\n </td>\n <td className=\"px-4 py-3\">\n <StatusPill status={m.status} />\n </td>\n <td className=\"px-4 py-3 text-sm\">\n {m.rating > 0 ? (\n <span className=\"flex items-center gap-1 text-text-primary\">\n <Star className=\"h-3.5 w-3.5 fill-status-warning-text text-status-warning-text\" />\n {m.rating.toFixed(1)}\n <span className=\"text-text-secondary\">({m.reviewCount})</span>\n </span>\n ) : (\n <span className=\"text-text-secondary\">—</span>\n )}\n </td>\n <td className=\"px-4 py-3 text-sm text-text-primary\">\n {m.avgOrderValue > 0 ? fmtCur(m.avgOrderValue) : '—'}\n </td>\n <td className=\"px-4 py-3\">\n <RowActions m={m} />\n </td>\n </tr>\n {expanded && (\n <tr className=\"bg-bg-sunken/20\">\n <td colSpan={6} className=\"px-4 py-4\">\n <MerchantDetail m={m} />\n </td>\n </tr>\n )}\n </Fragment>\n );\n })}\n </tbody>\n </table>\n </div>\n\n {/* Mobile cards */}\n <div className=\"space-y-4 p-4 md:hidden\">\n {rows.map((m) => {\n const expanded = expandedId === m.id;\n return (\n <div\n key={m.id}\n className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-4\"\n >\n <div className=\"mb-3 flex items-start gap-3\">\n <div className=\"flex h-12 w-12 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary\">\n <Store className=\"h-6 w-6\" />\n </div>\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"truncate font-medium text-text-primary\">{m.name}</h3>\n <p className=\"truncate text-sm text-text-secondary\">{titleCase(m.category)}</p>\n {m.address && (\n <p className=\"truncate text-xs text-text-secondary\">{m.address}</p>\n )}\n </div>\n </div>\n <div className=\"mb-3 flex flex-wrap items-center gap-2\">\n <StatusPill status={m.status} />\n {m.rating > 0 && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-status-warning-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-warning-text\">\n <Star className=\"h-3 w-3 fill-current\" />\n {m.rating.toFixed(1)} ({m.reviewCount})\n </span>\n )}\n {m.avgOrderValue > 0 && (\n <span className=\"text-xs text-text-secondary\">\n Avg {fmtCur(m.avgOrderValue)}\n </span>\n )}\n </div>\n <div className=\"mb-3\">\n <RowActions m={m} compact />\n </div>\n <button\n type=\"button\"\n onClick={() => setExpandedId(expanded ? null : m.id)}\n className=\"flex w-full items-center justify-center gap-1 rounded-lg border border-border-subtle py-1.5 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n {expanded ? 'Hide details' : 'View details'}\n <ChevronDown\n className={cn('h-4 w-4 transition-transform', expanded && 'rotate-180')}\n />\n </button>\n {expanded && (\n <div className=\"mt-3\">\n <MerchantDetail m={m} />\n </div>\n )}\n </div>\n );\n })}\n </div>\n </GlassCard>\n )}\n\n {/* Confirmation modal */}\n {showModal && selected && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\">\n <div className=\"max-h-[90vh] w-full max-w-lg overflow-y-auto rounded-lg border border-border-subtle bg-bg-surface shadow-lg\">\n <div className=\"flex items-center justify-between border-b border-border-subtle p-4\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {actionType === 'approve'\n ? 'Approve Merchant'\n : actionType === 'reject'\n ? 'Reject Merchant'\n : 'Suspend Merchant'}\n </h3>\n <button\n type=\"button\"\n onClick={() => setShowModal(false)}\n className=\"rounded p-1.5 text-text-secondary transition-colors hover:bg-accent hover:text-text-primary\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n <div className=\"space-y-4 p-4\">\n <div className=\"flex items-center gap-3 rounded-lg bg-bg-sunken/50 p-3\">\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary\">\n <Store className=\"h-5 w-5\" />\n </div>\n <div className=\"min-w-0\">\n <p className=\"truncate font-medium text-text-primary\">{selected.name}</p>\n <p className=\"truncate text-sm text-text-secondary\">\n {titleCase(selected.category)}\n </p>\n </div>\n </div>\n\n {actionType === 'approve' && (\n <div className=\"rounded-lg border border-status-success-text/30 bg-status-success-bg-subtle p-3\">\n <p className=\"text-sm text-status-success-text\">\n This marks the merchant as verified and active, so customers can start ordering\n from it.\n </p>\n </div>\n )}\n {actionType === 'suspend' && (\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle p-3\">\n <p className=\"text-sm text-status-error-text\">\n This suspends the merchant. It will be hidden from customers until reinstated.\n </p>\n </div>\n )}\n {actionType === 'reject' && (\n <div>\n <label className=\"mb-2 block text-sm font-medium text-text-primary\">\n Rejection Reason *\n </label>\n <textarea\n className=\"min-h-[100px] w-full rounded-lg border border-border-subtle bg-bg-surface p-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n rows={4}\n value={rejectionReason}\n onChange={(e) => setRejectionReason(e.target.value)}\n placeholder=\"Explain why this application is being rejected...\"\n />\n </div>\n )}\n\n <div className=\"flex gap-3 pt-2\">\n <button\n type=\"button\"\n onClick={() => setShowModal(false)}\n className=\"flex-1 rounded-lg border border-border-subtle py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={executeAction}\n disabled={\n updateProvider.isPending || (actionType === 'reject' && !rejectionReason.trim())\n }\n className=\"flex-1 rounded-lg bg-action-primary-bg py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {updateProvider.isPending\n ? 'Working…'\n : actionType === 'approve'\n ? 'Approve Merchant'\n : actionType === 'reject'\n ? 'Reject Merchant'\n : 'Suspend Merchant'}\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Management Page
|
|
3
|
+
* @module kadaikodi/pages/admin
|
|
4
|
+
*
|
|
5
|
+
* Full-featured user management with 8 stats cards, 5 filter controls,
|
|
6
|
+
* dual layout (mobile cards + desktop table), user action modal
|
|
7
|
+
* (edit form + delete confirmation), pagination, and loading state.
|
|
8
|
+
*/
|
|
9
|
+
export declare function UserManagementPage(): import("react").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=UserManagementPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserManagementPage.d.ts","sourceRoot":"","sources":["../../../../src/kadaikodi/pages/admin/UserManagementPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiGH,wBAAgB,kBAAkB,gCAivBjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserManagementPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/admin/UserManagementPage.tsx"],"sourcesContent":["/**\n * User Management Page\n * @module kadaikodi/pages/admin\n *\n * Full-featured user management with 8 stats cards, 5 filter controls,\n * dual layout (mobile cards + desktop table), user action modal\n * (edit form + delete confirmation), pagination, and loading state.\n */\n\nimport { useState, useMemo } from 'react';\nimport {\n Search,\n Users,\n UserCheck,\n UserX,\n Shield,\n Eye,\n CheckCircle2,\n AlertCircle,\n Loader2,\n ChevronLeft,\n ChevronRight,\n Smartphone,\n Mail,\n Phone,\n X,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useProviders, useUpdateProvider } from '../../hooks/useKadaikodiApi';\nimport type { MockCart } from '../../types';\nimport { cn } from '../../utils/cn';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\ninterface ExtendedUser {\n id: string;\n providerId: string;\n email: string;\n phone: string;\n firstName: string;\n lastName: string;\n role: 'customer' | 'cart_owner' | 'worker' | 'investor' | 'admin';\n isEmailVerified: boolean;\n isPhoneVerified: boolean;\n profilePicture: string;\n status: 'active' | 'inactive' | 'suspended' | 'pending';\n lastLoginTime?: string;\n totalOrders?: number;\n totalSpent?: number;\n totalEarnings?: number;\n kycStatus?: 'pending' | 'verified' | 'rejected';\n riskScore?: number;\n registrationDate: string;\n deviceInfo?: string;\n}\n\ninterface UserFilters {\n role: string;\n status: string;\n searchQuery: string;\n sortBy: string;\n registrationDate: string;\n}\n\ninterface UserStats {\n totalUsers: number;\n activeUsers: number;\n newUsers: number;\n verifiedUsers: number;\n customers: number;\n cartOwners: number;\n workers: number;\n investors: number;\n}\n\n/* ------------------------------------------------------------------ */\n/* Real data mapping — cart owners are real users (service providers). */\n/* No users endpoint exists, so we never fabricate accounts. */\n/* ------------------------------------------------------------------ */\n\nconst providerToUser = (p: MockCart): ExtendedUser => ({\n id: p.ownerId ?? p.id,\n providerId: p.id,\n email: '',\n phone: '',\n firstName: p.name,\n lastName: '',\n role: 'cart_owner',\n isEmailVerified: Boolean(p.isVerified),\n isPhoneVerified: false,\n profilePicture: '',\n status: p.isOpen ? 'active' : 'inactive',\n registrationDate: p.createdAt ?? new Date(0).toISOString(),\n});\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function UserManagementPage() {\n const { navigateTo } = useKadaikodi();\n\n const { data: providers = [], isLoading: loading } = useProviders();\n const updateProvider = useUpdateProvider();\n const [selectedUser, setSelectedUser] = useState<ExtendedUser | null>(null);\n const [showUserModal, setShowUserModal] = useState(false);\n const [statusMessage, setStatusMessage] = useState<{\n text: string;\n type: 'success' | 'error';\n } | null>(null);\n const showStatus = (text: string, type: 'success' | 'error') => {\n setStatusMessage({ text, type });\n setTimeout(() => setStatusMessage(null), 3500);\n };\n const [currentPage, setCurrentPage] = useState(1);\n const itemsPerPage = 10;\n\n const [filters, setFilters] = useState<UserFilters>({\n role: '',\n status: '',\n searchQuery: '',\n sortBy: 'recent',\n registrationDate: '',\n });\n\n // Real user base: cart owners derived from the live service-provider list.\n const allUsers = useMemo<ExtendedUser[]>(() => providers.map(providerToUser), [providers]);\n\n const users = useMemo<ExtendedUser[]>(() => {\n let filtered = [...allUsers];\n\n if (filters.searchQuery) {\n const q = filters.searchQuery.toLowerCase();\n filtered = filtered.filter(\n (u) =>\n u.firstName.toLowerCase().includes(q) ||\n u.lastName.toLowerCase().includes(q) ||\n u.email.toLowerCase().includes(q) ||\n u.phone.includes(q)\n );\n }\n if (filters.role) filtered = filtered.filter((u) => u.role === filters.role);\n if (filters.status) filtered = filtered.filter((u) => u.status === filters.status);\n if (filters.registrationDate) {\n const days = parseInt(filters.registrationDate);\n const cutoff = new Date(Date.now() - days * 86400000);\n filtered = filtered.filter((u) => new Date(u.registrationDate) >= cutoff);\n }\n\n switch (filters.sortBy) {\n case 'name':\n filtered.sort((a, b) => a.firstName.localeCompare(b.firstName));\n break;\n case 'activity':\n filtered.sort((a, b) => {\n const aT = a.lastLoginTime ? new Date(a.lastLoginTime).getTime() : 0;\n const bT = b.lastLoginTime ? new Date(b.lastLoginTime).getTime() : 0;\n return bT - aT;\n });\n break;\n default:\n filtered.sort(\n (a, b) => new Date(b.registrationDate).getTime() - new Date(a.registrationDate).getTime()\n );\n }\n\n return filtered;\n }, [allUsers, filters]);\n\n const stats = useMemo<UserStats>(() => {\n const thirtyDaysAgo = Date.now() - 30 * 86400000;\n return {\n totalUsers: allUsers.length,\n activeUsers: allUsers.filter((u) => u.status === 'active').length,\n newUsers: allUsers.filter((u) => new Date(u.registrationDate).getTime() >= thirtyDaysAgo)\n .length,\n verifiedUsers: allUsers.filter((u) => u.isEmailVerified).length,\n customers: allUsers.filter((u) => u.role === 'customer').length,\n cartOwners: allUsers.filter((u) => u.role === 'cart_owner').length,\n workers: allUsers.filter((u) => u.role === 'worker').length,\n investors: allUsers.filter((u) => u.role === 'investor').length,\n };\n }, [allUsers]);\n\n const handleFilterChange = (key: keyof UserFilters, value: string) => {\n setFilters((prev) => ({ ...prev, [key]: value }));\n setCurrentPage(1);\n };\n\n const handleUserAction = (\n user: ExtendedUser,\n action: 'view' | 'suspend' | 'activate' | 'verify'\n ) => {\n if (action === 'suspend' || action === 'activate' || action === 'verify') {\n // Every \"user\" here is a cart owner backed by a real service-provider\n // record, so account state persists to the provider status.\n const status =\n action === 'suspend' ? 'SUSPENDED' : action === 'activate' ? 'ACTIVE' : 'VERIFIED';\n const verb = action === 'suspend' ? 'suspended' : action === 'activate' ? 'activated' : 'verified';\n updateProvider.mutate(\n { id: user.providerId, input: { status } },\n {\n onSuccess: () => showStatus(`${user.firstName} ${user.lastName} ${verb}.`, 'success'),\n onError: () =>\n showStatus(`Could not ${action} ${user.firstName}. Please try again.`, 'error'),\n }\n );\n return;\n }\n setSelectedUser(user);\n setShowUserModal(true);\n };\n\n const formatDate = (d: string) =>\n new Date(d).toLocaleDateString('en-IN', { year: 'numeric', month: 'short', day: 'numeric' });\n\n const formatCurrency = (amount: number) => `₹${amount.toLocaleString('en-IN')}`;\n\n const pagedUsers = useMemo(() => {\n const start = (currentPage - 1) * itemsPerPage;\n return users.slice(start, start + itemsPerPage);\n }, [users, currentPage]);\n\n const roleBadge = (role: string) => {\n const c: Record<string, string> = {\n customer: 'bg-[var(--color-accent-soft)] text-text-primary',\n cart_owner: 'bg-status-success-bg-subtle text-status-success-text',\n worker: 'bg-status-warning-bg-subtle text-status-warning-text',\n investor: 'bg-accent-purple-subtle text-text-primary',\n admin: 'bg-status-error-bg-subtle text-status-error-text',\n };\n const l: Record<string, string> = {\n customer: 'Customer',\n cart_owner: 'Cart Owner',\n worker: 'Worker',\n investor: 'Investor',\n admin: 'Admin',\n };\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',\n c[role]\n )}\n >\n {l[role] ?? role}\n </span>\n );\n };\n\n const statusBadge = (status: string) => {\n const c: Record<string, string> = {\n active: 'bg-status-success-bg-subtle text-status-success-text',\n inactive: 'bg-bg-sunken text-text-secondary',\n suspended: 'bg-status-error-bg-subtle text-status-error-text',\n pending: 'bg-status-warning-bg-subtle text-status-warning-text',\n };\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium capitalize',\n c[status]\n )}\n >\n {status}\n </span>\n );\n };\n\n /* ---- Loading ---- */\n if (loading) {\n return (\n <PageLayout title=\"User Management\" description=\"Loading users...\">\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 users...</p>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"User Management\"\n description={`${(stats.totalUsers ?? 0).toLocaleString('en-IN')} registered users on the platform`}\n >\n <PagePurpose className=\"mb-6\">\n The directory of everyone on Kadaikodi — customers, cart owners, workers and investors. Use\n this page to find an account, verify or activate users, edit roles, and step in when someone\n needs help. Filter by role or status to manage one group at a time.\n </PagePurpose>\n\n {statusMessage && (\n <div\n className={cn(\n 'mb-6 flex items-center gap-2 rounded-lg border p-3',\n statusMessage.type === 'success'\n ? 'border-status-success-text/30 bg-status-success-bg-subtle'\n : 'border-status-error-text/30 bg-status-error-bg-subtle'\n )}\n >\n {statusMessage.type === 'success' ? (\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertCircle className=\"h-4 w-4 text-status-error-text\" />\n )}\n <span\n className={cn(\n 'text-sm font-medium',\n statusMessage.type === 'success'\n ? 'text-status-success-text'\n : 'text-status-error-text'\n )}\n >\n {statusMessage.text}\n </span>\n </div>\n )}\n\n {/* 8 Stats Cards — the one emphasis zone for this page */}\n <EmphasisPanel className=\"mb-6\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">User Base Overview</h2>\n <div className=\"grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-8 gap-3\">\n {[\n {\n label: 'Total Users',\n value: (stats.totalUsers ?? 0).toLocaleString('en-IN'),\n cls: '',\n },\n {\n label: 'Active',\n value: (stats.activeUsers ?? 0).toLocaleString('en-IN'),\n cls: 'bg-status-success-bg-subtle border-status-success-text/30',\n },\n {\n label: 'New (30d)',\n value: stats.newUsers.toString(),\n cls: 'bg-[var(--color-accent-soft)] border-border-focus/30',\n },\n {\n label: 'Verified',\n value: (stats.verifiedUsers ?? 0).toLocaleString('en-IN'),\n cls: 'bg-accent-purple-subtle border-accent-purple/30',\n },\n { label: 'Customers', value: (stats.customers ?? 0).toLocaleString('en-IN'), cls: '' },\n { label: 'Cart Owners', value: stats.cartOwners.toString(), cls: '' },\n { label: 'Workers', value: stats.workers.toString(), cls: '' },\n { label: 'Investors', value: stats.investors.toString(), cls: '' },\n ].map((s) => (\n <div\n key={s.label}\n className={cn('rounded-lg border border-border-subtle bg-bg-surface p-3', s.cls)}\n >\n <p className=\"text-xs text-text-secondary\">{s.label}</p>\n <p className=\"text-lg font-bold text-text-primary\">{s.value}</p>\n </div>\n ))}\n </div>\n </EmphasisPanel>\n\n {/* 5 Filter Controls */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 mb-6\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3\">\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search users...\"\n value={filters.searchQuery}\n onChange={(e) => handleFilterChange('searchQuery', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 pl-10 pr-4 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <select\n value={filters.role}\n onChange={(e) => handleFilterChange('role', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">All Roles</option>\n <option value=\"customer\">Customers</option>\n <option value=\"cart_owner\">Cart Owners</option>\n <option value=\"worker\">Workers</option>\n <option value=\"investor\">Investors</option>\n </select>\n <select\n value={filters.status}\n onChange={(e) => handleFilterChange('status', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">All Status</option>\n <option value=\"active\">Active</option>\n <option value=\"inactive\">Inactive</option>\n <option value=\"suspended\">Suspended</option>\n <option value=\"pending\">Pending</option>\n </select>\n <select\n value={filters.registrationDate}\n onChange={(e) => handleFilterChange('registrationDate', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">All Time</option>\n <option value=\"1\">Last 24 hours</option>\n <option value=\"7\">Last 7 days</option>\n <option value=\"30\">Last 30 days</option>\n <option value=\"90\">Last 90 days</option>\n </select>\n <select\n value={filters.sortBy}\n onChange={(e) => handleFilterChange('sortBy', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"recent\">Most Recent</option>\n <option value=\"name\">Name A-Z</option>\n <option value=\"activity\">Last Activity</option>\n </select>\n </div>\n </div>\n\n {/* Dual Layout */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface overflow-hidden\">\n {/* Mobile Card View */}\n <div className=\"block md:hidden space-y-4 p-4\">\n {pagedUsers.map((user) => (\n <div\n key={user.id}\n className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-4\"\n >\n <div className=\"flex items-center mb-3\">\n {user.profilePicture ? (\n <img\n src={user.profilePicture}\n alt={`${user.firstName} ${user.lastName}`}\n className=\"w-12 h-12 rounded-full object-cover mr-3\"\n />\n ) : (\n <div className=\"w-12 h-12 rounded-full bg-bg-sunken flex items-center justify-center mr-3\">\n <Users className=\"h-6 w-6 text-text-secondary\" />\n </div>\n )}\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"font-medium text-text-primary\">\n {user.firstName} {user.lastName}\n </h3>\n <p className=\"text-sm text-text-secondary truncate\">{user.email}</p>\n <p className=\"text-sm text-text-secondary\">{user.phone}</p>\n </div>\n </div>\n <div className=\"flex flex-wrap gap-2 mb-3\">\n {roleBadge(user.role)}\n {statusBadge(user.status)}\n </div>\n <div className=\"grid grid-cols-2 gap-4 text-sm mb-3\">\n <div>\n <p className=\"text-text-secondary\">Registered</p>\n <p className=\"text-text-primary\">{formatDate(user.registrationDate)}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Last Login</p>\n <p className=\"text-text-primary\">\n {user.lastLoginTime ? formatDate(user.lastLoginTime) : 'Never'}\n </p>\n </div>\n </div>\n <div className=\"flex flex-wrap gap-3 mb-3\">\n <div className=\"flex items-center\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full mr-2',\n user.isEmailVerified ? 'bg-status-success-text' : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">Email</span>\n </div>\n <div className=\"flex items-center\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full mr-2',\n user.isPhoneVerified ? 'bg-status-success-text' : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">Phone</span>\n </div>\n {user.kycStatus && (\n <div className=\"flex items-center\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full mr-2',\n user.kycStatus === 'verified'\n ? 'bg-status-success-text'\n : user.kycStatus === 'pending'\n ? 'bg-status-warning-text'\n : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">KYC</span>\n </div>\n )}\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'view')}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n View\n </button>\n {user.status === 'active' ? (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'suspend')}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n Suspend\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'activate')}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-sm font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n Activate\n </button>\n )}\n {user.kycStatus === 'pending' && (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'verify')}\n className=\"rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n Verify\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n\n {/* Desktop Table View */}\n <div className=\"hidden md:block overflow-x-auto\">\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 tracking-wider\">\n User\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Role & Status\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Activity\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Performance\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Verification\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {pagedUsers.map((user) => (\n <tr key={user.id} className=\"hover:bg-accent/50 transition-colors\">\n <td className=\"px-4 py-3\">\n <div className=\"flex items-center gap-3\">\n {user.profilePicture ? (\n <img\n src={user.profilePicture}\n alt={`${user.firstName}`}\n className=\"w-10 h-10 rounded-full object-cover\"\n />\n ) : (\n <div className=\"w-10 h-10 rounded-full bg-bg-sunken flex items-center justify-center\">\n <Users className=\"h-5 w-5 text-text-secondary\" />\n </div>\n )}\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {user.firstName} {user.lastName}\n </p>\n <p className=\"text-xs text-text-secondary\">{user.email}</p>\n <p className=\"text-xs text-text-secondary\">{user.phone}</p>\n </div>\n </div>\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"space-y-1\">\n {roleBadge(user.role)}\n <br />\n {statusBadge(user.status)}\n </div>\n </td>\n <td className=\"px-4 py-3 text-sm\">\n <p className=\"text-text-primary\">\n Registered: {formatDate(user.registrationDate)}\n </p>\n {user.lastLoginTime && (\n <p className=\"text-text-secondary\">\n Last login: {formatDate(user.lastLoginTime)}\n </p>\n )}\n {user.deviceInfo && (\n <p className=\"text-text-secondary flex items-center gap-1\">\n <Smartphone className=\"h-3 w-3\" />\n {user.deviceInfo}\n </p>\n )}\n </td>\n <td className=\"px-4 py-3 text-sm\">\n {user.role === 'customer' && user.totalOrders != null && (\n <>\n <p className=\"text-text-primary\">{user.totalOrders} orders</p>\n <p className=\"text-text-secondary\">\n {formatCurrency(user.totalSpent ?? 0)} spent\n </p>\n </>\n )}\n {(user.role === 'cart_owner' || user.role === 'worker') &&\n user.totalEarnings != null && (\n <p className=\"text-text-primary\">\n {formatCurrency(user.totalEarnings)} earned\n </p>\n )}\n {user.role === 'investor' && user.riskScore != null && (\n <p className=\"text-text-primary\">Risk: {user.riskScore}/5</p>\n )}\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full',\n user.isEmailVerified ? 'bg-status-success-text' : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">Email</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full',\n user.isPhoneVerified ? 'bg-status-success-text' : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">Phone</span>\n </div>\n {user.kycStatus && (\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full',\n user.kycStatus === 'verified'\n ? 'bg-status-success-text'\n : user.kycStatus === 'pending'\n ? 'bg-status-warning-text'\n : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">KYC</span>\n </div>\n )}\n </div>\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"flex gap-1\">\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'view')}\n title=\"View details\"\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-accent transition-colors\"\n >\n <Eye className=\"h-4 w-4\" />\n </button>\n {user.status === 'active' ? (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'suspend')}\n title=\"Suspend\"\n className=\"rounded p-1.5 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <UserX className=\"h-4 w-4\" />\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'activate')}\n title=\"Activate\"\n className=\"rounded p-1.5 text-text-secondary hover:text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <UserCheck className=\"h-4 w-4\" />\n </button>\n )}\n {user.kycStatus === 'pending' && (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'verify')}\n title=\"Verify\"\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-[var(--color-accent-soft)] transition-colors\"\n >\n <Shield className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {users.length === 0 && (\n <EmptyState\n illustration=\"empty-people\"\n title=\"No users found\"\n description=\"No accounts match your current filters. Try clearing them or searching for a different name or email.\"\n action={\n <button\n type=\"button\"\n onClick={() =>\n setFilters({\n role: '',\n status: '',\n searchQuery: '',\n sortBy: 'recent',\n registrationDate: '',\n })\n }\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Clear filters\n </button>\n }\n />\n )}\n </div>\n\n {/* Pagination */}\n <div className=\"mt-6 flex flex-col sm:flex-row sm:items-center justify-between gap-4\">\n <p className=\"text-sm text-text-secondary text-center sm:text-left\">\n Showing{' '}\n <span className=\"font-medium\">\n {Math.min((currentPage - 1) * itemsPerPage + 1, users.length)}\n </span>{' '}\n to{' '}\n <span className=\"font-medium\">{Math.min(currentPage * itemsPerPage, users.length)}</span>{' '}\n of <span className=\"font-medium\">{users.length}</span> results\n </p>\n <div className=\"flex justify-center sm:justify-end gap-2\">\n <button\n type=\"button\"\n disabled={currentPage === 1}\n onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n Previous\n </button>\n <button\n type=\"button\"\n disabled={currentPage * itemsPerPage >= users.length}\n onClick={() => setCurrentPage((p) => p + 1)}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Next\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n\n {/* User Details Modal (read-only) */}\n {showUserModal && selectedUser && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\">\n <div className=\"w-full max-w-md rounded-lg border border-border-subtle bg-bg-surface shadow-lg max-h-[90vh] overflow-y-auto\">\n <div className=\"flex items-center justify-between p-4 border-b border-border-subtle\">\n <h3 className=\"text-lg font-semibold text-text-primary\">User Details</h3>\n <button\n type=\"button\"\n onClick={() => setShowUserModal(false)}\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-accent transition-colors\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n <div className=\"p-4 space-y-4\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Name</p>\n <p className=\"font-medium text-text-primary\">\n {selectedUser.firstName} {selectedUser.lastName}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Role</p>\n <div className=\"mt-0.5\">{roleBadge(selectedUser.role)}</div>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Status</p>\n <div className=\"mt-0.5\">{statusBadge(selectedUser.status)}</div>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Registered</p>\n <p className=\"font-medium text-text-primary\">\n {formatDate(selectedUser.registrationDate)}\n </p>\n </div>\n {selectedUser.email && (\n <div>\n <p className=\"text-sm text-text-secondary\">Email</p>\n <p className=\"font-medium text-text-primary flex items-center gap-1\">\n <Mail className=\"h-3.5 w-3.5\" />\n {selectedUser.email}\n </p>\n </div>\n )}\n {selectedUser.phone && (\n <div>\n <p className=\"text-sm text-text-secondary\">Phone</p>\n <p className=\"font-medium text-text-primary flex items-center gap-1\">\n <Phone className=\"h-3.5 w-3.5\" />\n {selectedUser.phone}\n </p>\n </div>\n )}\n </div>\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/40 p-3\">\n <p className=\"text-sm text-text-secondary\">\n Profile details, email and role are managed by the account platform and can't\n be edited here. Use the Suspend / Activate controls in the list to change this\n account's access.\n </p>\n </div>\n\n <div className=\"flex justify-end\">\n <button\n type=\"button\"\n onClick={() => setShowUserModal(false)}\n className=\"rounded-lg border border-border-subtle py-2 px-4 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Close\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UserManagementPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/admin/UserManagementPage.tsx"],"sourcesContent":["/**\n * User Management Page\n * @module kadaikodi/pages/admin\n *\n * Full-featured user management with 8 stats cards, 5 filter controls,\n * dual layout (mobile cards + desktop table), user action modal\n * (edit form + delete confirmation), pagination, and loading state.\n */\n\nimport { useState, useMemo } from 'react';\nimport {\n Search,\n Users,\n UserCheck,\n UserX,\n Shield,\n Eye,\n CheckCircle2,\n AlertCircle,\n Loader2,\n ChevronLeft,\n ChevronRight,\n Smartphone,\n Mail,\n Phone,\n X,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useProviders, useUpdateProvider } from '../../hooks/useKadaikodiApi';\nimport type { MockCart } from '../../types';\nimport { cn } from '../../utils/cn';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\ninterface ExtendedUser {\n id: string;\n providerId: string;\n email: string;\n phone: string;\n firstName: string;\n lastName: string;\n role: 'customer' | 'cart_owner' | 'worker' | 'investor' | 'admin';\n isEmailVerified: boolean;\n isPhoneVerified: boolean;\n profilePicture: string;\n status: 'active' | 'inactive' | 'suspended' | 'pending';\n lastLoginTime?: string;\n totalOrders?: number;\n totalSpent?: number;\n totalEarnings?: number;\n kycStatus?: 'pending' | 'verified' | 'rejected';\n riskScore?: number;\n registrationDate: string;\n deviceInfo?: string;\n}\n\ninterface UserFilters {\n role: string;\n status: string;\n searchQuery: string;\n sortBy: string;\n registrationDate: string;\n}\n\ninterface UserStats {\n totalUsers: number;\n activeUsers: number;\n newUsers: number;\n verifiedUsers: number;\n customers: number;\n cartOwners: number;\n workers: number;\n investors: number;\n}\n\n/* ------------------------------------------------------------------ */\n/* Real data mapping — cart owners are real users (service providers). */\n/* No users endpoint exists, so we never fabricate accounts. */\n/* ------------------------------------------------------------------ */\n\nconst providerToUser = (p: MockCart): ExtendedUser => ({\n id: p.ownerId ?? p.id,\n providerId: p.id,\n email: '',\n phone: '',\n firstName: p.name,\n lastName: '',\n role: 'cart_owner',\n isEmailVerified: Boolean(p.isVerified),\n isPhoneVerified: false,\n profilePicture: '',\n status: p.isOpen ? 'active' : 'inactive',\n registrationDate: p.createdAt ?? new Date(0).toISOString(),\n});\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport function UserManagementPage() {\n const { navigateTo } = useKadaikodi();\n\n const { data: providers = [], isLoading: loading } = useProviders();\n const updateProvider = useUpdateProvider();\n const [selectedUser, setSelectedUser] = useState<ExtendedUser | null>(null);\n const [showUserModal, setShowUserModal] = useState(false);\n const [statusMessage, setStatusMessage] = useState<{\n text: string;\n type: 'success' | 'error';\n } | null>(null);\n const showStatus = (text: string, type: 'success' | 'error') => {\n setStatusMessage({ text, type });\n setTimeout(() => setStatusMessage(null), 3500);\n };\n const [currentPage, setCurrentPage] = useState(1);\n const itemsPerPage = 10;\n\n const [filters, setFilters] = useState<UserFilters>({\n role: '',\n status: '',\n searchQuery: '',\n sortBy: 'recent',\n registrationDate: '',\n });\n\n // Real user base: cart owners derived from the live service-provider list.\n const allUsers = useMemo<ExtendedUser[]>(() => providers.map(providerToUser), [providers]);\n\n const users = useMemo<ExtendedUser[]>(() => {\n let filtered = [...allUsers];\n\n if (filters.searchQuery) {\n const q = filters.searchQuery.toLowerCase();\n filtered = filtered.filter(\n (u) =>\n u.firstName.toLowerCase().includes(q) ||\n u.lastName.toLowerCase().includes(q) ||\n u.email.toLowerCase().includes(q) ||\n u.phone.includes(q)\n );\n }\n if (filters.role) filtered = filtered.filter((u) => u.role === filters.role);\n if (filters.status) filtered = filtered.filter((u) => u.status === filters.status);\n if (filters.registrationDate) {\n const days = parseInt(filters.registrationDate);\n const cutoff = new Date(Date.now() - days * 86400000);\n filtered = filtered.filter((u) => new Date(u.registrationDate) >= cutoff);\n }\n\n switch (filters.sortBy) {\n case 'name':\n filtered.sort((a, b) => a.firstName.localeCompare(b.firstName));\n break;\n case 'activity':\n filtered.sort((a, b) => {\n const aT = a.lastLoginTime ? new Date(a.lastLoginTime).getTime() : 0;\n const bT = b.lastLoginTime ? new Date(b.lastLoginTime).getTime() : 0;\n return bT - aT;\n });\n break;\n default:\n filtered.sort(\n (a, b) => new Date(b.registrationDate).getTime() - new Date(a.registrationDate).getTime()\n );\n }\n\n return filtered;\n }, [allUsers, filters]);\n\n const stats = useMemo<UserStats>(() => {\n const thirtyDaysAgo = Date.now() - 30 * 86400000;\n return {\n totalUsers: allUsers.length,\n activeUsers: allUsers.filter((u) => u.status === 'active').length,\n newUsers: allUsers.filter((u) => new Date(u.registrationDate).getTime() >= thirtyDaysAgo)\n .length,\n verifiedUsers: allUsers.filter((u) => u.isEmailVerified).length,\n customers: allUsers.filter((u) => u.role === 'customer').length,\n cartOwners: allUsers.filter((u) => u.role === 'cart_owner').length,\n workers: allUsers.filter((u) => u.role === 'worker').length,\n investors: allUsers.filter((u) => u.role === 'investor').length,\n };\n }, [allUsers]);\n\n const handleFilterChange = (key: keyof UserFilters, value: string) => {\n setFilters((prev) => ({ ...prev, [key]: value }));\n setCurrentPage(1);\n };\n\n const handleUserAction = (\n user: ExtendedUser,\n action: 'view' | 'suspend' | 'activate' | 'verify'\n ) => {\n if (action === 'suspend' || action === 'activate' || action === 'verify') {\n // Every \"user\" here is a cart owner backed by a real service-provider\n // record, so account state persists to the provider status.\n const status =\n action === 'suspend' ? 'SUSPENDED' : action === 'activate' ? 'ACTIVE' : 'VERIFIED';\n const verb =\n action === 'suspend' ? 'suspended' : action === 'activate' ? 'activated' : 'verified';\n updateProvider.mutate(\n { id: user.providerId, input: { status } },\n {\n onSuccess: () => showStatus(`${user.firstName} ${user.lastName} ${verb}.`, 'success'),\n onError: () =>\n showStatus(`Could not ${action} ${user.firstName}. Please try again.`, 'error'),\n }\n );\n return;\n }\n setSelectedUser(user);\n setShowUserModal(true);\n };\n\n const formatDate = (d: string) =>\n new Date(d).toLocaleDateString('en-IN', { year: 'numeric', month: 'short', day: 'numeric' });\n\n const formatCurrency = (amount: number) => `₹${amount.toLocaleString('en-IN')}`;\n\n const pagedUsers = useMemo(() => {\n const start = (currentPage - 1) * itemsPerPage;\n return users.slice(start, start + itemsPerPage);\n }, [users, currentPage]);\n\n const roleBadge = (role: string) => {\n const c: Record<string, string> = {\n customer: 'bg-[var(--color-accent-soft)] text-text-primary',\n cart_owner: 'bg-status-success-bg-subtle text-status-success-text',\n worker: 'bg-status-warning-bg-subtle text-status-warning-text',\n investor: 'bg-accent-purple-subtle text-text-primary',\n admin: 'bg-status-error-bg-subtle text-status-error-text',\n };\n const l: Record<string, string> = {\n customer: 'Customer',\n cart_owner: 'Cart Owner',\n worker: 'Worker',\n investor: 'Investor',\n admin: 'Admin',\n };\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',\n c[role]\n )}\n >\n {l[role] ?? role}\n </span>\n );\n };\n\n const statusBadge = (status: string) => {\n const c: Record<string, string> = {\n active: 'bg-status-success-bg-subtle text-status-success-text',\n inactive: 'bg-bg-sunken text-text-secondary',\n suspended: 'bg-status-error-bg-subtle text-status-error-text',\n pending: 'bg-status-warning-bg-subtle text-status-warning-text',\n };\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium capitalize',\n c[status]\n )}\n >\n {status}\n </span>\n );\n };\n\n /* ---- Loading ---- */\n if (loading) {\n return (\n <PageLayout title=\"User Management\" description=\"Loading users...\">\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 users...</p>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"User Management\"\n description={`${(stats.totalUsers ?? 0).toLocaleString('en-IN')} registered users on the platform`}\n >\n <PagePurpose className=\"mb-6\">\n The directory of everyone on Kadaikodi — customers, cart owners, workers and investors. Use\n this page to find an account, verify or activate users, edit roles, and step in when someone\n needs help. Filter by role or status to manage one group at a time.\n </PagePurpose>\n\n {statusMessage && (\n <div\n className={cn(\n 'mb-6 flex items-center gap-2 rounded-lg border p-3',\n statusMessage.type === 'success'\n ? 'border-status-success-text/30 bg-status-success-bg-subtle'\n : 'border-status-error-text/30 bg-status-error-bg-subtle'\n )}\n >\n {statusMessage.type === 'success' ? (\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertCircle className=\"h-4 w-4 text-status-error-text\" />\n )}\n <span\n className={cn(\n 'text-sm font-medium',\n statusMessage.type === 'success'\n ? 'text-status-success-text'\n : 'text-status-error-text'\n )}\n >\n {statusMessage.text}\n </span>\n </div>\n )}\n\n {/* 8 Stats Cards — the one emphasis zone for this page */}\n <EmphasisPanel className=\"mb-6\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">User Base Overview</h2>\n <div className=\"grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-8 gap-3\">\n {[\n {\n label: 'Total Users',\n value: (stats.totalUsers ?? 0).toLocaleString('en-IN'),\n cls: '',\n },\n {\n label: 'Active',\n value: (stats.activeUsers ?? 0).toLocaleString('en-IN'),\n cls: 'bg-status-success-bg-subtle border-status-success-text/30',\n },\n {\n label: 'New (30d)',\n value: stats.newUsers.toString(),\n cls: 'bg-[var(--color-accent-soft)] border-border-focus/30',\n },\n {\n label: 'Verified',\n value: (stats.verifiedUsers ?? 0).toLocaleString('en-IN'),\n cls: 'bg-accent-purple-subtle border-accent-purple/30',\n },\n { label: 'Customers', value: (stats.customers ?? 0).toLocaleString('en-IN'), cls: '' },\n { label: 'Cart Owners', value: stats.cartOwners.toString(), cls: '' },\n { label: 'Workers', value: stats.workers.toString(), cls: '' },\n { label: 'Investors', value: stats.investors.toString(), cls: '' },\n ].map((s) => (\n <div\n key={s.label}\n className={cn('rounded-lg border border-border-subtle bg-bg-surface p-3', s.cls)}\n >\n <p className=\"text-xs text-text-secondary\">{s.label}</p>\n <p className=\"text-lg font-bold text-text-primary\">{s.value}</p>\n </div>\n ))}\n </div>\n </EmphasisPanel>\n\n {/* 5 Filter Controls */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 mb-6\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3\">\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search users...\"\n value={filters.searchQuery}\n onChange={(e) => handleFilterChange('searchQuery', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 pl-10 pr-4 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <select\n value={filters.role}\n onChange={(e) => handleFilterChange('role', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">All Roles</option>\n <option value=\"customer\">Customers</option>\n <option value=\"cart_owner\">Cart Owners</option>\n <option value=\"worker\">Workers</option>\n <option value=\"investor\">Investors</option>\n </select>\n <select\n value={filters.status}\n onChange={(e) => handleFilterChange('status', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">All Status</option>\n <option value=\"active\">Active</option>\n <option value=\"inactive\">Inactive</option>\n <option value=\"suspended\">Suspended</option>\n <option value=\"pending\">Pending</option>\n </select>\n <select\n value={filters.registrationDate}\n onChange={(e) => handleFilterChange('registrationDate', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">All Time</option>\n <option value=\"1\">Last 24 hours</option>\n <option value=\"7\">Last 7 days</option>\n <option value=\"30\">Last 30 days</option>\n <option value=\"90\">Last 90 days</option>\n </select>\n <select\n value={filters.sortBy}\n onChange={(e) => handleFilterChange('sortBy', e.target.value)}\n className=\"rounded-lg border border-border-subtle bg-bg-surface py-2 px-3 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"recent\">Most Recent</option>\n <option value=\"name\">Name A-Z</option>\n <option value=\"activity\">Last Activity</option>\n </select>\n </div>\n </div>\n\n {/* Dual Layout */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface overflow-hidden\">\n {/* Mobile Card View */}\n <div className=\"block md:hidden space-y-4 p-4\">\n {pagedUsers.map((user) => (\n <div\n key={user.id}\n className=\"rounded-lg border border-border-subtle bg-bg-sunken/30 p-4\"\n >\n <div className=\"flex items-center mb-3\">\n {user.profilePicture ? (\n <img\n src={user.profilePicture}\n alt={`${user.firstName} ${user.lastName}`}\n className=\"w-12 h-12 rounded-full object-cover mr-3\"\n />\n ) : (\n <div className=\"w-12 h-12 rounded-full bg-bg-sunken flex items-center justify-center mr-3\">\n <Users className=\"h-6 w-6 text-text-secondary\" />\n </div>\n )}\n <div className=\"flex-1 min-w-0\">\n <h3 className=\"font-medium text-text-primary\">\n {user.firstName} {user.lastName}\n </h3>\n <p className=\"text-sm text-text-secondary truncate\">{user.email}</p>\n <p className=\"text-sm text-text-secondary\">{user.phone}</p>\n </div>\n </div>\n <div className=\"flex flex-wrap gap-2 mb-3\">\n {roleBadge(user.role)}\n {statusBadge(user.status)}\n </div>\n <div className=\"grid grid-cols-2 gap-4 text-sm mb-3\">\n <div>\n <p className=\"text-text-secondary\">Registered</p>\n <p className=\"text-text-primary\">{formatDate(user.registrationDate)}</p>\n </div>\n <div>\n <p className=\"text-text-secondary\">Last Login</p>\n <p className=\"text-text-primary\">\n {user.lastLoginTime ? formatDate(user.lastLoginTime) : 'Never'}\n </p>\n </div>\n </div>\n <div className=\"flex flex-wrap gap-3 mb-3\">\n <div className=\"flex items-center\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full mr-2',\n user.isEmailVerified ? 'bg-status-success-text' : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">Email</span>\n </div>\n <div className=\"flex items-center\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full mr-2',\n user.isPhoneVerified ? 'bg-status-success-text' : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">Phone</span>\n </div>\n {user.kycStatus && (\n <div className=\"flex items-center\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full mr-2',\n user.kycStatus === 'verified'\n ? 'bg-status-success-text'\n : user.kycStatus === 'pending'\n ? 'bg-status-warning-text'\n : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">KYC</span>\n </div>\n )}\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'view')}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n View\n </button>\n {user.status === 'active' ? (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'suspend')}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n Suspend\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'activate')}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-sm font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n Activate\n </button>\n )}\n {user.kycStatus === 'pending' && (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'verify')}\n className=\"rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n Verify\n </button>\n )}\n </div>\n </div>\n ))}\n </div>\n\n {/* Desktop Table View */}\n <div className=\"hidden md:block overflow-x-auto\">\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 tracking-wider\">\n User\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Role & Status\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Activity\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Performance\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Verification\n </th>\n <th className=\"px-4 py-3 text-left text-xs font-medium text-text-secondary uppercase tracking-wider\">\n Actions\n </th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {pagedUsers.map((user) => (\n <tr key={user.id} className=\"hover:bg-accent/50 transition-colors\">\n <td className=\"px-4 py-3\">\n <div className=\"flex items-center gap-3\">\n {user.profilePicture ? (\n <img\n src={user.profilePicture}\n alt={`${user.firstName}`}\n className=\"w-10 h-10 rounded-full object-cover\"\n />\n ) : (\n <div className=\"w-10 h-10 rounded-full bg-bg-sunken flex items-center justify-center\">\n <Users className=\"h-5 w-5 text-text-secondary\" />\n </div>\n )}\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {user.firstName} {user.lastName}\n </p>\n <p className=\"text-xs text-text-secondary\">{user.email}</p>\n <p className=\"text-xs text-text-secondary\">{user.phone}</p>\n </div>\n </div>\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"space-y-1\">\n {roleBadge(user.role)}\n <br />\n {statusBadge(user.status)}\n </div>\n </td>\n <td className=\"px-4 py-3 text-sm\">\n <p className=\"text-text-primary\">\n Registered: {formatDate(user.registrationDate)}\n </p>\n {user.lastLoginTime && (\n <p className=\"text-text-secondary\">\n Last login: {formatDate(user.lastLoginTime)}\n </p>\n )}\n {user.deviceInfo && (\n <p className=\"text-text-secondary flex items-center gap-1\">\n <Smartphone className=\"h-3 w-3\" />\n {user.deviceInfo}\n </p>\n )}\n </td>\n <td className=\"px-4 py-3 text-sm\">\n {user.role === 'customer' && user.totalOrders != null && (\n <>\n <p className=\"text-text-primary\">{user.totalOrders} orders</p>\n <p className=\"text-text-secondary\">\n {formatCurrency(user.totalSpent ?? 0)} spent\n </p>\n </>\n )}\n {(user.role === 'cart_owner' || user.role === 'worker') &&\n user.totalEarnings != null && (\n <p className=\"text-text-primary\">\n {formatCurrency(user.totalEarnings)} earned\n </p>\n )}\n {user.role === 'investor' && user.riskScore != null && (\n <p className=\"text-text-primary\">Risk: {user.riskScore}/5</p>\n )}\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"space-y-1\">\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full',\n user.isEmailVerified ? 'bg-status-success-text' : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">Email</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full',\n user.isPhoneVerified ? 'bg-status-success-text' : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">Phone</span>\n </div>\n {user.kycStatus && (\n <div className=\"flex items-center gap-2\">\n <span\n className={cn(\n 'w-2 h-2 rounded-full',\n user.kycStatus === 'verified'\n ? 'bg-status-success-text'\n : user.kycStatus === 'pending'\n ? 'bg-status-warning-text'\n : 'bg-status-error-text'\n )}\n />\n <span className=\"text-sm text-text-secondary\">KYC</span>\n </div>\n )}\n </div>\n </td>\n <td className=\"px-4 py-3\">\n <div className=\"flex gap-1\">\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'view')}\n title=\"View details\"\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-accent transition-colors\"\n >\n <Eye className=\"h-4 w-4\" />\n </button>\n {user.status === 'active' ? (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'suspend')}\n title=\"Suspend\"\n className=\"rounded p-1.5 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <UserX className=\"h-4 w-4\" />\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'activate')}\n title=\"Activate\"\n className=\"rounded p-1.5 text-text-secondary hover:text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <UserCheck className=\"h-4 w-4\" />\n </button>\n )}\n {user.kycStatus === 'pending' && (\n <button\n type=\"button\"\n onClick={() => handleUserAction(user, 'verify')}\n title=\"Verify\"\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-[var(--color-accent-soft)] transition-colors\"\n >\n <Shield className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {users.length === 0 && (\n <EmptyState\n illustration=\"empty-people\"\n title=\"No users found\"\n description=\"No accounts match your current filters. Try clearing them or searching for a different name or email.\"\n action={\n <button\n type=\"button\"\n onClick={() =>\n setFilters({\n role: '',\n status: '',\n searchQuery: '',\n sortBy: 'recent',\n registrationDate: '',\n })\n }\n className=\"rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Clear filters\n </button>\n }\n />\n )}\n </div>\n\n {/* Pagination */}\n <div className=\"mt-6 flex flex-col sm:flex-row sm:items-center justify-between gap-4\">\n <p className=\"text-sm text-text-secondary text-center sm:text-left\">\n Showing{' '}\n <span className=\"font-medium\">\n {Math.min((currentPage - 1) * itemsPerPage + 1, users.length)}\n </span>{' '}\n to{' '}\n <span className=\"font-medium\">{Math.min(currentPage * itemsPerPage, users.length)}</span>{' '}\n of <span className=\"font-medium\">{users.length}</span> results\n </p>\n <div className=\"flex justify-center sm:justify-end gap-2\">\n <button\n type=\"button\"\n disabled={currentPage === 1}\n onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n Previous\n </button>\n <button\n type=\"button\"\n disabled={currentPage * itemsPerPage >= users.length}\n onClick={() => setCurrentPage((p) => p + 1)}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Next\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n\n {/* User Details Modal (read-only) */}\n {showUserModal && selectedUser && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\">\n <div className=\"w-full max-w-md rounded-lg border border-border-subtle bg-bg-surface shadow-lg max-h-[90vh] overflow-y-auto\">\n <div className=\"flex items-center justify-between p-4 border-b border-border-subtle\">\n <h3 className=\"text-lg font-semibold text-text-primary\">User Details</h3>\n <button\n type=\"button\"\n onClick={() => setShowUserModal(false)}\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-accent transition-colors\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n <div className=\"p-4 space-y-4\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div>\n <p className=\"text-sm text-text-secondary\">Name</p>\n <p className=\"font-medium text-text-primary\">\n {selectedUser.firstName} {selectedUser.lastName}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Role</p>\n <div className=\"mt-0.5\">{roleBadge(selectedUser.role)}</div>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Status</p>\n <div className=\"mt-0.5\">{statusBadge(selectedUser.status)}</div>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">Registered</p>\n <p className=\"font-medium text-text-primary\">\n {formatDate(selectedUser.registrationDate)}\n </p>\n </div>\n {selectedUser.email && (\n <div>\n <p className=\"text-sm text-text-secondary\">Email</p>\n <p className=\"font-medium text-text-primary flex items-center gap-1\">\n <Mail className=\"h-3.5 w-3.5\" />\n {selectedUser.email}\n </p>\n </div>\n )}\n {selectedUser.phone && (\n <div>\n <p className=\"text-sm text-text-secondary\">Phone</p>\n <p className=\"font-medium text-text-primary flex items-center gap-1\">\n <Phone className=\"h-3.5 w-3.5\" />\n {selectedUser.phone}\n </p>\n </div>\n )}\n </div>\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/40 p-3\">\n <p className=\"text-sm text-text-secondary\">\n Profile details, email and role are managed by the account platform and can't\n be edited here. Use the Suspend / Activate controls in the list to change this\n account's access.\n </p>\n </div>\n\n <div className=\"flex justify-end\">\n <button\n type=\"button\"\n onClick={() => setShowUserModal(false)}\n className=\"rounded-lg border border-border-subtle py-2 px-4 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n Close\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics Dashboard Page
|
|
3
|
+
*
|
|
4
|
+
* Performance insights for the signed-in owner's own service provider (cart):
|
|
5
|
+
* revenue overview with real period-over-period growth, order statistics,
|
|
6
|
+
* popular times, performance metrics, top/least selling offerings, category
|
|
7
|
+
* performance, reviews & ratings, peak hours/days and daily order trends —
|
|
8
|
+
* every number derived from live backend data (no fabrication).
|
|
9
|
+
*
|
|
10
|
+
* @module kadaikodi/pages/cart-owner
|
|
11
|
+
*/
|
|
12
|
+
export declare const AnalyticsDashboard: () => import("react").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=AnalyticsDashboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnalyticsDashboard.d.ts","sourceRoot":"","sources":["../../../../src/kadaikodi/pages/cart-owner/AnalyticsDashboard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAwEH,eAAO,MAAM,kBAAkB,mCA6xB9B,CAAC"}
|