@burdenoff/microfe-atheletebridge 2026.626.1 → 2026.628.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.
Files changed (162) hide show
  1. package/dist/atheletebridge/AthleteBridgeRoot.js +49 -129
  2. package/dist/atheletebridge/AthleteBridgeRoot.js.map +1 -1
  3. package/dist/atheletebridge/AthleteBridgeRoutes.js +65 -184
  4. package/dist/atheletebridge/AthleteBridgeRoutes.js.map +1 -1
  5. package/dist/atheletebridge/components/CursorPager.js +34 -0
  6. package/dist/atheletebridge/components/CursorPager.js.map +1 -0
  7. package/dist/atheletebridge/components/FilterSelect.js +22 -0
  8. package/dist/atheletebridge/components/FilterSelect.js.map +1 -0
  9. package/dist/atheletebridge/components/FixtureCard.js +76 -0
  10. package/dist/atheletebridge/components/FixtureCard.js.map +1 -0
  11. package/dist/atheletebridge/components/LoadingState.js +36 -0
  12. package/dist/atheletebridge/components/LoadingState.js.map +1 -0
  13. package/dist/atheletebridge/components/ProgramCard.js +69 -0
  14. package/dist/atheletebridge/components/ProgramCard.js.map +1 -0
  15. package/dist/atheletebridge/components/SessionCard.js +76 -0
  16. package/dist/atheletebridge/components/SessionCard.js.map +1 -0
  17. package/dist/atheletebridge/components/StatusBadge.js +44 -35
  18. package/dist/atheletebridge/components/StatusBadge.js.map +1 -1
  19. package/dist/atheletebridge/components/TeamCard.js +81 -0
  20. package/dist/atheletebridge/components/TeamCard.js.map +1 -0
  21. package/dist/atheletebridge/components/domain.js +47 -0
  22. package/dist/atheletebridge/components/domain.js.map +1 -0
  23. package/dist/atheletebridge/components/form.js +29 -0
  24. package/dist/atheletebridge/components/form.js.map +1 -0
  25. package/dist/atheletebridge/context/AthleteBridgeContext.js +6 -6
  26. package/dist/atheletebridge/context/AthleteBridgeContext.js.map +1 -1
  27. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js +342 -165
  28. package/dist/atheletebridge/hooks/useAthleteBridgeApi.js.map +1 -1
  29. package/dist/atheletebridge/index.js +1 -1
  30. package/dist/atheletebridge/pages/DashboardPage.js +169 -0
  31. package/dist/atheletebridge/pages/DashboardPage.js.map +1 -0
  32. package/dist/atheletebridge/pages/StandingsPage.js +166 -0
  33. package/dist/atheletebridge/pages/StandingsPage.js.map +1 -0
  34. package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js +201 -0
  35. package/dist/atheletebridge/pages/fixtures/FixtureDetailPage.js.map +1 -0
  36. package/dist/atheletebridge/pages/fixtures/FixtureFormPage.js +205 -0
  37. package/dist/atheletebridge/pages/fixtures/FixtureFormPage.js.map +1 -0
  38. package/dist/atheletebridge/pages/fixtures/FixturesListPage.js +92 -0
  39. package/dist/atheletebridge/pages/fixtures/FixturesListPage.js.map +1 -0
  40. package/dist/atheletebridge/pages/programs/ProgramDetailPage.js +374 -0
  41. package/dist/atheletebridge/pages/programs/ProgramDetailPage.js.map +1 -0
  42. package/dist/atheletebridge/pages/programs/ProgramFormPage.js +207 -0
  43. package/dist/atheletebridge/pages/programs/ProgramFormPage.js.map +1 -0
  44. package/dist/atheletebridge/pages/programs/ProgramsListPage.js +113 -0
  45. package/dist/atheletebridge/pages/programs/ProgramsListPage.js.map +1 -0
  46. package/dist/atheletebridge/pages/sessions/SessionDetailPage.js +224 -0
  47. package/dist/atheletebridge/pages/sessions/SessionDetailPage.js.map +1 -0
  48. package/dist/atheletebridge/pages/sessions/SessionFormPage.js +206 -0
  49. package/dist/atheletebridge/pages/sessions/SessionFormPage.js.map +1 -0
  50. package/dist/atheletebridge/pages/sessions/SessionsListPage.js +92 -0
  51. package/dist/atheletebridge/pages/sessions/SessionsListPage.js.map +1 -0
  52. package/dist/atheletebridge/pages/teams/TeamDetailPage.js +350 -0
  53. package/dist/atheletebridge/pages/teams/TeamDetailPage.js.map +1 -0
  54. package/dist/atheletebridge/pages/teams/TeamFormPage.js +222 -0
  55. package/dist/atheletebridge/pages/teams/TeamFormPage.js.map +1 -0
  56. package/dist/atheletebridge/pages/teams/TeamsListPage.js +101 -0
  57. package/dist/atheletebridge/pages/teams/TeamsListPage.js.map +1 -0
  58. package/dist/atheletebridge/store/atheletebridgeStore.js +2 -13
  59. package/dist/atheletebridge/store/atheletebridgeStore.js.map +1 -1
  60. package/dist/atheletebridge/utils/datetime.js +10 -0
  61. package/dist/atheletebridge/utils/datetime.js.map +1 -0
  62. package/dist/atheletebridge/utils/formatters.js +1 -4
  63. package/dist/atheletebridge/utils/formatters.js.map +1 -1
  64. package/package.json +1 -1
  65. package/dist/atheletebridge/components/InvestmentCard.js +0 -96
  66. package/dist/atheletebridge/components/InvestmentCard.js.map +0 -1
  67. package/dist/atheletebridge/components/RatingDisplay.js +0 -35
  68. package/dist/atheletebridge/components/RatingDisplay.js.map +0 -1
  69. package/dist/atheletebridge/mocks/data.js +0 -1517
  70. package/dist/atheletebridge/mocks/data.js.map +0 -1
  71. package/dist/atheletebridge/mocks/users.js +0 -34
  72. package/dist/atheletebridge/mocks/users.js.map +0 -1
  73. package/dist/atheletebridge/pages/HomePage.js +0 -936
  74. package/dist/atheletebridge/pages/HomePage.js.map +0 -1
  75. package/dist/atheletebridge/pages/admin/AdminAnalyticsPage.js +0 -653
  76. package/dist/atheletebridge/pages/admin/AdminAnalyticsPage.js.map +0 -1
  77. package/dist/atheletebridge/pages/admin/AdminDashboard.js +0 -671
  78. package/dist/atheletebridge/pages/admin/AdminDashboard.js.map +0 -1
  79. package/dist/atheletebridge/pages/admin/AdminFinancialPage.js +0 -429
  80. package/dist/atheletebridge/pages/admin/AdminFinancialPage.js.map +0 -1
  81. package/dist/atheletebridge/pages/admin/AdminOrdersPage.js +0 -667
  82. package/dist/atheletebridge/pages/admin/AdminOrdersPage.js.map +0 -1
  83. package/dist/atheletebridge/pages/admin/AdminProfilePage.js +0 -261
  84. package/dist/atheletebridge/pages/admin/AdminProfilePage.js.map +0 -1
  85. package/dist/atheletebridge/pages/admin/AdminSettingsPage.js +0 -653
  86. package/dist/atheletebridge/pages/admin/AdminSettingsPage.js.map +0 -1
  87. package/dist/atheletebridge/pages/admin/CartManagementPage.js +0 -876
  88. package/dist/atheletebridge/pages/admin/CartManagementPage.js.map +0 -1
  89. package/dist/atheletebridge/pages/admin/UserManagementPage.js +0 -900
  90. package/dist/atheletebridge/pages/admin/UserManagementPage.js.map +0 -1
  91. package/dist/atheletebridge/pages/cart-owner/AnalyticsDashboard.js +0 -839
  92. package/dist/atheletebridge/pages/cart-owner/AnalyticsDashboard.js.map +0 -1
  93. package/dist/atheletebridge/pages/cart-owner/BusinessSettingsPage.js +0 -704
  94. package/dist/atheletebridge/pages/cart-owner/BusinessSettingsPage.js.map +0 -1
  95. package/dist/atheletebridge/pages/cart-owner/CartOwnerDashboard.js +0 -792
  96. package/dist/atheletebridge/pages/cart-owner/CartOwnerDashboard.js.map +0 -1
  97. package/dist/atheletebridge/pages/cart-owner/CartOwnerProfilePage.js +0 -891
  98. package/dist/atheletebridge/pages/cart-owner/CartOwnerProfilePage.js.map +0 -1
  99. package/dist/atheletebridge/pages/cart-owner/CartServiceConfigPage.js +0 -633
  100. package/dist/atheletebridge/pages/cart-owner/CartServiceConfigPage.js.map +0 -1
  101. package/dist/atheletebridge/pages/cart-owner/InventoryManagementPage.js +0 -913
  102. package/dist/atheletebridge/pages/cart-owner/InventoryManagementPage.js.map +0 -1
  103. package/dist/atheletebridge/pages/cart-owner/OrderManagementPage.js +0 -881
  104. package/dist/atheletebridge/pages/cart-owner/OrderManagementPage.js.map +0 -1
  105. package/dist/atheletebridge/pages/cart-owner/StaffManagementPage.js +0 -841
  106. package/dist/atheletebridge/pages/cart-owner/StaffManagementPage.js.map +0 -1
  107. package/dist/atheletebridge/pages/common/HelpSupportPage.js +0 -1319
  108. package/dist/atheletebridge/pages/common/HelpSupportPage.js.map +0 -1
  109. package/dist/atheletebridge/pages/common/NotificationCenterPage.js +0 -674
  110. package/dist/atheletebridge/pages/common/NotificationCenterPage.js.map +0 -1
  111. package/dist/atheletebridge/pages/common/SettingsPage.js +0 -972
  112. package/dist/atheletebridge/pages/common/SettingsPage.js.map +0 -1
  113. package/dist/atheletebridge/pages/customer/BookingDetailsPage.js +0 -602
  114. package/dist/atheletebridge/pages/customer/BookingDetailsPage.js.map +0 -1
  115. package/dist/atheletebridge/pages/customer/CartDetailPage.js +0 -656
  116. package/dist/atheletebridge/pages/customer/CartDetailPage.js.map +0 -1
  117. package/dist/atheletebridge/pages/customer/CartDiscoveryPage.js +0 -558
  118. package/dist/atheletebridge/pages/customer/CartDiscoveryPage.js.map +0 -1
  119. package/dist/atheletebridge/pages/customer/CheckoutPage.js +0 -536
  120. package/dist/atheletebridge/pages/customer/CheckoutPage.js.map +0 -1
  121. package/dist/atheletebridge/pages/customer/CustomerDashboard.js +0 -539
  122. package/dist/atheletebridge/pages/customer/CustomerDashboard.js.map +0 -1
  123. package/dist/atheletebridge/pages/customer/CustomerProfilePage.js +0 -657
  124. package/dist/atheletebridge/pages/customer/CustomerProfilePage.js.map +0 -1
  125. package/dist/atheletebridge/pages/customer/DirectServiceBookingPage.js +0 -635
  126. package/dist/atheletebridge/pages/customer/DirectServiceBookingPage.js.map +0 -1
  127. package/dist/atheletebridge/pages/customer/FavoritesPage.js +0 -486
  128. package/dist/atheletebridge/pages/customer/FavoritesPage.js.map +0 -1
  129. package/dist/atheletebridge/pages/customer/OrderHistoryPage.js +0 -447
  130. package/dist/atheletebridge/pages/customer/OrderHistoryPage.js.map +0 -1
  131. package/dist/atheletebridge/pages/customer/OrderTrackingPage.js +0 -393
  132. package/dist/atheletebridge/pages/customer/OrderTrackingPage.js.map +0 -1
  133. package/dist/atheletebridge/pages/customer/PaymentMethodsPage.js +0 -494
  134. package/dist/atheletebridge/pages/customer/PaymentMethodsPage.js.map +0 -1
  135. package/dist/atheletebridge/pages/customer/ReviewsPage.js +0 -615
  136. package/dist/atheletebridge/pages/customer/ReviewsPage.js.map +0 -1
  137. package/dist/atheletebridge/pages/customer/SavedAddressesPage.js +0 -451
  138. package/dist/atheletebridge/pages/customer/SavedAddressesPage.js.map +0 -1
  139. package/dist/atheletebridge/pages/investor/InvestmentDetailsPage.js +0 -881
  140. package/dist/atheletebridge/pages/investor/InvestmentDetailsPage.js.map +0 -1
  141. package/dist/atheletebridge/pages/investor/InvestmentOpportunitiesPage.js +0 -945
  142. package/dist/atheletebridge/pages/investor/InvestmentOpportunitiesPage.js.map +0 -1
  143. package/dist/atheletebridge/pages/investor/InvestorAnalyticsPage.js +0 -686
  144. package/dist/atheletebridge/pages/investor/InvestorAnalyticsPage.js.map +0 -1
  145. package/dist/atheletebridge/pages/investor/InvestorDashboard.js +0 -453
  146. package/dist/atheletebridge/pages/investor/InvestorDashboard.js.map +0 -1
  147. package/dist/atheletebridge/pages/investor/InvestorInvestmentsPage.js +0 -405
  148. package/dist/atheletebridge/pages/investor/InvestorInvestmentsPage.js.map +0 -1
  149. package/dist/atheletebridge/pages/investor/InvestorPortfolioPage.js +0 -577
  150. package/dist/atheletebridge/pages/investor/InvestorPortfolioPage.js.map +0 -1
  151. package/dist/atheletebridge/pages/investor/InvestorProfilePage.js +0 -1069
  152. package/dist/atheletebridge/pages/investor/InvestorProfilePage.js.map +0 -1
  153. package/dist/atheletebridge/pages/worker/TaskDetailsPage.js +0 -530
  154. package/dist/atheletebridge/pages/worker/TaskDetailsPage.js.map +0 -1
  155. package/dist/atheletebridge/pages/worker/WorkerDashboard.js +0 -669
  156. package/dist/atheletebridge/pages/worker/WorkerDashboard.js.map +0 -1
  157. package/dist/atheletebridge/pages/worker/WorkerOrdersPage.js +0 -681
  158. package/dist/atheletebridge/pages/worker/WorkerOrdersPage.js.map +0 -1
  159. package/dist/atheletebridge/pages/worker/WorkerProfilePage.js +0 -691
  160. package/dist/atheletebridge/pages/worker/WorkerProfilePage.js.map +0 -1
  161. package/dist/atheletebridge/pages/worker/WorkerSchedulePage.js +0 -588
  162. package/dist/atheletebridge/pages/worker/WorkerSchedulePage.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"FavoritesPage.js","names":[],"sources":["../../../../src/atheletebridge/pages/customer/FavoritesPage.tsx"],"sourcesContent":["/**\n * Favorites Page\n * @module atheletebridge/pages/customer\n *\n * Favorite carts AND products with stats header, 4 filters\n * (search, type, category, sort), Order Again / View Menu per cart,\n * Add to Cart / View Cart + remove per product, Veg badges,\n * prep time, 3 mock favorite products, 2 mock favorite carts.\n */\n\nimport { useState, useCallback, useEffect } from 'react';\nimport {\n Heart,\n Star,\n MapPin,\n Clock,\n CheckCircle2,\n Search,\n ShoppingCart,\n Leaf,\n Utensils,\n RotateCcw,\n ListFilter,\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 { useAthleteBridge } from '../../context/AthleteBridgeContext';\nimport { useProviders, useOrders } from '../../hooks/useAthleteBridgeApi';\nimport { mockCarts } from '../../mocks/data';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency, formatDate, formatDistance } from '../../utils/formatters';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface FavoriteCart {\n id: string;\n name: string;\n description: string;\n category: string;\n image: string;\n rating: number;\n reviewCount: number;\n isOpen: boolean;\n isVerified: boolean;\n distance: number;\n estimatedTime: number;\n addedToFavorites: string;\n lastOrdered?: string;\n totalOrders: number;\n totalSpent: number;\n}\n\ninterface FavoriteProduct {\n id: string;\n name: string;\n description: string;\n price: number;\n category: string;\n image: string;\n cartId: string;\n cartName: string;\n isVegetarian: boolean;\n isVegan: boolean;\n preparationTime: number;\n rating: number;\n addedToFavorites: string;\n lastOrdered?: string;\n orderCount: number;\n}\n\ninterface FavoriteFilters {\n searchQuery: string;\n type: 'all' | 'carts' | 'products';\n category: string;\n sortBy: 'recent' | 'name' | 'rating' | 'orders';\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function FavoritesPage() {\n const { navigateTo, currentUser } = useAthleteBridge();\n const { data: providers = [], isLoading: isLoadingProviders } = useProviders();\n const { data: orders = [], isLoading: isLoadingOrders } = useOrders({\n customerId: currentUser?.id,\n });\n\n const favoriteCarts: FavoriteCart[] = providers.slice(0, 2).map((p) => ({\n id: p.id,\n name: p.name,\n description: 'Authentic services from AthleteBridge',\n category: p.category,\n image: p.image,\n rating: p.rating,\n reviewCount: p.totalRatings,\n isOpen: p.isOpen,\n isVerified: p.isVerified || false,\n distance: p.distance,\n estimatedTime: p.estimatedTime,\n addedToFavorites: new Date().toISOString(),\n totalOrders: orders.filter((o) => o.cartId === p.id).length,\n totalSpent: orders.filter((o) => o.cartId === p.id).reduce((acc, o) => acc + o.total, 0),\n }));\n\n const favoriteProducts: FavoriteProduct[] = [\n {\n id: 'prod-001',\n name: 'Masala Dosa',\n description: 'Crispy rice crepe with spiced potato filling',\n price: 120,\n category: 'South Indian',\n image: 'https://images.unsplash.com/photo-1630383249896-424e482df921?w=300',\n cartId: providers[0]?.id || 'FOOD-001',\n cartName: providers[0]?.name || 'Dosa Express',\n isVegetarian: true,\n isVegan: false,\n preparationTime: 15,\n rating: 4.7,\n addedToFavorites: '2024-02-20T12:30:00Z',\n orderCount: 8,\n },\n ];\n\n const [filters, setFilters] = useState<FavoriteFilters>({\n searchQuery: '',\n type: 'all',\n category: '',\n sortBy: 'recent',\n });\n\n const isLoading = isLoadingProviders || isLoadingOrders;\n\n // --- Derived data ---\n const getDisplayItems = useCallback(() => {\n let carts = [...favoriteCarts];\n let products = [...favoriteProducts];\n\n // Search\n if (filters.searchQuery) {\n const q = filters.searchQuery.toLowerCase();\n carts = carts.filter(\n (c) =>\n c.name.toLowerCase().includes(q) ||\n c.description.toLowerCase().includes(q) ||\n c.category.toLowerCase().includes(q)\n );\n products = products.filter(\n (p) =>\n p.name.toLowerCase().includes(q) ||\n p.description.toLowerCase().includes(q) ||\n p.category.toLowerCase().includes(q) ||\n p.cartName.toLowerCase().includes(q)\n );\n }\n\n // Category\n if (filters.category) {\n carts = carts.filter((c) => c.category === filters.category);\n products = products.filter((p) => p.category === filters.category);\n }\n\n // Sort\n switch (filters.sortBy) {\n case 'recent':\n carts.sort(\n (a, b) => new Date(b.addedToFavorites).getTime() - new Date(a.addedToFavorites).getTime()\n );\n products.sort(\n (a, b) => new Date(b.addedToFavorites).getTime() - new Date(a.addedToFavorites).getTime()\n );\n break;\n case 'name':\n carts.sort((a, b) => a.name.localeCompare(b.name));\n products.sort((a, b) => a.name.localeCompare(b.name));\n break;\n case 'rating':\n carts.sort((a, b) => b.rating - a.rating);\n products.sort((a, b) => b.rating - a.rating);\n break;\n case 'orders':\n carts.sort((a, b) => b.totalOrders - a.totalOrders);\n products.sort((a, b) => b.orderCount - a.orderCount);\n break;\n }\n\n // Type filter\n if (filters.type === 'carts') return { carts, products: [] };\n if (filters.type === 'products') return { carts: [], products };\n return { carts, products };\n }, [favoriteCarts, favoriteProducts, filters]);\n\n const { carts: displayCarts, products: displayProducts } = getDisplayItems();\n\n const handleRemoveCart = (id: string) => {\n // In real app, this would call an API\n console.log('Remove cart:', id);\n };\n\n const handleRemoveProduct = (id: string) => {\n // In real app, this would call an API\n console.log('Remove product:', id);\n };\n\n // Stats\n const totalSaved =\n favoriteCarts.reduce((s, c) => s + c.totalSpent, 0) +\n favoriteProducts.reduce((s, p) => s + p.price * p.orderCount, 0);\n\n if (isLoading) {\n return (\n <PageLayout title=\"My Favorites\">\n <div className=\"flex items-center justify-center py-20\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-foreground\" />\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"My Favorites\"\n description={`${favoriteCarts.length} carts, ${favoriteProducts.length} products`}\n >\n <PagePurpose className=\"mb-6\">\n All the carts and products you&apos;ve saved, in one place. Come back here to quickly reorder\n from places you love, track how much you&apos;ve saved, and filter your favourites by type or\n category.\n </PagePurpose>\n\n {/* Stats Header */}\n <EmphasisPanel className=\"mb-6\">\n <div className=\"flex flex-wrap items-center gap-4 text-sm text-text-secondary\">\n <span className=\"flex items-center gap-1.5\">\n <ShoppingCart className=\"h-3.5 w-3.5\" />\n {favoriteCarts.length} carts\n </span>\n <span className=\"flex items-center gap-1.5\">\n <Utensils className=\"h-3.5 w-3.5\" />\n {favoriteProducts.length} products\n </span>\n <span className=\"flex items-center gap-1.5\">\n <Star className=\"h-3.5 w-3.5\" />\n Total saved: {formatCurrency(totalSaved, { minimumFractionDigits: 0 })}\n </span>\n </div>\n </EmphasisPanel>\n\n {/* Filters */}\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 lg:grid-cols-4 gap-3\">\n {/* Search */}\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search favorites...\"\n value={filters.searchQuery}\n onChange={(e) => setFilters((p) => ({ ...p, searchQuery: e.target.value }))}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 pl-9 pr-3 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\n {/* Type */}\n <select\n value={filters.type}\n onChange={(e) =>\n setFilters((p) => ({ ...p, type: e.target.value as FavoriteFilters['type'] }))\n }\n className=\"w-full 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\">All Favorites</option>\n <option value=\"carts\">Favorite Carts</option>\n <option value=\"products\">Favorite Products</option>\n </select>\n\n {/* Category */}\n <select\n value={filters.category}\n onChange={(e) => setFilters((p) => ({ ...p, category: e.target.value }))}\n className=\"w-full 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 <option value=\"Food & Beverage\">Food & Beverage</option>\n <option value=\"Street Food\">Street Food</option>\n <option value=\"South Indian\">South Indian</option>\n <option value=\"Beverages\">Beverages</option>\n </select>\n\n {/* Sort */}\n <select\n value={filters.sortBy}\n onChange={(e) =>\n setFilters((p) => ({ ...p, sortBy: e.target.value as FavoriteFilters['sortBy'] }))\n }\n className=\"w-full 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\">Recently Added</option>\n <option value=\"name\">Name A-Z</option>\n <option value=\"rating\">Highest Rated</option>\n <option value=\"orders\">Most Ordered</option>\n </select>\n </div>\n </div>\n\n {/* Content */}\n {displayCarts.length === 0 && displayProducts.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Heart className=\"h-12 w-12\" />}\n title=\"No favorites yet\"\n description=\"Browse carts and tap the heart icon to add them to your favorites.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/carts')}\n className=\"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background hover:opacity-90 transition-opacity\"\n >\n Discover Carts\n </button>\n }\n />\n ) : (\n <div className=\"space-y-8\">\n {/* Favorite Carts */}\n {displayCarts.length > 0 && (\n <section>\n <h3 className=\"text-base font-semibold text-text-primary mb-4 flex items-center gap-2\">\n <ShoppingCart className=\"h-4 w-4 text-text-secondary\" />\n Favorite Carts ({displayCarts.length})\n </h3>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n {displayCarts.map((cart) => (\n <div\n key={cart.id}\n className=\"rounded-lg border border-border-subtle bg-bg-surface shadow-sm overflow-hidden\"\n >\n {/* Image */}\n <div className=\"relative h-36 bg-bg-sunken\">\n <button\n type=\"button\"\n onClick={() => navigateTo(`/customer/carts/${cart.id}`)}\n className=\"block h-full w-full\"\n >\n <img\n src={cart.image}\n alt={cart.name}\n className=\"h-full w-full object-cover\"\n />\n </button>\n <button\n type=\"button\"\n onClick={() => handleRemoveCart(cart.id)}\n title=\"Remove from favorites\"\n className=\"absolute top-2 right-2 flex h-8 w-8 items-center justify-center rounded-full bg-bg-surface/80 backdrop-blur-sm text-red-500 hover:bg-bg-surface transition-colors\"\n >\n <Heart className=\"h-4 w-4 fill-current\" />\n </button>\n <div className=\"absolute top-2 left-2\">\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n cart.isOpen\n ? 'bg-green-500/20 text-green-600 dark:text-green-400'\n : 'bg-status-error-bg/20 text-status-error-text'\n )}\n >\n {cart.isOpen ? 'Open' : 'Closed'}\n </span>\n </div>\n </div>\n\n {/* Details */}\n <div className=\"p-4\">\n <div className=\"flex items-start justify-between gap-2 mb-2\">\n <h4 className=\"text-sm font-semibold text-text-primary truncate\">\n {cart.name}\n </h4>\n <div className=\"flex items-center gap-1 shrink-0\">\n <Star className=\"h-3.5 w-3.5 fill-yellow-400 text-yellow-400\" />\n <span className=\"text-xs font-medium text-text-primary\">\n {cart.rating}\n </span>\n <span className=\"text-xs text-text-secondary\">({cart.reviewCount})</span>\n </div>\n </div>\n\n <p className=\"text-xs text-text-secondary line-clamp-2 mb-3\">\n {cart.description}\n </p>\n\n <div className=\"space-y-1.5 text-xs text-text-secondary\">\n <div className=\"flex justify-between\">\n <span>Added:</span>\n <span>\n {formatDate(cart.addedToFavorites, {\n hour: undefined,\n minute: undefined,\n hour12: undefined,\n })}\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span>Total orders:</span>\n <span>{cart.totalOrders}</span>\n </div>\n <div className=\"flex justify-between\">\n <span>Total spent:</span>\n <span className=\"font-medium\">\n {formatCurrency(cart.totalSpent, { minimumFractionDigits: 0 })}\n </span>\n </div>\n {cart.lastOrdered && (\n <div className=\"flex justify-between\">\n <span>Last ordered:</span>\n <span>\n {formatDate(cart.lastOrdered, {\n hour: undefined,\n minute: undefined,\n hour12: undefined,\n })}\n </span>\n </div>\n )}\n </div>\n\n <div className=\"flex gap-2 mt-4\">\n <button\n type=\"button\"\n onClick={() => navigateTo(`/customer/carts/${cart.id}`)}\n className=\"flex-1 flex items-center justify-center gap-1.5 rounded-lg bg-foreground px-3 py-2 text-xs font-medium text-background hover:opacity-90 transition-opacity\"\n >\n <RotateCcw className=\"h-3 w-3\" />\n Order Again\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/customer/carts/${cart.id}`)}\n className=\"flex-1 rounded-lg border border-border-subtle px-3 py-2 text-xs font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n View Menu\n </button>\n </div>\n </div>\n </div>\n ))}\n </div>\n </section>\n )}\n\n {/* Favorite Products */}\n {displayProducts.length > 0 && (\n <section>\n <h3 className=\"text-base font-semibold text-text-primary mb-4 flex items-center gap-2\">\n <Utensils className=\"h-4 w-4 text-text-secondary\" />\n Favorite Products ({displayProducts.length})\n </h3>\n <div className=\"space-y-3\">\n {displayProducts.map((product) => (\n <div\n key={product.id}\n className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\"\n >\n <div className=\"flex flex-col sm:flex-row sm:items-center gap-4\">\n {/* Image */}\n <img\n src={product.image}\n alt={product.name}\n className=\"w-20 h-20 rounded-lg object-cover shrink-0 mx-auto sm:mx-0\"\n />\n\n {/* Info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-start justify-between gap-2 mb-1\">\n <h4 className=\"text-sm font-semibold text-text-primary\">\n {product.name}\n </h4>\n <div className=\"flex items-center gap-2 shrink-0\">\n <span className=\"text-base font-bold text-text-primary\">\n {formatCurrency(product.price, { minimumFractionDigits: 0 })}\n </span>\n <button\n type=\"button\"\n onClick={() => handleRemoveProduct(product.id)}\n title=\"Remove from favorites\"\n className=\"rounded-md p-1 text-red-500 hover:bg-status-error-bg/10 transition-colors\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n\n <p className=\"text-xs text-text-secondary mb-2\">{product.description}</p>\n\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-text-secondary mb-2\">\n <span>\n From:{' '}\n <span className=\"font-medium text-text-primary\">\n {product.cartName}\n </span>\n </span>\n <span>Ordered {product.orderCount} times</span>\n <span>\n Added:{' '}\n {formatDate(product.addedToFavorites, {\n hour: undefined,\n minute: undefined,\n hour12: undefined,\n })}\n </span>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n {product.isVegetarian && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-green-500/10 px-2 py-0.5 text-[10px] font-medium text-green-600 dark:text-green-400\">\n <Leaf className=\"h-3 w-3\" />\n Veg\n </span>\n )}\n {product.isVegan && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-green-500/10 px-2 py-0.5 text-[10px] font-medium text-green-600 dark:text-green-400\">\n <Leaf className=\"h-3 w-3\" />\n Vegan\n </span>\n )}\n <span className=\"inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] font-medium text-text-secondary\">\n <Clock className=\"h-3 w-3\" />\n {product.preparationTime} min\n </span>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex sm:flex-col gap-2 shrink-0\">\n <button\n type=\"button\"\n onClick={() => navigateTo(`/customer/carts/${product.cartId}`)}\n className=\"flex-1 sm:flex-none rounded-lg bg-foreground px-4 py-2 text-xs font-medium text-background hover:opacity-90 transition-opacity whitespace-nowrap\"\n >\n Add to Cart\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/customer/carts/${product.cartId}`)}\n className=\"flex-1 sm:flex-none rounded-lg border border-border-subtle px-4 py-2 text-xs font-medium text-text-primary hover:bg-accent transition-colors whitespace-nowrap\"\n >\n View Cart\n </button>\n </div>\n </div>\n </div>\n ))}\n </div>\n </section>\n )}\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1,447 +0,0 @@
1
- import { useAthleteBridge as e } from "../../context/AthleteBridgeContext.js";
2
- import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { StatusBadge as n } from "../../components/StatusBadge.js";
4
- import { EmptyState as r } from "../../components/EmptyState.js";
5
- import { useOrders as i } from "../../hooks/useAthleteBridgeApi.js";
6
- import { formatCurrency as a, formatDate as o } from "../../utils/formatters.js";
7
- import { RatingDisplay as s } from "../../components/RatingDisplay.js";
8
- import { useMemo as c, useState as l } from "react";
9
- import { AlertCircle as u, CheckCircle2 as d, ChevronDown as f, Clock as p, Eye as m, Heart as h, IndianRupee as g, Loader2 as _, Package as v, RotateCcw as y, Search as b, ShoppingBag as x, Star as S, TrendingUp as C, Truck as w, XCircle as T } from "lucide-react";
10
- import { jsx as E, jsxs as D } from "react/jsx-runtime";
11
- import { EmphasisPanel as O, PagePurpose as k } from "@burdenoff/fe-libs/ui";
12
- //#region src/atheletebridge/pages/customer/OrderHistoryPage.tsx
13
- var A = 10, j = [
14
- {
15
- value: "",
16
- label: "All Status"
17
- },
18
- {
19
- value: "pending",
20
- label: "Pending"
21
- },
22
- {
23
- value: "confirmed",
24
- label: "Confirmed"
25
- },
26
- {
27
- value: "preparing",
28
- label: "Preparing"
29
- },
30
- {
31
- value: "ready",
32
- label: "Ready"
33
- },
34
- {
35
- value: "out_for_delivery",
36
- label: "Out for Delivery"
37
- },
38
- {
39
- value: "delivered",
40
- label: "Delivered"
41
- },
42
- {
43
- value: "cancelled",
44
- label: "Cancelled"
45
- }
46
- ], M = [
47
- {
48
- value: "7days",
49
- label: "Last 7 Days"
50
- },
51
- {
52
- value: "30days",
53
- label: "Last 30 Days"
54
- },
55
- {
56
- value: "90days",
57
- label: "Last 90 Days"
58
- },
59
- {
60
- value: "all",
61
- label: "All Time"
62
- }
63
- ], N = [
64
- {
65
- value: "recent",
66
- label: "Most Recent"
67
- },
68
- {
69
- value: "oldest",
70
- label: "Oldest First"
71
- },
72
- {
73
- value: "amount_high",
74
- label: "Amount: High to Low"
75
- },
76
- {
77
- value: "amount_low",
78
- label: "Amount: Low to High"
79
- }
80
- ];
81
- function P() {
82
- let { navigateTo: P, currentUser: F } = e(), [I, L] = l(A), [R, z] = l({
83
- status: "",
84
- dateRange: "30days",
85
- searchQuery: "",
86
- sortBy: "recent"
87
- }), { data: B = [], isLoading: V, isError: H } = i({ customerId: F?.id }), U = c(() => {
88
- let e = B.length, t = B.reduce((e, t) => e + t.total, 0), n = e > 0 ? Math.round(t / e) : 0, r = B.filter((e) => new Date(e.orderDate) > /* @__PURE__ */ new Date(Date.now() - 10080 * 60 * 1e3)).length, i = {};
89
- for (let e of B) i[e.cartName] = (i[e.cartName] || 0) + 1;
90
- return {
91
- totalOrders: e,
92
- totalSpent: t,
93
- averageOrderValue: n,
94
- recentOrdersCount: r,
95
- favoriteCart: Object.entries(i).sort((e, t) => t[1] - e[1])[0]?.[0] || "No orders yet"
96
- };
97
- }, [B]), W = c(() => {
98
- let e = [...B];
99
- if (R.status && (e = e.filter((e) => e.status === R.status)), R.dateRange !== "all") {
100
- let t = /* @__PURE__ */ new Date(), n = /* @__PURE__ */ new Date();
101
- switch (R.dateRange) {
102
- case "7days":
103
- n.setDate(t.getDate() - 7);
104
- break;
105
- case "30days":
106
- n.setDate(t.getDate() - 30);
107
- break;
108
- case "90days":
109
- n.setDate(t.getDate() - 90);
110
- break;
111
- }
112
- e = e.filter((e) => new Date(e.orderDate) >= n);
113
- }
114
- if (R.searchQuery) {
115
- let t = R.searchQuery.toLowerCase();
116
- e = e.filter((e) => e.id.toLowerCase().includes(t) || e.cartName.toLowerCase().includes(t) || e.items.some((e) => e.name.toLowerCase().includes(t)));
117
- }
118
- switch (R.sortBy) {
119
- case "recent":
120
- e.sort((e, t) => new Date(t.orderDate).getTime() - new Date(e.orderDate).getTime());
121
- break;
122
- case "oldest":
123
- e.sort((e, t) => new Date(e.orderDate).getTime() - new Date(t.orderDate).getTime());
124
- break;
125
- case "amount_high":
126
- e.sort((e, t) => t.total - e.total);
127
- break;
128
- case "amount_low":
129
- e.sort((e, t) => e.total - t.total);
130
- break;
131
- }
132
- return e;
133
- }, [B, R]), G = c(() => W.slice(0, I), [W, I]), K = I < W.length, q = (e, t) => {
134
- z((n) => ({
135
- ...n,
136
- [e]: t
137
- })), L(A);
138
- }, J = (e) => {
139
- P(`/customer/cart/${e.cartId}`), alert("Add items to cart to reorder");
140
- };
141
- return V ? /* @__PURE__ */ E(t, {
142
- title: "Order History",
143
- description: "Loading your orders...",
144
- children: /* @__PURE__ */ E("div", {
145
- className: "flex h-[60vh] items-center justify-center",
146
- children: /* @__PURE__ */ E(_, { className: "h-8 w-8 animate-spin text-primary" })
147
- })
148
- }) : H ? /* @__PURE__ */ E(t, {
149
- title: "Order History",
150
- description: "Error loading orders",
151
- children: /* @__PURE__ */ D("div", {
152
- className: "flex h-[60vh] flex-col items-center justify-center gap-4",
153
- children: [
154
- /* @__PURE__ */ E(u, { className: "h-12 w-12 text-status-error-text" }),
155
- /* @__PURE__ */ E("h2", {
156
- className: "text-xl font-semibold",
157
- children: "Error loading your orders"
158
- }),
159
- /* @__PURE__ */ E("button", {
160
- type: "button",
161
- onClick: () => window.location.reload(),
162
- className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text",
163
- children: "Retry"
164
- })
165
- ]
166
- })
167
- }) : /* @__PURE__ */ D(t, {
168
- title: "Order History",
169
- description: "View all your past and current orders",
170
- children: [
171
- /* @__PURE__ */ E(k, {
172
- className: "mb-6",
173
- children: "A complete record of everything you've ordered. Review past and in-progress orders, see how much you've spent, reorder your favourites in one tap, and filter by status or date to find a specific order quickly."
174
- }),
175
- /* @__PURE__ */ E(O, {
176
- className: "mb-6",
177
- children: /* @__PURE__ */ D("div", {
178
- className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3",
179
- children: [
180
- /* @__PURE__ */ D("div", {
181
- className: "rounded-lg border border-border-subtle bg-bg-surface p-3.5",
182
- children: [/* @__PURE__ */ D("div", {
183
- className: "flex items-center gap-2 mb-1",
184
- children: [/* @__PURE__ */ E(v, { className: "h-3.5 w-3.5 text-text-secondary" }), /* @__PURE__ */ E("p", {
185
- className: "text-xs text-text-secondary",
186
- children: "Total Orders"
187
- })]
188
- }), /* @__PURE__ */ E("p", {
189
- className: "text-xl font-bold text-text-primary",
190
- children: U.totalOrders
191
- })]
192
- }),
193
- /* @__PURE__ */ D("div", {
194
- className: "rounded-lg border border-border-subtle bg-bg-surface p-3.5",
195
- children: [/* @__PURE__ */ D("div", {
196
- className: "flex items-center gap-2 mb-1",
197
- children: [/* @__PURE__ */ E(g, { className: "h-3.5 w-3.5 text-text-secondary" }), /* @__PURE__ */ E("p", {
198
- className: "text-xs text-text-secondary",
199
- children: "Total Spent"
200
- })]
201
- }), /* @__PURE__ */ E("p", {
202
- className: "text-xl font-bold text-text-primary",
203
- children: a(U.totalSpent, { minimumFractionDigits: 0 })
204
- })]
205
- }),
206
- /* @__PURE__ */ D("div", {
207
- className: "rounded-lg border border-border-subtle bg-bg-surface p-3.5",
208
- children: [/* @__PURE__ */ D("div", {
209
- className: "flex items-center gap-2 mb-1",
210
- children: [/* @__PURE__ */ E(C, { className: "h-3.5 w-3.5 text-text-secondary" }), /* @__PURE__ */ E("p", {
211
- className: "text-xs text-text-secondary",
212
- children: "Average Order"
213
- })]
214
- }), /* @__PURE__ */ E("p", {
215
- className: "text-xl font-bold text-text-primary",
216
- children: a(U.averageOrderValue, { minimumFractionDigits: 0 })
217
- })]
218
- }),
219
- /* @__PURE__ */ D("div", {
220
- className: "rounded-lg border border-border-subtle bg-bg-surface p-3.5",
221
- children: [/* @__PURE__ */ D("div", {
222
- className: "flex items-center gap-2 mb-1",
223
- children: [/* @__PURE__ */ E(p, { className: "h-3.5 w-3.5 text-text-secondary" }), /* @__PURE__ */ E("p", {
224
- className: "text-xs text-text-secondary",
225
- children: "Recent Orders"
226
- })]
227
- }), /* @__PURE__ */ E("p", {
228
- className: "text-xl font-bold text-text-primary",
229
- children: U.recentOrdersCount
230
- })]
231
- }),
232
- /* @__PURE__ */ D("div", {
233
- className: "rounded-lg border border-border-subtle bg-bg-surface p-3.5 col-span-2 md:col-span-1",
234
- children: [/* @__PURE__ */ D("div", {
235
- className: "flex items-center gap-2 mb-1",
236
- children: [/* @__PURE__ */ E(h, { className: "h-3.5 w-3.5 text-text-secondary" }), /* @__PURE__ */ E("p", {
237
- className: "text-xs text-text-secondary",
238
- children: "Favorite Cart"
239
- })]
240
- }), /* @__PURE__ */ E("p", {
241
- className: "text-sm font-bold text-text-primary truncate",
242
- children: U.favoriteCart
243
- })]
244
- })
245
- ]
246
- })
247
- }),
248
- /* @__PURE__ */ E("div", {
249
- className: "rounded-lg border border-border-subtle bg-bg-surface p-4 mb-6",
250
- children: /* @__PURE__ */ D("div", {
251
- className: "grid grid-cols-1 md:grid-cols-4 gap-3",
252
- children: [
253
- /* @__PURE__ */ D("div", {
254
- className: "relative",
255
- children: [/* @__PURE__ */ E(b, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary" }), /* @__PURE__ */ E("input", {
256
- type: "text",
257
- placeholder: "Search orders...",
258
- value: R.searchQuery,
259
- onChange: (e) => q("searchQuery", e.target.value),
260
- className: "w-full rounded-lg border border-border-subtle bg-bg-surface pl-9 pr-3 py-2.5 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
261
- })]
262
- }),
263
- /* @__PURE__ */ E("select", {
264
- value: R.status,
265
- onChange: (e) => q("status", e.target.value),
266
- className: "w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
267
- children: j.map((e) => /* @__PURE__ */ E("option", {
268
- value: e.value,
269
- children: e.label
270
- }, e.value))
271
- }),
272
- /* @__PURE__ */ E("select", {
273
- value: R.dateRange,
274
- onChange: (e) => q("dateRange", e.target.value),
275
- className: "w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
276
- children: M.map((e) => /* @__PURE__ */ E("option", {
277
- value: e.value,
278
- children: e.label
279
- }, e.value))
280
- }),
281
- /* @__PURE__ */ E("select", {
282
- value: R.sortBy,
283
- onChange: (e) => q("sortBy", e.target.value),
284
- className: "w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
285
- children: N.map((e) => /* @__PURE__ */ E("option", {
286
- value: e.value,
287
- children: e.label
288
- }, e.value))
289
- })
290
- ]
291
- })
292
- }),
293
- V ? /* @__PURE__ */ D("div", {
294
- className: "flex flex-col items-center justify-center py-12 text-center",
295
- children: [/* @__PURE__ */ E("div", { className: "animate-spin rounded-full h-12 w-12 border-b-2 border-foreground mx-auto mb-4" }), /* @__PURE__ */ E("p", {
296
- className: "text-sm text-text-secondary",
297
- children: "Loading orders..."
298
- })]
299
- }) : G.length === 0 ? /* @__PURE__ */ E(r, {
300
- illustration: "empty-data",
301
- icon: /* @__PURE__ */ E(x, { className: "h-12 w-12" }),
302
- title: "No orders found",
303
- description: R.searchQuery || R.status ? "Try adjusting your filters" : "You haven't placed any orders yet",
304
- action: /* @__PURE__ */ E("button", {
305
- type: "button",
306
- onClick: () => P("/customer/carts"),
307
- className: "rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background hover:opacity-90 transition-opacity",
308
- children: "Start Ordering"
309
- })
310
- }) : /* @__PURE__ */ E("div", {
311
- className: "space-y-4",
312
- children: G.map((e) => /* @__PURE__ */ E("div", {
313
- className: "rounded-lg border border-border-subtle bg-bg-surface hover:shadow-md transition-shadow",
314
- children: /* @__PURE__ */ D("div", {
315
- className: "p-4 md:p-5",
316
- children: [
317
- /* @__PURE__ */ D("div", {
318
- className: "flex flex-col md:flex-row md:items-center justify-between mb-3",
319
- children: [/* @__PURE__ */ D("div", {
320
- className: "mb-3 md:mb-0",
321
- children: [/* @__PURE__ */ D("div", {
322
- className: "flex flex-col sm:flex-row sm:items-center gap-2",
323
- children: [/* @__PURE__ */ E("h3", {
324
- className: "text-base font-semibold text-text-primary",
325
- children: e.cartName
326
- }), /* @__PURE__ */ E(n, { status: e.status })]
327
- }), /* @__PURE__ */ D("p", {
328
- className: "text-xs text-text-secondary mt-1",
329
- children: [
330
- "Order #",
331
- e.id,
332
- " · ",
333
- o(e.orderDate)
334
- ]
335
- })]
336
- }), /* @__PURE__ */ D("div", {
337
- className: "flex flex-col sm:flex-row sm:items-center gap-2",
338
- children: [/* @__PURE__ */ E("p", {
339
- className: "text-lg font-bold text-text-primary",
340
- children: a(e.total, { minimumFractionDigits: 0 })
341
- }), /* @__PURE__ */ D("div", {
342
- className: "flex gap-2",
343
- children: [/* @__PURE__ */ D("button", {
344
- type: "button",
345
- onClick: () => P(`/customer/orders/${e.id}`),
346
- className: "flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent transition-colors",
347
- children: [/* @__PURE__ */ E(m, { className: "h-3 w-3" }), "Track Order"]
348
- }), e.status === "delivered" && /* @__PURE__ */ D("button", {
349
- type: "button",
350
- onClick: () => J(e),
351
- className: "flex items-center gap-1.5 rounded-lg bg-foreground px-3 py-1.5 text-xs font-medium text-background hover:opacity-90 transition-opacity",
352
- children: [/* @__PURE__ */ E(y, { className: "h-3 w-3" }), "Reorder"]
353
- })]
354
- })]
355
- })]
356
- }),
357
- /* @__PURE__ */ E("div", {
358
- className: "border-t border-border-subtle pt-3",
359
- children: /* @__PURE__ */ D("div", {
360
- className: "flex flex-wrap gap-1",
361
- children: [e.items.slice(0, 3).map((t, n) => /* @__PURE__ */ D("span", {
362
- className: "text-xs text-text-secondary",
363
- children: [
364
- t.name,
365
- " (",
366
- t.quantity,
367
- ")",
368
- n < Math.min(2, e.items.length - 1) && ", "
369
- ]
370
- }, n)), e.items.length > 3 && /* @__PURE__ */ D("span", {
371
- className: "text-xs text-text-secondary",
372
- children: [
373
- "+",
374
- e.items.length - 3,
375
- " more items"
376
- ]
377
- })]
378
- })
379
- }),
380
- /* @__PURE__ */ D("div", {
381
- className: "mt-3",
382
- children: [
383
- e.status === "delivered" && /* @__PURE__ */ D("div", {
384
- className: "flex items-center gap-1.5 text-xs text-green-600 dark:text-green-400",
385
- children: [/* @__PURE__ */ E(d, { className: "h-3 w-3" }), /* @__PURE__ */ E("span", { children: "Order delivered successfully" })]
386
- }),
387
- e.status === "cancelled" && /* @__PURE__ */ D("div", {
388
- className: "flex items-center gap-1.5 text-xs text-status-error-text",
389
- children: [/* @__PURE__ */ E(T, { className: "h-3 w-3" }), /* @__PURE__ */ D("span", { children: ["Cancelled", e.cancellationReason && ` - ${e.cancellationReason}`] })]
390
- }),
391
- [
392
- "pending",
393
- "confirmed",
394
- "preparing",
395
- "ready",
396
- "out_for_delivery"
397
- ].includes(e.status) && /* @__PURE__ */ D("div", {
398
- className: "flex items-center gap-1.5 text-xs text-blue-600 dark:text-blue-400",
399
- children: [/* @__PURE__ */ E(w, { className: "h-3 w-3" }), /* @__PURE__ */ D("span", { children: [
400
- "Estimated delivery by",
401
- " ",
402
- e.estimatedDeliveryTime ? o(e.estimatedDeliveryTime) : "TBD"
403
- ] })]
404
- })
405
- ]
406
- }),
407
- e.status === "delivered" && /* @__PURE__ */ E("div", {
408
- className: "mt-3 flex flex-col sm:flex-row sm:items-center justify-between gap-2",
409
- children: e.rating ? /* @__PURE__ */ D("div", {
410
- className: "flex flex-col sm:flex-row sm:items-center gap-2",
411
- children: [/* @__PURE__ */ E(s, { value: e.rating }), e.review && /* @__PURE__ */ D("p", {
412
- className: "text-xs text-text-secondary italic",
413
- children: [
414
- "“",
415
- e.review,
416
- "”"
417
- ]
418
- })]
419
- }) : /* @__PURE__ */ D("button", {
420
- type: "button",
421
- onClick: () => P(`/customer/orders/${e.id}/rate`),
422
- className: "flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent transition-colors",
423
- children: [/* @__PURE__ */ E(S, { className: "h-3 w-3" }), "Rate Order"]
424
- })
425
- })
426
- ]
427
- })
428
- }, e.id))
429
- }),
430
- K && !V && /* @__PURE__ */ E("div", {
431
- className: "text-center mt-8",
432
- children: /* @__PURE__ */ D("button", {
433
- type: "button",
434
- onClick: () => {
435
- L((e) => e + A);
436
- },
437
- className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle px-6 py-2.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors",
438
- children: [/* @__PURE__ */ E(f, { className: "h-4 w-4" }), "Load More Orders"]
439
- })
440
- })
441
- ]
442
- });
443
- }
444
- //#endregion
445
- export { P as OrderHistoryPage };
446
-
447
- //# sourceMappingURL=OrderHistoryPage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"OrderHistoryPage.js","names":[],"sources":["../../../../src/atheletebridge/pages/customer/OrderHistoryPage.tsx"],"sourcesContent":["/**\n * Order History Page\n * @module atheletebridge/pages/customer\n *\n * Full list of customer orders with stats summary, search, status/date/sort\n * filters, rating display, reorder, cancellation reason, and Load More pagination.\n */\n\nimport { useState, useMemo, useCallback, useEffect } from 'react';\nimport {\n ShoppingBag,\n Search,\n Star,\n RotateCcw,\n Eye,\n ChevronDown,\n Package,\n IndianRupee,\n TrendingUp,\n Clock,\n Heart,\n CheckCircle2,\n XCircle,\n Truck,\n Loader2,\n AlertCircle,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { RatingDisplay } from '../../components/RatingDisplay';\nimport { useAthleteBridge } from '../../context/AthleteBridgeContext';\nimport { useOrders } from '../../hooks/useAthleteBridgeApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency, formatDate } from '../../utils/formatters';\nimport type { OrderStatus, MockOrder } from '../../types';\n\ninterface OrderFilters {\n status: string;\n dateRange: string;\n searchQuery: string;\n sortBy: string;\n}\n\nconst PAGE_SIZE = 10;\n\nconst statusOptions = [\n { value: '', label: 'All Status' },\n { value: 'pending', label: 'Pending' },\n { value: 'confirmed', label: 'Confirmed' },\n { value: 'preparing', label: 'Preparing' },\n { value: 'ready', label: 'Ready' },\n { value: 'out_for_delivery', label: 'Out for Delivery' },\n { value: 'delivered', label: 'Delivered' },\n { value: 'cancelled', label: 'Cancelled' },\n];\n\nconst dateRangeOptions = [\n { value: '7days', label: 'Last 7 Days' },\n { value: '30days', label: 'Last 30 Days' },\n { value: '90days', label: 'Last 90 Days' },\n { value: 'all', label: 'All Time' },\n];\n\nconst sortOptions = [\n { value: 'recent', label: 'Most Recent' },\n { value: 'oldest', label: 'Oldest First' },\n { value: 'amount_high', label: 'Amount: High to Low' },\n { value: 'amount_low', label: 'Amount: Low to High' },\n];\n\nexport function OrderHistoryPage() {\n const { navigateTo, currentUser } = useAthleteBridge();\n const [displayCount, setDisplayCount] = useState(PAGE_SIZE);\n const [filters, setFilters] = useState<OrderFilters>({\n status: '',\n dateRange: '30days',\n searchQuery: '',\n sortBy: 'recent',\n });\n\n const { data: allOrders = [], isLoading, isError } = useOrders({ customerId: currentUser?.id });\n\n // Calculate stats from all orders\n const orderStats = useMemo(() => {\n const totalOrders = allOrders.length;\n const totalSpent = allOrders.reduce((sum, o) => sum + o.total, 0);\n const averageOrderValue = totalOrders > 0 ? Math.round(totalSpent / totalOrders) : 0;\n const recentOrdersCount = allOrders.filter(\n (o) => new Date(o.orderDate) > new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)\n ).length;\n\n // Find favorite cart (most ordered from)\n const cartCounts: Record<string, number> = {};\n for (const o of allOrders) {\n cartCounts[o.cartName] = (cartCounts[o.cartName] || 0) + 1;\n }\n const favoriteCart =\n Object.entries(cartCounts).sort((a, b) => b[1] - a[1])[0]?.[0] || 'No orders yet';\n\n return { totalOrders, totalSpent, averageOrderValue, recentOrdersCount, favoriteCart };\n }, [allOrders]);\n\n // Filter and sort orders\n const filteredOrders = useMemo(() => {\n let orders = [...allOrders];\n\n // Filter by status\n if (filters.status) {\n orders = orders.filter((o) => o.status === filters.status);\n }\n\n // Filter by date range\n if (filters.dateRange !== 'all') {\n const now = new Date();\n const dateLimit = new Date();\n switch (filters.dateRange) {\n case '7days':\n dateLimit.setDate(now.getDate() - 7);\n break;\n case '30days':\n dateLimit.setDate(now.getDate() - 30);\n break;\n case '90days':\n dateLimit.setDate(now.getDate() - 90);\n break;\n }\n orders = orders.filter((o) => new Date(o.orderDate) >= dateLimit);\n }\n\n // Search filter\n if (filters.searchQuery) {\n const query = filters.searchQuery.toLowerCase();\n orders = orders.filter(\n (o) =>\n o.id.toLowerCase().includes(query) ||\n o.cartName.toLowerCase().includes(query) ||\n o.items.some((item) => item.name.toLowerCase().includes(query))\n );\n }\n\n // Sort\n switch (filters.sortBy) {\n case 'recent':\n orders.sort((a, b) => new Date(b.orderDate).getTime() - new Date(a.orderDate).getTime());\n break;\n case 'oldest':\n orders.sort((a, b) => new Date(a.orderDate).getTime() - new Date(b.orderDate).getTime());\n break;\n case 'amount_high':\n orders.sort((a, b) => b.total - a.total);\n break;\n case 'amount_low':\n orders.sort((a, b) => a.total - b.total);\n break;\n }\n\n return orders;\n }, [allOrders, filters]);\n\n const displayedOrders = useMemo(\n () => filteredOrders.slice(0, displayCount),\n [filteredOrders, displayCount]\n );\n\n const hasMore = displayCount < filteredOrders.length;\n\n const handleFilterChange = (key: keyof OrderFilters, value: string) => {\n setFilters((prev) => ({ ...prev, [key]: value }));\n setDisplayCount(PAGE_SIZE);\n };\n\n const handleReorder = (order: MockOrder) => {\n navigateTo(`/customer/cart/${order.cartId}`);\n alert('Add items to cart to reorder');\n };\n\n const handleLoadMore = () => {\n setDisplayCount((prev) => prev + PAGE_SIZE);\n };\n\n if (isLoading) {\n return (\n <PageLayout title=\"Order History\" description=\"Loading your orders...\">\n <div className=\"flex h-[60vh] items-center justify-center\">\n <Loader2 className=\"h-8 w-8 animate-spin text-primary\" />\n </div>\n </PageLayout>\n );\n }\n\n if (isError) {\n return (\n <PageLayout title=\"Order History\" description=\"Error loading orders\">\n <div className=\"flex h-[60vh] flex-col items-center justify-center gap-4\">\n <AlertCircle className=\"h-12 w-12 text-status-error-text\" />\n <h2 className=\"text-xl font-semibold\">Error loading your orders</h2>\n <button\n type=\"button\"\n onClick={() => window.location.reload()}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n Retry\n </button>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout title=\"Order History\" description=\"View all your past and current orders\">\n <PagePurpose className=\"mb-6\">\n A complete record of everything you&apos;ve ordered. Review past and in-progress orders,\n see how much you&apos;ve spent, reorder your favourites in one tap, and filter by status or\n date to find a specific order quickly.\n </PagePurpose>\n\n {/* Stats Summary */}\n <EmphasisPanel className=\"mb-6\">\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3.5\">\n <div className=\"flex items-center gap-2 mb-1\">\n <Package className=\"h-3.5 w-3.5 text-text-secondary\" />\n <p className=\"text-xs text-text-secondary\">Total Orders</p>\n </div>\n <p className=\"text-xl font-bold text-text-primary\">{orderStats.totalOrders}</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3.5\">\n <div className=\"flex items-center gap-2 mb-1\">\n <IndianRupee className=\"h-3.5 w-3.5 text-text-secondary\" />\n <p className=\"text-xs text-text-secondary\">Total Spent</p>\n </div>\n <p className=\"text-xl font-bold text-text-primary\">\n {formatCurrency(orderStats.totalSpent, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3.5\">\n <div className=\"flex items-center gap-2 mb-1\">\n <TrendingUp className=\"h-3.5 w-3.5 text-text-secondary\" />\n <p className=\"text-xs text-text-secondary\">Average Order</p>\n </div>\n <p className=\"text-xl font-bold text-text-primary\">\n {formatCurrency(orderStats.averageOrderValue, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3.5\">\n <div className=\"flex items-center gap-2 mb-1\">\n <Clock className=\"h-3.5 w-3.5 text-text-secondary\" />\n <p className=\"text-xs text-text-secondary\">Recent Orders</p>\n </div>\n <p className=\"text-xl font-bold text-text-primary\">{orderStats.recentOrdersCount}</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-3.5 col-span-2 md:col-span-1\">\n <div className=\"flex items-center gap-2 mb-1\">\n <Heart className=\"h-3.5 w-3.5 text-text-secondary\" />\n <p className=\"text-xs text-text-secondary\">Favorite Cart</p>\n </div>\n <p className=\"text-sm font-bold text-text-primary truncate\">{orderStats.favoriteCart}</p>\n </div>\n </div>\n </EmphasisPanel>\n\n {/* Filters */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 mb-6\">\n <div className=\"grid grid-cols-1 md:grid-cols-4 gap-3\">\n {/* Search */}\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search orders...\"\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 pl-9 pr-3 py-2.5 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\n {/* Status Filter */}\n <select\n value={filters.status}\n onChange={(e) => handleFilterChange('status', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n {statusOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n\n {/* Date Range */}\n <select\n value={filters.dateRange}\n onChange={(e) => handleFilterChange('dateRange', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n {dateRangeOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n\n {/* Sort */}\n <select\n value={filters.sortBy}\n onChange={(e) => handleFilterChange('sortBy', e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2.5 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n {sortOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n {/* Orders List */}\n {isLoading ? (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-foreground mx-auto mb-4\" />\n <p className=\"text-sm text-text-secondary\">Loading orders...</p>\n </div>\n ) : displayedOrders.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<ShoppingBag className=\"h-12 w-12\" />}\n title=\"No orders found\"\n description={\n filters.searchQuery || filters.status\n ? 'Try adjusting your filters'\n : \"You haven't placed any orders yet\"\n }\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/customer/carts')}\n className=\"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background hover:opacity-90 transition-opacity\"\n >\n Start Ordering\n </button>\n }\n />\n ) : (\n <div className=\"space-y-4\">\n {displayedOrders.map((order) => (\n <div\n key={order.id}\n className=\"rounded-lg border border-border-subtle bg-bg-surface hover:shadow-md transition-shadow\"\n >\n <div className=\"p-4 md:p-5\">\n {/* Order Header */}\n <div className=\"flex flex-col md:flex-row md:items-center justify-between mb-3\">\n <div className=\"mb-3 md:mb-0\">\n <div className=\"flex flex-col sm:flex-row sm:items-center gap-2\">\n <h3 className=\"text-base font-semibold text-text-primary\">\n {order.cartName}\n </h3>\n <StatusBadge status={order.status} />\n </div>\n <p className=\"text-xs text-text-secondary mt-1\">\n Order #{order.id} &middot; {formatDate(order.orderDate)}\n </p>\n </div>\n <div className=\"flex flex-col sm:flex-row sm:items-center gap-2\">\n <p className=\"text-lg font-bold text-text-primary\">\n {formatCurrency(order.total, { minimumFractionDigits: 0 })}\n </p>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={() => navigateTo(`/customer/orders/${order.id}`)}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <Eye className=\"h-3 w-3\" />\n Track Order\n </button>\n {order.status === 'delivered' && (\n <button\n type=\"button\"\n onClick={() => handleReorder(order)}\n className=\"flex items-center gap-1.5 rounded-lg bg-foreground px-3 py-1.5 text-xs font-medium text-background hover:opacity-90 transition-opacity\"\n >\n <RotateCcw className=\"h-3 w-3\" />\n Reorder\n </button>\n )}\n </div>\n </div>\n </div>\n\n {/* Order Items Summary */}\n <div className=\"border-t border-border-subtle pt-3\">\n <div className=\"flex flex-wrap gap-1\">\n {order.items.slice(0, 3).map((item, index) => (\n <span key={index} className=\"text-xs text-text-secondary\">\n {item.name} ({item.quantity})\n {index < Math.min(2, order.items.length - 1) && ', '}\n </span>\n ))}\n {order.items.length > 3 && (\n <span className=\"text-xs text-text-secondary\">\n +{order.items.length - 3} more items\n </span>\n )}\n </div>\n </div>\n\n {/* Status Message */}\n <div className=\"mt-3\">\n {order.status === 'delivered' && (\n <div className=\"flex items-center gap-1.5 text-xs text-green-600 dark:text-green-400\">\n <CheckCircle2 className=\"h-3 w-3\" />\n <span>Order delivered successfully</span>\n </div>\n )}\n {order.status === 'cancelled' && (\n <div className=\"flex items-center gap-1.5 text-xs text-status-error-text\">\n <XCircle className=\"h-3 w-3\" />\n <span>\n Cancelled{order.cancellationReason && ` - ${order.cancellationReason}`}\n </span>\n </div>\n )}\n {['pending', 'confirmed', 'preparing', 'ready', 'out_for_delivery'].includes(\n order.status\n ) && (\n <div className=\"flex items-center gap-1.5 text-xs text-blue-600 dark:text-blue-400\">\n <Truck className=\"h-3 w-3\" />\n <span>\n Estimated delivery by{' '}\n {order.estimatedDeliveryTime\n ? formatDate(order.estimatedDeliveryTime)\n : 'TBD'}\n </span>\n </div>\n )}\n </div>\n\n {/* Rating Section */}\n {order.status === 'delivered' && (\n <div className=\"mt-3 flex flex-col sm:flex-row sm:items-center justify-between gap-2\">\n {order.rating ? (\n <div className=\"flex flex-col sm:flex-row sm:items-center gap-2\">\n <RatingDisplay value={order.rating} />\n {order.review && (\n <p className=\"text-xs text-text-secondary italic\">\n &ldquo;{order.review}&rdquo;\n </p>\n )}\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/customer/orders/${order.id}/rate`)}\n className=\"flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <Star className=\"h-3 w-3\" />\n Rate Order\n </button>\n )}\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Load More */}\n {hasMore && !isLoading && (\n <div className=\"text-center mt-8\">\n <button\n type=\"button\"\n onClick={handleLoadMore}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle px-6 py-2.5 text-sm font-medium text-text-primary hover:bg-accent transition-colors\"\n >\n <ChevronDown className=\"h-4 w-4\" />\n Load More Orders\n </button>\n </div>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}