@burdenoff/microfe-atheletebridge 2026.626.1 → 2026.629.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 +1 @@
1
- {"version":3,"file":"useAthleteBridgeApi.js","names":[],"sources":["../../../src/atheletebridge/hooks/useAthleteBridgeApi.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\n\nimport { useAthleteBridge } from '../context';\nimport type {\n MockCart,\n MockOrder,\n InvestmentOpportunity,\n Investment,\n DashboardStats,\n AdminAnalytics,\n WorkerTask,\n} from '../types';\n\nconst atheletebridgeQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n\n return response.data;\n};\n\n// ============================================================================\n// Service Providers (Carts)\n// ============================================================================\n\nexport const useProviders = (query?: string) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'providers', query],\n queryFn: async () => {\n const result = await atheletebridgeQuery<{ listServiceProviders: any[] }>(\n `query Providers($filter: AthleteBridgeProviderFilterInput) {\n listServiceProviders(filter: $filter, limit: 200) {\n id name slug category status rating totalRatings averageOrderValue serviceTypes location businessHours createdAt\n }\n }`,\n {\n filter: query\n ? {\n query,\n }\n : undefined,\n },\n apiGatewayUrl\n );\n\n return result.listServiceProviders.map((p) => ({\n ...p,\n image: `https://images.unsplash.com/photo-1567620905732-2d1ec7ab7445?w=400`, // Placeholder\n images: [`https://images.unsplash.com/photo-1567620905732-2d1ec7ab7445?w=400`],\n isOpen: p.status === 'ACTIVE' || p.status === 'VERIFIED',\n isVerified: p.status === 'VERIFIED',\n distance: 0.5, // Mock\n estimatedTime: 20, // Mock\n createdAt: p.createdAt,\n })) as MockCart[];\n },\n });\n};\n\nexport const useOfferings = (providerId?: string) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'offerings', providerId],\n queryFn: async () => {\n const result = await atheletebridgeQuery<{ listOfferings: any[] }>(\n `query Offerings($providerId: String) {\n listOfferings(providerId: $providerId, limit: 300) {\n id providerId kind name slug category description price originalPrice stock durationMinutes serviceType tags isAvailable metadata media\n }\n }`,\n { providerId },\n apiGatewayUrl\n );\n return result.listOfferings;\n },\n enabled: Boolean(providerId),\n });\n};\n\n// ============================================================================\n// Orders\n// ============================================================================\n\nexport const useOrders = (input: { providerId?: string; customerId?: string } = {}) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'orders', input.providerId, input.customerId],\n queryFn: async () => {\n const result = await atheletebridgeQuery<{ listOrders: any[] }>(\n `query Orders($providerId: String, $customerId: String) {\n listOrders(providerId: $providerId, customerId: $customerId, limit: 200) {\n id orderNumber providerId customerId status paymentStatus fulfillmentType subtotal tax deliveryFee discount total notes timeline paymentMethod deliveryAddress createdAt\n provider { name }\n items { id offeringId name quantity unitPrice totalPrice customizations }\n }\n }`,\n input,\n apiGatewayUrl\n );\n\n return result.listOrders.map((o) => ({\n id: o.id,\n cartId: o.providerId,\n cartName: o.provider?.name || 'Unknown Cart',\n cartImage: `https://images.unsplash.com/photo-1567620905732-2d1ec7ab7445?w=100`, // Placeholder\n items: o.items.map((i: any) => ({\n id: i.id,\n name: i.name,\n quantity: i.quantity,\n price: i.unitPrice,\n customizations: i.customizations,\n })),\n total: o.total,\n subtotal: o.subtotal,\n taxes: o.tax,\n deliveryFee: o.deliveryFee,\n discount: o.discount,\n status: o.status.toLowerCase(),\n orderDate: o.createdAt,\n deliveryAddress: o.deliveryAddress,\n paymentMethod: o.paymentMethod || 'Cash',\n paymentStatus: o.paymentStatus.toLowerCase(),\n timeline: o.timeline || [],\n })) as MockOrder[];\n },\n });\n};\n\n// ============================================================================\n// Analytics & Stats\n// ============================================================================\n\nexport const useDashboardStats = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'dashboard-stats'],\n queryFn: async () => {\n const result = await atheletebridgeQuery<{\n atheletebridgeDashboardStats: DashboardStats;\n }>(\n `query DashboardStats { atheletebridgeDashboardStats { totalOrders totalRevenue activeProviders activeCustomers avgRating pendingOrders } }`,\n {},\n apiGatewayUrl\n );\n return result.atheletebridgeDashboardStats;\n },\n });\n};\n\nexport const useAdminAnalytics = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'admin-analytics'],\n queryFn: async () => {\n const result = await atheletebridgeQuery<{ atheletebridgeAdminAnalytics: AdminAnalytics }>(\n `query AdminAnalytics { atheletebridgeAdminAnalytics { revenueByCategory orderTrends topProviders customerGrowth categoryDistribution } }`,\n {},\n apiGatewayUrl\n );\n return result.atheletebridgeAdminAnalytics;\n },\n });\n};\n\n// ============================================================================\n// Investments\n// ============================================================================\n\nexport const useInvestmentOpportunities = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'investment-opportunities'],\n queryFn: async () => {\n const result = await atheletebridgeQuery<{ listInvestmentOpportunities: any[] }>(\n `query Opportunities {\n listInvestmentOpportunities(limit: 200) {\n id providerId title description targetAmount raisedAmount minimumInvestment expectedReturnsPct lockInMonths riskLevel status expiresAt terms businessMetrics createdAt\n provider { name }\n }\n }`,\n {},\n apiGatewayUrl\n );\n\n return result.listInvestmentOpportunities.map((o) => ({\n id: o.id,\n cartId: o.providerId,\n cartName: o.provider?.name || 'Unknown Cart',\n businessOwner: 'Owner', // Mock\n targetAmount: o.targetAmount,\n raisedAmount: o.raisedAmount,\n minimumInvestment: o.minimumInvestment,\n expectedReturns: o.expectedReturnsPct,\n investmentPeriod: o.lockInMonths,\n riskLevel: o.riskLevel.toLowerCase(),\n description: o.description,\n businessPlan: '',\n financialProjections: [],\n documents: [],\n investors: [],\n status: o.status.toLowerCase(),\n createdAt: o.createdAt,\n expiresAt: o.expiresAt,\n })) as InvestmentOpportunity[];\n },\n });\n};\n\nexport const useInvestments = (investorId: string) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'investments', investorId],\n queryFn: async () => {\n const result = await atheletebridgeQuery<{ listInvestments: any[] }>(\n `query Investments($investorId: String!) {\n listInvestments(investorId: $investorId) {\n id opportunityId amount currentValue expectedReturnsPct status investedAt maturedAt realizedReturns\n opportunity { provider { name } }\n }\n }`,\n { investorId },\n apiGatewayUrl\n );\n\n return result.listInvestments.map((i) => ({\n id: i.id,\n opportunityId: i.opportunityId,\n cartName: i.opportunity?.provider?.name || 'Unknown Cart',\n investedAmount: i.amount,\n currentValue: i.currentValue,\n returns: i.realizedReturns,\n returnsPercentage: i.expectedReturnsPct,\n investmentDate: i.investedAt,\n status: i.status.toLowerCase(),\n })) as Investment[];\n },\n enabled: Boolean(investorId),\n });\n};\n\n// ============================================================================\n// Workers & Tasks\n// ============================================================================\n\nexport const useWorkerTasks = (workerId: string) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'worker-tasks', workerId],\n queryFn: async () => {\n const result = await atheletebridgeQuery<{ listWorkerTasks: any[] }>(\n `query WorkerTasks($workerId: String!) {\n listWorkerTasks(workerId: $workerId, limit: 100) {\n id orderId providerId type description priority status assignedAt dueAt completedAt customerName customerPhone earnings distance notes\n provider { name }\n order { deliveryAddress }\n }\n }`,\n { workerId },\n apiGatewayUrl\n );\n\n return result.listWorkerTasks.map((t) => ({\n id: t.id,\n orderId: t.orderId,\n cartId: t.providerId,\n cartName: t.provider?.name || 'Unknown Cart',\n type: t.type.toLowerCase(),\n description: t.description,\n priority: t.priority.toLowerCase(),\n status: t.status.toLowerCase(),\n assignedAt: t.assignedAt,\n dueAt: t.dueAt,\n completedAt: t.completedAt,\n customerName: t.customerName,\n customerPhone: t.customerPhone,\n deliveryAddress: t.order?.deliveryAddress,\n earnings: t.earnings,\n distance: t.distance,\n notes: t.notes,\n })) as WorkerTask[];\n },\n enabled: Boolean(workerId),\n });\n};\n\nexport const useWorkerStats = (workerId: string) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'worker-stats', workerId],\n queryFn: async () => {\n const result = await atheletebridgeQuery<{ atheletebridgeWorkerStats: any }>(\n `query WorkerStats($workerId: String!) {\n atheletebridgeWorkerStats(workerId: $workerId) {\n totalDeliveries totalEarnings averageRating completionRate todayTasks todayEarnings\n }\n }`,\n { workerId },\n apiGatewayUrl\n );\n return result.atheletebridgeWorkerStats;\n },\n enabled: Boolean(workerId),\n });\n};\n\nexport const useWorkerSchedules = (workerId: string) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'worker-schedules', workerId],\n queryFn: async () => {\n const result = await atheletebridgeQuery<{ listWorkerSchedules: any[] }>(\n `query WorkerSchedules($workerId: String!) {\n listWorkerSchedules(workerId: $workerId) {\n id date startTime endTime providerId status tasksCompleted totalEarnings\n provider { name }\n }\n }`,\n { workerId },\n apiGatewayUrl\n );\n\n return result.listWorkerSchedules.map((s) => ({\n id: s.id,\n date: s.date,\n startTime: s.startTime,\n endTime: s.endTime,\n cartId: s.providerId,\n cartName: s.provider?.name || 'Unknown Cart',\n status: s.status.toLowerCase(),\n tasksCompleted: s.tasksCompleted,\n totalEarnings: s.totalEarnings,\n }));\n },\n enabled: Boolean(workerId),\n });\n};\n\n// ============================================================================\n// Reviews\n// ============================================================================\n\nexport const useReviews = (providerId: string) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'reviews', providerId],\n queryFn: async () => {\n const result = await atheletebridgeQuery<{ listReviews: any[] }>(\n `query Reviews($providerId: String!) {\n listReviews(providerId: $providerId) {\n id providerId customerId rating review response createdAt updatedAt\n }\n }`,\n { providerId },\n apiGatewayUrl\n );\n return result.listReviews;\n },\n enabled: Boolean(providerId),\n });\n};\n\n// ============================================================================\n// Mutations\n// ============================================================================\n\nexport const usePlaceOrder = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n\n return useMutation({\n mutationFn: async (input: Record<string, unknown>) => {\n const result = await atheletebridgeQuery<{ placeOrder: any }>(\n `mutation PlaceOrder($input: AthleteBridgePlaceOrderInput!) {\n placeOrder(input: $input) {\n id orderNumber status total createdAt\n }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.placeOrder;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'orders'] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'dashboard-stats'] });\n },\n });\n};\n\nexport const useCreateProvider = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n\n return useMutation({\n mutationFn: async (input: Record<string, unknown>) => {\n const result = await atheletebridgeQuery<{ atheletebridgeCreateServiceProvider: any }>(\n `mutation CreateProvider($input: AthleteBridgeCreateServiceProviderInput!) {\n atheletebridgeCreateServiceProvider(input: $input) {\n id name slug status category location rating\n }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.atheletebridgeCreateServiceProvider;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'providers'] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'dashboard-stats'] });\n },\n });\n};\n\nexport const useUpdateWorkerTaskStatus = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n\n return useMutation({\n mutationFn: async ({ taskId, status }: { taskId: string; status: string }) => {\n const result = await atheletebridgeQuery<{ atheletebridgeUpdateWorkerTaskStatus: any }>(\n `mutation UpdateTaskStatus($taskId: String!, $status: AthleteBridgeWorkerTaskStatus!) {\n atheletebridgeUpdateWorkerTaskStatus(taskId: $taskId, status: $status) {\n id status\n }\n }`,\n { taskId, status },\n apiGatewayUrl\n );\n return result.atheletebridgeUpdateWorkerTaskStatus;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'worker-tasks'] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'worker-stats'] });\n },\n });\n};\n\nexport const useWorkerClockInOut = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n\n return useMutation({\n mutationFn: async ({\n workerId,\n action,\n }: {\n workerId: string;\n action: 'CLOCK_IN' | 'CLOCK_OUT';\n }) => {\n const result = await atheletebridgeQuery<{ atheletebridgeWorkerClockInOut: any }>(\n `mutation ClockInOut($workerId: String!, $action: AthleteBridgeClockAction!) {\n atheletebridgeWorkerClockInOut(workerId: $workerId, action: $action) {\n success message\n }\n }`,\n { workerId, action },\n apiGatewayUrl\n );\n return result.atheletebridgeWorkerClockInOut;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'worker-schedules'] });\n },\n });\n};\n\n// ============================================================================\n// Main Hook\n// ============================================================================\n\nexport const useAthleteBridgeApi = () => {\n const { currentUser } = useAthleteBridge();\n const providers = useProviders();\n const orders = useOrders({ customerId: currentUser?.id });\n const dashboardStats = useDashboardStats();\n const investmentOpportunities = useInvestmentOpportunities();\n const investments = useInvestments(currentUser?.id || '');\n\n return useMemo(\n () => ({\n providers,\n orders,\n dashboardStats,\n investmentOpportunities,\n investments,\n }),\n [providers, orders, dashboardStats, investmentOpportunities, investments]\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useAthleteBridgeApi.js","names":[],"sources":["../../../src/atheletebridge/hooks/useAthleteBridgeApi.ts"],"sourcesContent":["/**\n * AthleteBridge API hooks\n * @module atheletebridge/hooks\n *\n * Thin react-query wrappers over the real `wspace-atheletebridge-svc` federated\n * GraphQL contract, reached through the workspace gateway with the workspace\n * dual-token. Every query/mutation here maps 1:1 to an `ath*` root field in the\n * service's `.hive-schema.graphql`. NO MOCKS — all data is live.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\n\nimport { useAthleteBridge } from '../context';\nimport type {\n AthCompleteSessionInput,\n AthCreateFixtureInput,\n AthCreateProgramInput,\n AthCreateTeamInput,\n AthAddMemberInput,\n AthAddDrillInput,\n AthBookSessionInput,\n AthDrill,\n AthFixture,\n AthFixtureConnection,\n AthFixtureStatus,\n AthMember,\n AthMemberStatus,\n AthPerformanceMetric,\n AthProgram,\n AthProgramConnection,\n AthProgramLevel,\n AthProgramStatus,\n AthRecordResultInput,\n AthSession,\n AthSessionConnection,\n AthSessionStatus,\n AthSport,\n AthStanding,\n AthTeam,\n AthTeamConnection,\n AthTeamStatus,\n AthUpdateProgramInput,\n AthUpdateTeamInput,\n AthWorkoutLogConnection,\n PaginationInput,\n} from '../types';\n\n// ============================================================================\n// Low-level query wrapper\n// ============================================================================\n\nconst athQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n\n return response.data;\n};\n\n// ============================================================================\n// GraphQL fragments (inline strings — exact fields from the svc schema)\n// ============================================================================\n\nconst TEAM_FIELDS = `\n id workspaceId name sport status description ageGroup season homeVenue\n headCoachId tags createdAt updatedAt\n`;\n\nconst MEMBER_FIELDS = `\n id workspaceId teamId userId displayName role status position jerseyNumber\n height weight dominantSide notes joinedAt createdAt updatedAt\n`;\n\nconst FIXTURE_FIELDS = `\n id workspaceId type status competition round venue homeTeamId awayTeamId\n homeScore awayScore scheduledAt kickoffAt notes createdAt updatedAt\n homeTeam { id name sport }\n awayTeam { id name sport }\n`;\n\nconst STANDING_FIELDS = `\n id workspaceId competition teamId played won drawn lost goalsFor goalsAgainst\n points rank createdAt updatedAt\n team { id name sport }\n`;\n\nconst DRILL_FIELDS = `\n id workspaceId programId name description weekNumber orderIndex sets reps\n durationSec restSec createdAt updatedAt\n video { id }\n`;\n\nconst PROGRAM_FIELDS = `\n id workspaceId coachId name sport level status summary weeks isTemplate tags\n createdAt updatedAt\n`;\n\nconst SESSION_FIELDS = `\n id workspaceId coachId athleteId programId title type status location\n meetingUrl scheduledAt durationMin completedAt feedback rating\n createdAt updatedAt\n`;\n\nconst WORKOUT_LOG_FIELDS = `\n id workspaceId athleteId programId title status performedAt durationMin rpe\n totalLoad metrics notes createdAt updatedAt\n`;\n\nconst METRIC_FIELDS = `\n id workspaceId athleteId type label value unit source recordedAt\n createdAt updatedAt\n`;\n\n// ============================================================================\n// Teams\n// ============================================================================\n\nexport interface TeamFilters {\n sport?: AthSport;\n status?: AthTeamStatus;\n pagination?: PaginationInput;\n}\n\nexport const useTeams = (filters: TeamFilters = {}) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'teams', filters],\n queryFn: async () => {\n const result = await athQuery<{ athListTeams: AthTeamConnection }>(\n `query AthListTeams($sport: AthSport, $status: AthTeamStatus, $pagination: PaginationInput) {\n athListTeams(sport: $sport, status: $status, pagination: $pagination) {\n items { ${TEAM_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n sport: filters.sport,\n status: filters.status,\n pagination: filters.pagination,\n },\n apiGatewayUrl\n );\n return result.athListTeams;\n },\n });\n};\n\nexport const useTeam = (id: string | undefined) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'team', id],\n queryFn: async () => {\n const result = await athQuery<{ athTeam: AthTeam | null }>(\n `query AthTeam($id: ID!) {\n athTeam(id: $id) {\n ${TEAM_FIELDS}\n members { ${MEMBER_FIELDS} }\n fixtures { ${FIXTURE_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.athTeam;\n },\n enabled: Boolean(id),\n });\n};\n\nexport const useTeamMembers = (teamId: string | undefined, status?: AthMemberStatus) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'members', teamId, status],\n queryFn: async () => {\n const result = await athQuery<{ athListMembers: AthMember[] }>(\n `query AthListMembers($teamId: ID!, $status: AthMemberStatus) {\n athListMembers(teamId: $teamId, status: $status) { ${MEMBER_FIELDS} }\n }`,\n { teamId, status },\n apiGatewayUrl\n );\n return result.athListMembers;\n },\n enabled: Boolean(teamId),\n });\n};\n\nexport const useCreateTeam = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (input: AthCreateTeamInput) => {\n const result = await athQuery<{ athCreateTeam: AthTeam }>(\n `mutation AthCreateTeam($input: AthCreateTeamInput!) {\n athCreateTeam(input: $input) { ${TEAM_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athCreateTeam;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'teams'] });\n },\n });\n};\n\nexport const useUpdateTeam = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: AthUpdateTeamInput }) => {\n const result = await athQuery<{ athUpdateTeam: AthTeam }>(\n `mutation AthUpdateTeam($id: ID!, $input: AthUpdateTeamInput!) {\n athUpdateTeam(id: $id, input: $input) { ${TEAM_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.athUpdateTeam;\n },\n onSuccess: (team) => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'teams'] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'team', team.id] });\n },\n });\n};\n\nexport const useArchiveTeam = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await athQuery<{ athArchiveTeam: boolean }>(\n `mutation AthArchiveTeam($id: ID!) { athArchiveTeam(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.athArchiveTeam;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'teams'] });\n },\n });\n};\n\nexport const useAddMember = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (input: AthAddMemberInput) => {\n const result = await athQuery<{ athAddMember: AthMember }>(\n `mutation AthAddMember($input: AthAddMemberInput!) {\n athAddMember(input: $input) { ${MEMBER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athAddMember;\n },\n onSuccess: (member) => {\n void queryClient.invalidateQueries({\n queryKey: ['atheletebridge', 'members', member.teamId],\n });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'team', member.teamId] });\n },\n });\n};\n\nexport const useRemoveMember = (teamId?: string) => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await athQuery<{ athRemoveMember: boolean }>(\n `mutation AthRemoveMember($id: ID!) { athRemoveMember(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.athRemoveMember;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'members', teamId] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'team', teamId] });\n },\n });\n};\n\n// ============================================================================\n// Fixtures & standings\n// ============================================================================\n\nexport interface FixtureFilters {\n status?: AthFixtureStatus;\n teamId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useFixtures = (filters: FixtureFilters = {}) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'fixtures', filters],\n queryFn: async () => {\n const result = await athQuery<{ athListFixtures: AthFixtureConnection }>(\n `query AthListFixtures($status: AthFixtureStatus, $teamId: ID, $pagination: PaginationInput) {\n athListFixtures(status: $status, teamId: $teamId, pagination: $pagination) {\n items { ${FIXTURE_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n teamId: filters.teamId,\n pagination: filters.pagination,\n },\n apiGatewayUrl\n );\n return result.athListFixtures;\n },\n });\n};\n\nexport const useFixture = (id: string | undefined) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'fixture', id],\n queryFn: async () => {\n const result = await athQuery<{ athFixture: AthFixture | null }>(\n `query AthFixture($id: ID!) {\n athFixture(id: $id) { ${FIXTURE_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.athFixture;\n },\n enabled: Boolean(id),\n });\n};\n\nexport const useStandings = (competition: string | undefined) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'standings', competition],\n queryFn: async () => {\n const result = await athQuery<{ athStandings: AthStanding[] }>(\n `query AthStandings($competition: String!) {\n athStandings(competition: $competition) { ${STANDING_FIELDS} }\n }`,\n { competition },\n apiGatewayUrl\n );\n return result.athStandings;\n },\n enabled: Boolean(competition),\n });\n};\n\nexport const useScheduleFixture = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (input: AthCreateFixtureInput) => {\n const result = await athQuery<{ athScheduleFixture: AthFixture }>(\n `mutation AthScheduleFixture($input: AthCreateFixtureInput!) {\n athScheduleFixture(input: $input) { ${FIXTURE_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athScheduleFixture;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'fixtures'] });\n },\n });\n};\n\nexport const useRecordFixtureResult = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: AthRecordResultInput }) => {\n const result = await athQuery<{ athRecordFixtureResult: AthFixture }>(\n `mutation AthRecordFixtureResult($id: ID!, $input: AthRecordResultInput!) {\n athRecordFixtureResult(id: $id, input: $input) { ${FIXTURE_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.athRecordFixtureResult;\n },\n onSuccess: (fixture) => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'fixtures'] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'fixture', fixture.id] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'standings'] });\n },\n });\n};\n\n// ============================================================================\n// Programs & drills\n// ============================================================================\n\nexport interface ProgramFilters {\n sport?: AthSport;\n level?: AthProgramLevel;\n status?: AthProgramStatus;\n pagination?: PaginationInput;\n}\n\nexport const usePrograms = (filters: ProgramFilters = {}) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'programs', filters],\n queryFn: async () => {\n const result = await athQuery<{ athListPrograms: AthProgramConnection }>(\n `query AthListPrograms($sport: AthSport, $level: AthProgramLevel, $status: AthProgramStatus, $pagination: PaginationInput) {\n athListPrograms(sport: $sport, level: $level, status: $status, pagination: $pagination) {\n items { ${PROGRAM_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n sport: filters.sport,\n level: filters.level,\n status: filters.status,\n pagination: filters.pagination,\n },\n apiGatewayUrl\n );\n return result.athListPrograms;\n },\n });\n};\n\nexport const useProgram = (id: string | undefined) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'program', id],\n queryFn: async () => {\n const result = await athQuery<{ athProgram: AthProgram | null }>(\n `query AthProgram($id: ID!) {\n athProgram(id: $id) {\n ${PROGRAM_FIELDS}\n drills { ${DRILL_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.athProgram;\n },\n enabled: Boolean(id),\n });\n};\n\nexport const useCreateProgram = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (input: AthCreateProgramInput) => {\n const result = await athQuery<{ athCreateProgram: AthProgram }>(\n `mutation AthCreateProgram($input: AthCreateProgramInput!) {\n athCreateProgram(input: $input) { ${PROGRAM_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athCreateProgram;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'programs'] });\n },\n });\n};\n\nexport const useUpdateProgram = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: AthUpdateProgramInput }) => {\n const result = await athQuery<{ athUpdateProgram: AthProgram }>(\n `mutation AthUpdateProgram($id: ID!, $input: AthUpdateProgramInput!) {\n athUpdateProgram(id: $id, input: $input) { ${PROGRAM_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.athUpdateProgram;\n },\n onSuccess: (program) => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'programs'] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'program', program.id] });\n },\n });\n};\n\nexport const useTransitionProgram = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async ({ id, status }: { id: string; status: AthProgramStatus }) => {\n const result = await athQuery<{ athTransitionProgram: AthProgram }>(\n `mutation AthTransitionProgram($id: ID!, $status: AthProgramStatus!) {\n athTransitionProgram(id: $id, status: $status) { ${PROGRAM_FIELDS} }\n }`,\n { id, status },\n apiGatewayUrl\n );\n return result.athTransitionProgram;\n },\n onSuccess: (program) => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'programs'] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'program', program.id] });\n },\n });\n};\n\nexport const useArchiveProgram = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await athQuery<{ athArchiveProgram: boolean }>(\n `mutation AthArchiveProgram($id: ID!) { athArchiveProgram(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.athArchiveProgram;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'programs'] });\n },\n });\n};\n\nexport const useAddDrill = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (input: AthAddDrillInput) => {\n const result = await athQuery<{ athAddDrill: AthDrill }>(\n `mutation AthAddDrill($input: AthAddDrillInput!) {\n athAddDrill(input: $input) { ${DRILL_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athAddDrill;\n },\n onSuccess: (drill) => {\n void queryClient.invalidateQueries({\n queryKey: ['atheletebridge', 'program', drill.programId],\n });\n },\n });\n};\n\nexport const useRemoveDrill = (programId?: string) => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await athQuery<{ athRemoveDrill: boolean }>(\n `mutation AthRemoveDrill($id: ID!) { athRemoveDrill(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.athRemoveDrill;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'program', programId] });\n },\n });\n};\n\n// ============================================================================\n// Coaching sessions\n// ============================================================================\n\nexport interface SessionFilters {\n athleteId?: string;\n coachId?: string;\n status?: AthSessionStatus;\n pagination?: PaginationInput;\n}\n\nexport const useSessions = (filters: SessionFilters = {}) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'sessions', filters],\n queryFn: async () => {\n const result = await athQuery<{ athListSessions: AthSessionConnection }>(\n `query AthListSessions($athleteId: ID, $coachId: ID, $status: AthSessionStatus, $pagination: PaginationInput) {\n athListSessions(athleteId: $athleteId, coachId: $coachId, status: $status, pagination: $pagination) {\n items { ${SESSION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n athleteId: filters.athleteId,\n coachId: filters.coachId,\n status: filters.status,\n pagination: filters.pagination,\n },\n apiGatewayUrl\n );\n return result.athListSessions;\n },\n });\n};\n\nexport const useSession = (id: string | undefined) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'session', id],\n queryFn: async () => {\n const result = await athQuery<{ athSession: AthSession | null }>(\n `query AthSession($id: ID!) {\n athSession(id: $id) { ${SESSION_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.athSession;\n },\n enabled: Boolean(id),\n });\n};\n\nexport const useBookSession = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (input: AthBookSessionInput) => {\n const result = await athQuery<{ athBookSession: AthSession }>(\n `mutation AthBookSession($input: AthBookSessionInput!) {\n athBookSession(input: $input) { ${SESSION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.athBookSession;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'sessions'] });\n },\n });\n};\n\nexport const useConfirmSession = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await athQuery<{ athConfirmSession: AthSession }>(\n `mutation AthConfirmSession($id: ID!) {\n athConfirmSession(id: $id) { ${SESSION_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.athConfirmSession;\n },\n onSuccess: (session) => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'sessions'] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'session', session.id] });\n },\n });\n};\n\nexport const useCompleteSession = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input?: AthCompleteSessionInput }) => {\n const result = await athQuery<{ athCompleteSession: AthSession }>(\n `mutation AthCompleteSession($id: ID!, $input: AthCompleteSessionInput) {\n athCompleteSession(id: $id, input: $input) { ${SESSION_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.athCompleteSession;\n },\n onSuccess: (session) => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'sessions'] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'session', session.id] });\n },\n });\n};\n\nexport const useCancelSession = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAthleteBridge();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await athQuery<{ athCancelSession: AthSession }>(\n `mutation AthCancelSession($id: ID!) {\n athCancelSession(id: $id) { ${SESSION_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.athCancelSession;\n },\n onSuccess: (session) => {\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'sessions'] });\n void queryClient.invalidateQueries({ queryKey: ['atheletebridge', 'session', session.id] });\n },\n });\n};\n\n// ============================================================================\n// Workout logs & performance metrics\n// ============================================================================\n\nexport interface WorkoutLogFilters {\n athleteId?: string;\n programId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useWorkoutLogs = (filters: WorkoutLogFilters = {}) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'workout-logs', filters],\n queryFn: async () => {\n const result = await athQuery<{ athListWorkoutLogs: AthWorkoutLogConnection }>(\n `query AthListWorkoutLogs($athleteId: ID, $programId: ID, $pagination: PaginationInput) {\n athListWorkoutLogs(athleteId: $athleteId, programId: $programId, pagination: $pagination) {\n items { ${WORKOUT_LOG_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n athleteId: filters.athleteId,\n programId: filters.programId,\n pagination: filters.pagination,\n },\n apiGatewayUrl\n );\n return result.athListWorkoutLogs;\n },\n });\n};\n\nexport const usePerformanceMetrics = (athleteId: string | undefined) => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'metrics', athleteId],\n queryFn: async () => {\n const result = await athQuery<{ athPerformanceMetrics: AthPerformanceMetric[] }>(\n `query AthPerformanceMetrics($athleteId: ID!) {\n athPerformanceMetrics(athleteId: $athleteId) { ${METRIC_FIELDS} }\n }`,\n { athleteId },\n apiGatewayUrl\n );\n return result.athPerformanceMetrics;\n },\n enabled: Boolean(athleteId),\n });\n};\n\n// ============================================================================\n// Health probe\n// ============================================================================\n\nexport const useHealth = () => {\n const { apiGatewayUrl } = useAthleteBridge();\n return useQuery({\n queryKey: ['atheletebridge', 'health'],\n queryFn: async () => {\n const result = await athQuery<{ athHealth: string }>(\n `query AthHealth { athHealth }`,\n {},\n apiGatewayUrl\n );\n return result.athHealth;\n },\n });\n};\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import "./context/AthleteBridgeContext.js";
2
2
  import "./utils/cn.js";
3
- import "./context/index.js";
4
3
  import "./utils/formatters.js";
4
+ import "./context/index.js";
5
5
  import "./AthleteBridgeRoot.js";
6
6
  import "./store/atheletebridgeStore.js";
7
7
  import "./store/index.js";
@@ -0,0 +1,169 @@
1
+ import { useAthleteBridge as e } from "../context/AthleteBridgeContext.js";
2
+ import { PageLayout as t } from "../components/PageLayout.js";
3
+ import { MetricsCard as n } from "../components/MetricsCard.js";
4
+ import { TeamCard as r } from "../components/TeamCard.js";
5
+ import { FixtureCard as i } from "../components/FixtureCard.js";
6
+ import { SessionCard as a } from "../components/SessionCard.js";
7
+ import { EmptyState as o } from "../components/EmptyState.js";
8
+ import { LoadingState as s } from "../components/LoadingState.js";
9
+ import { useFixtures as c, usePrograms as l, useSessions as u, useTeams as d } from "../hooks/useAthleteBridgeApi.js";
10
+ import { useMemo as f } from "react";
11
+ import { ArrowRight as p, CalendarDays as m, ClipboardCheck as h, Dumbbell as g, Plus as _, Trophy as v, Users as y } from "lucide-react";
12
+ import { jsx as b, jsxs as x } from "react/jsx-runtime";
13
+ import { EmphasisPanel as S, PagePurpose as C } from "@burdenoff/fe-libs/ui";
14
+ //#region src/atheletebridge/pages/DashboardPage.tsx
15
+ function w() {
16
+ let { navigateTo: w, currentUser: T } = e(), E = d({ pagination: { limit: 50 } }), D = c({ pagination: { limit: 50 } }), O = l({ pagination: { limit: 50 } }), k = u({ pagination: { limit: 50 } }), A = T?.firstName ?? T?.name ?? "coach", j = f(() => E.data?.items ?? [], [E.data]), M = f(() => D.data?.items ?? [], [D.data]), N = f(() => O.data?.items ?? [], [O.data]), P = f(() => k.data?.items ?? [], [k.data]), F = f(() => [...M].filter((e) => e.status === "SCHEDULED" || e.status === "LIVE").sort((e, t) => new Date(e.scheduledAt).getTime() - new Date(t.scheduledAt).getTime()).slice(0, 3), [M]), I = f(() => [...P].filter((e) => e.status === "REQUESTED" || e.status === "CONFIRMED").sort((e, t) => new Date(e.scheduledAt).getTime() - new Date(t.scheduledAt).getTime()).slice(0, 3), [P]), L = f(() => j.slice(0, 6), [j]), R = N.filter((e) => e.status === "PUBLISHED").length;
17
+ return E.isLoading || D.isLoading || O.isLoading || k.isLoading ? /* @__PURE__ */ b(t, {
18
+ title: "AthleteBridge",
19
+ hero: !0,
20
+ gradientTitle: !0,
21
+ children: /* @__PURE__ */ b(s, { label: "Loading your sporting operation…" })
22
+ }) : /* @__PURE__ */ x(t, {
23
+ title: `Welcome back, ${A}`,
24
+ description: "Your teams, fixtures, training and coaching — one connected record.",
25
+ hero: !0,
26
+ gradientTitle: !0,
27
+ actions: /* @__PURE__ */ x("button", {
28
+ type: "button",
29
+ onClick: () => w("/teams/new"),
30
+ className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90",
31
+ children: [/* @__PURE__ */ b(_, { className: "h-4 w-4" }), " New team"]
32
+ }),
33
+ children: [
34
+ /* @__PURE__ */ b(C, {
35
+ className: "mb-6",
36
+ children: "AthleteBridge is the operating system for sports, coaching and training. From here you can assemble your roster, schedule fixtures, build training programs, run coaching sessions and track athlete performance — all reading and writing the same workspace-scoped source of truth."
37
+ }),
38
+ /* @__PURE__ */ x(S, {
39
+ className: "mb-8",
40
+ children: [/* @__PURE__ */ b("h2", {
41
+ className: "mb-4 text-lg font-semibold text-text-primary",
42
+ children: "At a glance"
43
+ }), /* @__PURE__ */ x("div", {
44
+ className: "grid grid-cols-2 gap-4 lg:grid-cols-4",
45
+ children: [
46
+ /* @__PURE__ */ b(n, {
47
+ icon: /* @__PURE__ */ b(y, { className: "h-5 w-5" }),
48
+ value: j.length,
49
+ label: "Teams",
50
+ featured: !0
51
+ }),
52
+ /* @__PURE__ */ b(n, {
53
+ icon: /* @__PURE__ */ b(m, { className: "h-5 w-5" }),
54
+ value: M.length,
55
+ label: "Fixtures"
56
+ }),
57
+ /* @__PURE__ */ b(n, {
58
+ icon: /* @__PURE__ */ b(g, { className: "h-5 w-5" }),
59
+ value: `${R}/${N.length}`,
60
+ label: "Programs published"
61
+ }),
62
+ /* @__PURE__ */ b(n, {
63
+ icon: /* @__PURE__ */ b(h, { className: "h-5 w-5" }),
64
+ value: P.length,
65
+ label: "Sessions"
66
+ })
67
+ ]
68
+ })]
69
+ }),
70
+ /* @__PURE__ */ x("section", {
71
+ className: "mb-8",
72
+ children: [/* @__PURE__ */ x("div", {
73
+ className: "mb-4 flex items-center justify-between",
74
+ children: [/* @__PURE__ */ b("h2", {
75
+ className: "text-lg font-semibold text-text-primary",
76
+ children: "Upcoming fixtures"
77
+ }), /* @__PURE__ */ x("button", {
78
+ type: "button",
79
+ onClick: () => w("/fixtures"),
80
+ className: "flex items-center gap-1 text-sm font-medium text-primary hover:underline",
81
+ children: ["View all ", /* @__PURE__ */ b(p, { className: "h-3.5 w-3.5" })]
82
+ })]
83
+ }), F.length === 0 ? /* @__PURE__ */ b(o, {
84
+ illustration: "empty-calendar",
85
+ icon: /* @__PURE__ */ b(m, { className: "h-10 w-10" }),
86
+ title: "No upcoming fixtures",
87
+ description: "Schedule a match to start tracking results and standings.",
88
+ action: /* @__PURE__ */ b("button", {
89
+ type: "button",
90
+ onClick: () => w("/fixtures/new"),
91
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90",
92
+ children: "Schedule fixture"
93
+ })
94
+ }) : /* @__PURE__ */ b("div", {
95
+ className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3",
96
+ children: F.map((e) => /* @__PURE__ */ b(i, {
97
+ fixture: e,
98
+ onClick: () => w(`/fixtures/${e.id}`)
99
+ }, e.id))
100
+ })]
101
+ }),
102
+ /* @__PURE__ */ x("section", {
103
+ className: "mb-8",
104
+ children: [/* @__PURE__ */ x("div", {
105
+ className: "mb-4 flex items-center justify-between",
106
+ children: [/* @__PURE__ */ b("h2", {
107
+ className: "text-lg font-semibold text-text-primary",
108
+ children: "Upcoming sessions"
109
+ }), /* @__PURE__ */ x("button", {
110
+ type: "button",
111
+ onClick: () => w("/sessions"),
112
+ className: "flex items-center gap-1 text-sm font-medium text-primary hover:underline",
113
+ children: ["View all ", /* @__PURE__ */ b(p, { className: "h-3.5 w-3.5" })]
114
+ })]
115
+ }), I.length === 0 ? /* @__PURE__ */ b(o, {
116
+ illustration: "empty-calendar",
117
+ icon: /* @__PURE__ */ b(h, { className: "h-10 w-10" }),
118
+ title: "No upcoming sessions",
119
+ description: "Book a coaching session with an athlete to get started.",
120
+ action: /* @__PURE__ */ b("button", {
121
+ type: "button",
122
+ onClick: () => w("/sessions/new"),
123
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90",
124
+ children: "Book session"
125
+ })
126
+ }) : /* @__PURE__ */ b("div", {
127
+ className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3",
128
+ children: I.map((e) => /* @__PURE__ */ b(a, {
129
+ session: e,
130
+ onClick: () => w(`/sessions/${e.id}`)
131
+ }, e.id))
132
+ })]
133
+ }),
134
+ /* @__PURE__ */ x("section", { children: [/* @__PURE__ */ x("div", {
135
+ className: "mb-4 flex items-center justify-between",
136
+ children: [/* @__PURE__ */ b("h2", {
137
+ className: "text-lg font-semibold text-text-primary",
138
+ children: "Your teams"
139
+ }), /* @__PURE__ */ x("button", {
140
+ type: "button",
141
+ onClick: () => w("/teams"),
142
+ className: "flex items-center gap-1 text-sm font-medium text-primary hover:underline",
143
+ children: ["View all ", /* @__PURE__ */ b(p, { className: "h-3.5 w-3.5" })]
144
+ })]
145
+ }), L.length === 0 ? /* @__PURE__ */ b(o, {
146
+ illustration: "empty-data",
147
+ icon: /* @__PURE__ */ b(v, { className: "h-10 w-10" }),
148
+ title: "No teams yet",
149
+ description: "Create your first team to build a roster and schedule fixtures.",
150
+ action: /* @__PURE__ */ b("button", {
151
+ type: "button",
152
+ onClick: () => w("/teams/new"),
153
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90",
154
+ children: "Create team"
155
+ })
156
+ }) : /* @__PURE__ */ b("div", {
157
+ className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3",
158
+ children: L.map((e) => /* @__PURE__ */ b(r, {
159
+ team: e,
160
+ onClick: () => w(`/teams/${e.id}`)
161
+ }, e.id))
162
+ })] })
163
+ ]
164
+ });
165
+ }
166
+ //#endregion
167
+ export { w as DashboardPage };
168
+
169
+ //# sourceMappingURL=DashboardPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/atheletebridge/pages/DashboardPage.tsx"],"sourcesContent":["/**\n * Dashboard / Overview\n * @module atheletebridge/pages\n *\n * The AthleteBridge landing page: a workspace-wide command center that reads\n * live counts and recent items across teams, fixtures, programs and sessions\n * from the real `ath*` API.\n */\n\nimport { useMemo } from 'react';\nimport {\n Users,\n CalendarDays,\n Dumbbell,\n ClipboardCheck,\n ArrowRight,\n Plus,\n Trophy,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { MetricsCard } from '../components/MetricsCard';\nimport { TeamCard } from '../components/TeamCard';\nimport { FixtureCard } from '../components/FixtureCard';\nimport { SessionCard } from '../components/SessionCard';\nimport { EmptyState } from '../components/EmptyState';\nimport { LoadingState } from '../components/LoadingState';\nimport { useAthleteBridge } from '../context/AthleteBridgeContext';\nimport { useTeams, useFixtures, usePrograms, useSessions } from '../hooks/useAthleteBridgeApi';\n\nexport function DashboardPage() {\n const { navigateTo, currentUser } = useAthleteBridge();\n\n const teams = useTeams({ pagination: { limit: 50 } });\n const fixtures = useFixtures({ pagination: { limit: 50 } });\n const programs = usePrograms({ pagination: { limit: 50 } });\n const sessions = useSessions({ pagination: { limit: 50 } });\n\n const firstName = currentUser?.firstName ?? currentUser?.name ?? 'coach';\n\n const teamItems = useMemo(() => teams.data?.items ?? [], [teams.data]);\n const fixtureItems = useMemo(() => fixtures.data?.items ?? [], [fixtures.data]);\n const programItems = useMemo(() => programs.data?.items ?? [], [programs.data]);\n const sessionItems = useMemo(() => sessions.data?.items ?? [], [sessions.data]);\n\n const upcomingFixtures = useMemo(\n () =>\n [...fixtureItems]\n .filter((f) => f.status === 'SCHEDULED' || f.status === 'LIVE')\n .sort((a, b) => new Date(a.scheduledAt).getTime() - new Date(b.scheduledAt).getTime())\n .slice(0, 3),\n [fixtureItems]\n );\n\n const upcomingSessions = useMemo(\n () =>\n [...sessionItems]\n .filter((s) => s.status === 'REQUESTED' || s.status === 'CONFIRMED')\n .sort((a, b) => new Date(a.scheduledAt).getTime() - new Date(b.scheduledAt).getTime())\n .slice(0, 3),\n [sessionItems]\n );\n\n const recentTeams = useMemo(() => teamItems.slice(0, 6), [teamItems]);\n\n const publishedPrograms = programItems.filter((p) => p.status === 'PUBLISHED').length;\n\n const isLoading =\n teams.isLoading || fixtures.isLoading || programs.isLoading || sessions.isLoading;\n\n if (isLoading) {\n return (\n <PageLayout title=\"AthleteBridge\" hero gradientTitle>\n <LoadingState label=\"Loading your sporting operation…\" />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={`Welcome back, ${firstName}`}\n description=\"Your teams, fixtures, training and coaching — one connected record.\"\n hero\n gradientTitle\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/teams/new')}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n <Plus className=\"h-4 w-4\" /> New team\n </button>\n }\n >\n <PagePurpose className=\"mb-6\">\n AthleteBridge is the operating system for sports, coaching and training. From here you can\n assemble your roster, schedule fixtures, build training programs, run coaching sessions and\n track athlete performance — all reading and writing the same workspace-scoped source of\n truth.\n </PagePurpose>\n\n {/* KPIs */}\n <EmphasisPanel className=\"mb-8\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">At a glance</h2>\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-4\">\n <MetricsCard\n icon={<Users className=\"h-5 w-5\" />}\n value={teamItems.length}\n label=\"Teams\"\n featured\n />\n <MetricsCard\n icon={<CalendarDays className=\"h-5 w-5\" />}\n value={fixtureItems.length}\n label=\"Fixtures\"\n />\n <MetricsCard\n icon={<Dumbbell className=\"h-5 w-5\" />}\n value={`${publishedPrograms}/${programItems.length}`}\n label=\"Programs published\"\n />\n <MetricsCard\n icon={<ClipboardCheck className=\"h-5 w-5\" />}\n value={sessionItems.length}\n label=\"Sessions\"\n />\n </div>\n </EmphasisPanel>\n\n {/* Upcoming fixtures */}\n <section className=\"mb-8\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Upcoming fixtures</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/fixtures')}\n className=\"flex items-center gap-1 text-sm font-medium text-primary hover:underline\"\n >\n View all <ArrowRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n {upcomingFixtures.length === 0 ? (\n <EmptyState\n illustration=\"empty-calendar\"\n icon={<CalendarDays className=\"h-10 w-10\" />}\n title=\"No upcoming fixtures\"\n description=\"Schedule a match to start tracking results and standings.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/fixtures/new')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n Schedule fixture\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {upcomingFixtures.map((fixture) => (\n <FixtureCard\n key={fixture.id}\n fixture={fixture}\n onClick={() => navigateTo(`/fixtures/${fixture.id}`)}\n />\n ))}\n </div>\n )}\n </section>\n\n {/* Upcoming sessions */}\n <section className=\"mb-8\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Upcoming sessions</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/sessions')}\n className=\"flex items-center gap-1 text-sm font-medium text-primary hover:underline\"\n >\n View all <ArrowRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n {upcomingSessions.length === 0 ? (\n <EmptyState\n illustration=\"empty-calendar\"\n icon={<ClipboardCheck className=\"h-10 w-10\" />}\n title=\"No upcoming sessions\"\n description=\"Book a coaching session with an athlete to get started.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/sessions/new')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n Book session\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {upcomingSessions.map((session) => (\n <SessionCard\n key={session.id}\n session={session}\n onClick={() => navigateTo(`/sessions/${session.id}`)}\n />\n ))}\n </div>\n )}\n </section>\n\n {/* Teams */}\n <section>\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Your teams</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/teams')}\n className=\"flex items-center gap-1 text-sm font-medium text-primary hover:underline\"\n >\n View all <ArrowRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n {recentTeams.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Trophy className=\"h-10 w-10\" />}\n title=\"No teams yet\"\n description=\"Create your first team to build a roster and schedule fixtures.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/teams/new')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n Create team\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {recentTeams.map((team) => (\n <TeamCard key={team.id} team={team} onClick={() => navigateTo(`/teams/${team.id}`)} />\n ))}\n </div>\n )}\n </section>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,166 @@
1
+ import { PageLayout as e } from "../components/PageLayout.js";
2
+ import { EmptyState as t } from "../components/EmptyState.js";
3
+ import { ErrorState as n, LoadingState as r } from "../components/LoadingState.js";
4
+ import { useFixtures as i, useStandings as a } from "../hooks/useAthleteBridgeApi.js";
5
+ import { fieldInputClass as o } from "../components/form.js";
6
+ import { useEffect as s, useMemo as c, useState as l } from "react";
7
+ import { Search as u, Trophy as d } from "lucide-react";
8
+ import { useSearchParams as f } from "react-router-dom";
9
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
10
+ import { EmphasisPanel as h } from "@burdenoff/fe-libs/ui";
11
+ //#region src/atheletebridge/pages/StandingsPage.tsx
12
+ function g() {
13
+ let [g] = f(), _ = g.get("competition") ?? "", [v, y] = l(_), [b, x] = l(_), S = i({ pagination: { limit: 100 } }), C = c(() => {
14
+ let e = /* @__PURE__ */ new Set();
15
+ for (let t of S.data?.items ?? []) t.competition && e.add(t.competition);
16
+ return Array.from(e).sort();
17
+ }, [S.data]);
18
+ s(() => {
19
+ !b && C.length > 0 && (y(C[0]), x(C[0]));
20
+ }, [b, C]);
21
+ let w = a(b || void 0), T = c(() => [...w.data ?? []].sort((e, t) => t.points === e.points ? t.goalsFor - e.goalsFor : t.points - e.points), [w.data]);
22
+ return /* @__PURE__ */ m(e, {
23
+ title: "Standings",
24
+ description: "Live competition tables — recomputed automatically from results.",
25
+ children: [/* @__PURE__ */ m("form", {
26
+ onSubmit: (e) => {
27
+ e.preventDefault(), x(v.trim());
28
+ },
29
+ className: "mb-6 flex flex-wrap items-end gap-3",
30
+ children: [/* @__PURE__ */ m("div", {
31
+ className: "flex-1 min-w-[220px]",
32
+ children: [
33
+ /* @__PURE__ */ p("label", {
34
+ htmlFor: "competition",
35
+ className: "mb-1.5 block text-sm font-medium text-text-primary",
36
+ children: "Competition"
37
+ }),
38
+ /* @__PURE__ */ p("input", {
39
+ id: "competition",
40
+ list: "ath-competitions",
41
+ className: o,
42
+ value: v,
43
+ onChange: (e) => y(e.target.value),
44
+ placeholder: "e.g. Spring League 2026"
45
+ }),
46
+ /* @__PURE__ */ p("datalist", {
47
+ id: "ath-competitions",
48
+ children: C.map((e) => /* @__PURE__ */ p("option", { value: e }, e))
49
+ })
50
+ ]
51
+ }), /* @__PURE__ */ m("button", {
52
+ type: "submit",
53
+ className: "inline-flex h-[38px] items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90",
54
+ children: [/* @__PURE__ */ p(u, { className: "h-4 w-4" }), " View table"]
55
+ })]
56
+ }), b ? w.isLoading ? /* @__PURE__ */ p(r, { label: "Loading standings…" }) : w.isError ? /* @__PURE__ */ p(n, { onRetry: () => void w.refetch() }) : T.length === 0 ? /* @__PURE__ */ p(t, {
57
+ illustration: "empty-data",
58
+ icon: /* @__PURE__ */ p(d, { className: "h-10 w-10" }),
59
+ title: "No standings yet",
60
+ description: `No results have been recorded for "${b}". Record a fixture result to build the table.`
61
+ }) : /* @__PURE__ */ p(h, {
62
+ className: "overflow-x-auto",
63
+ children: /* @__PURE__ */ m("table", {
64
+ className: "w-full min-w-[640px] text-sm",
65
+ children: [/* @__PURE__ */ p("thead", { children: /* @__PURE__ */ m("tr", {
66
+ className: "border-b border-border-seam text-left text-xs uppercase tracking-wide text-text-secondary",
67
+ children: [
68
+ /* @__PURE__ */ p("th", {
69
+ className: "px-3 py-2 font-medium",
70
+ children: "#"
71
+ }),
72
+ /* @__PURE__ */ p("th", {
73
+ className: "px-3 py-2 font-medium",
74
+ children: "Team"
75
+ }),
76
+ /* @__PURE__ */ p("th", {
77
+ className: "px-3 py-2 text-center font-medium",
78
+ children: "P"
79
+ }),
80
+ /* @__PURE__ */ p("th", {
81
+ className: "px-3 py-2 text-center font-medium",
82
+ children: "W"
83
+ }),
84
+ /* @__PURE__ */ p("th", {
85
+ className: "px-3 py-2 text-center font-medium",
86
+ children: "D"
87
+ }),
88
+ /* @__PURE__ */ p("th", {
89
+ className: "px-3 py-2 text-center font-medium",
90
+ children: "L"
91
+ }),
92
+ /* @__PURE__ */ p("th", {
93
+ className: "px-3 py-2 text-center font-medium",
94
+ children: "GF"
95
+ }),
96
+ /* @__PURE__ */ p("th", {
97
+ className: "px-3 py-2 text-center font-medium",
98
+ children: "GA"
99
+ }),
100
+ /* @__PURE__ */ p("th", {
101
+ className: "px-3 py-2 text-center font-medium",
102
+ children: "GD"
103
+ }),
104
+ /* @__PURE__ */ p("th", {
105
+ className: "px-3 py-2 text-center font-semibold text-text-primary",
106
+ children: "Pts"
107
+ })
108
+ ]
109
+ }) }), /* @__PURE__ */ p("tbody", { children: T.map((e, t) => /* @__PURE__ */ m("tr", {
110
+ className: "border-b border-border-seam/60 last:border-0 hover:bg-bg-sunken/50",
111
+ children: [
112
+ /* @__PURE__ */ p("td", {
113
+ className: "px-3 py-2.5 tabular-nums text-text-secondary",
114
+ children: e.rank ?? t + 1
115
+ }),
116
+ /* @__PURE__ */ p("td", {
117
+ className: "px-3 py-2.5 font-medium text-text-primary",
118
+ children: e.team?.name ?? "Unknown team"
119
+ }),
120
+ /* @__PURE__ */ p("td", {
121
+ className: "px-3 py-2.5 text-center tabular-nums text-text-secondary",
122
+ children: e.played
123
+ }),
124
+ /* @__PURE__ */ p("td", {
125
+ className: "px-3 py-2.5 text-center tabular-nums text-text-secondary",
126
+ children: e.won
127
+ }),
128
+ /* @__PURE__ */ p("td", {
129
+ className: "px-3 py-2.5 text-center tabular-nums text-text-secondary",
130
+ children: e.drawn
131
+ }),
132
+ /* @__PURE__ */ p("td", {
133
+ className: "px-3 py-2.5 text-center tabular-nums text-text-secondary",
134
+ children: e.lost
135
+ }),
136
+ /* @__PURE__ */ p("td", {
137
+ className: "px-3 py-2.5 text-center tabular-nums text-text-secondary",
138
+ children: e.goalsFor
139
+ }),
140
+ /* @__PURE__ */ p("td", {
141
+ className: "px-3 py-2.5 text-center tabular-nums text-text-secondary",
142
+ children: e.goalsAgainst
143
+ }),
144
+ /* @__PURE__ */ p("td", {
145
+ className: "px-3 py-2.5 text-center tabular-nums text-text-secondary",
146
+ children: e.goalsFor - e.goalsAgainst
147
+ }),
148
+ /* @__PURE__ */ p("td", {
149
+ className: "px-3 py-2.5 text-center font-bold tabular-nums text-text-primary",
150
+ children: e.points
151
+ })
152
+ ]
153
+ }, e.id)) })]
154
+ })
155
+ }) : /* @__PURE__ */ p(t, {
156
+ illustration: "empty-data",
157
+ icon: /* @__PURE__ */ p(d, { className: "h-10 w-10" }),
158
+ title: "Pick a competition",
159
+ description: "Enter a competition name to see its live standings. Standings are computed from recorded fixture results on a 3-1-0 model."
160
+ })]
161
+ });
162
+ }
163
+ //#endregion
164
+ export { g as StandingsPage };
165
+
166
+ //# sourceMappingURL=StandingsPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StandingsPage.js","names":[],"sources":["../../../src/atheletebridge/pages/StandingsPage.tsx"],"sourcesContent":["/**\n * Standings\n * @module atheletebridge/pages\n *\n * Reads the live competition table (athStandings) for a chosen competition.\n * The svc requires a competition name, so the user picks one (seeded from\n * fixtures that carry a competition, or typed directly).\n */\n\nimport { useEffect, useMemo, useState } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { Search, Trophy } from 'lucide-react';\nimport { EmphasisPanel } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../components/PageLayout';\nimport { EmptyState } from '../components/EmptyState';\nimport { LoadingState, ErrorState } from '../components/LoadingState';\nimport { fieldInputClass } from '../components/form';\nimport { useFixtures, useStandings } from '../hooks/useAthleteBridgeApi';\n\nexport function StandingsPage() {\n const [searchParams] = useSearchParams();\n const initialCompetition = searchParams.get('competition') ?? '';\n\n const [competition, setCompetition] = useState(initialCompetition);\n const [activeCompetition, setActiveCompetition] = useState(initialCompetition);\n\n // Suggest competitions that appear on existing fixtures.\n const fixtures = useFixtures({ pagination: { limit: 100 } });\n const competitions = useMemo(() => {\n const set = new Set<string>();\n for (const f of fixtures.data?.items ?? []) {\n if (f.competition) set.add(f.competition);\n }\n return Array.from(set).sort();\n }, [fixtures.data]);\n\n // If no competition selected yet but fixtures have one, default to the first.\n useEffect(() => {\n if (!activeCompetition && competitions.length > 0) {\n setCompetition(competitions[0]);\n setActiveCompetition(competitions[0]);\n }\n }, [activeCompetition, competitions]);\n\n const standings = useStandings(activeCompetition || undefined);\n const rows = useMemo(() => {\n const items = standings.data ?? [];\n return [...items].sort((a, b) => {\n if (b.points !== a.points) return b.points - a.points;\n return b.goalsFor - a.goalsFor;\n });\n }, [standings.data]);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n setActiveCompetition(competition.trim());\n };\n\n return (\n <PageLayout\n title=\"Standings\"\n description=\"Live competition tables — recomputed automatically from results.\"\n >\n <form onSubmit={handleSubmit} className=\"mb-6 flex flex-wrap items-end gap-3\">\n <div className=\"flex-1 min-w-[220px]\">\n <label\n htmlFor=\"competition\"\n className=\"mb-1.5 block text-sm font-medium text-text-primary\"\n >\n Competition\n </label>\n <input\n id=\"competition\"\n list=\"ath-competitions\"\n className={fieldInputClass}\n value={competition}\n onChange={(e) => setCompetition(e.target.value)}\n placeholder=\"e.g. Spring League 2026\"\n />\n <datalist id=\"ath-competitions\">\n {competitions.map((c) => (\n <option key={c} value={c} />\n ))}\n </datalist>\n </div>\n <button\n type=\"submit\"\n className=\"inline-flex h-[38px] items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg/90\"\n >\n <Search className=\"h-4 w-4\" /> View table\n </button>\n </form>\n\n {!activeCompetition ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Trophy className=\"h-10 w-10\" />}\n title=\"Pick a competition\"\n description=\"Enter a competition name to see its live standings. Standings are computed from recorded fixture results on a 3-1-0 model.\"\n />\n ) : standings.isLoading ? (\n <LoadingState label=\"Loading standings…\" />\n ) : standings.isError ? (\n <ErrorState onRetry={() => void standings.refetch()} />\n ) : rows.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Trophy className=\"h-10 w-10\" />}\n title=\"No standings yet\"\n description={`No results have been recorded for \"${activeCompetition}\". Record a fixture result to build the table.`}\n />\n ) : (\n <EmphasisPanel className=\"overflow-x-auto\">\n <table className=\"w-full min-w-[640px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam text-left text-xs uppercase tracking-wide text-text-secondary\">\n <th className=\"px-3 py-2 font-medium\">#</th>\n <th className=\"px-3 py-2 font-medium\">Team</th>\n <th className=\"px-3 py-2 text-center font-medium\">P</th>\n <th className=\"px-3 py-2 text-center font-medium\">W</th>\n <th className=\"px-3 py-2 text-center font-medium\">D</th>\n <th className=\"px-3 py-2 text-center font-medium\">L</th>\n <th className=\"px-3 py-2 text-center font-medium\">GF</th>\n <th className=\"px-3 py-2 text-center font-medium\">GA</th>\n <th className=\"px-3 py-2 text-center font-medium\">GD</th>\n <th className=\"px-3 py-2 text-center font-semibold text-text-primary\">Pts</th>\n </tr>\n </thead>\n <tbody>\n {rows.map((row, idx) => (\n <tr\n key={row.id}\n className=\"border-b border-border-seam/60 last:border-0 hover:bg-bg-sunken/50\"\n >\n <td className=\"px-3 py-2.5 tabular-nums text-text-secondary\">\n {row.rank ?? idx + 1}\n </td>\n <td className=\"px-3 py-2.5 font-medium text-text-primary\">\n {row.team?.name ?? 'Unknown team'}\n </td>\n <td className=\"px-3 py-2.5 text-center tabular-nums text-text-secondary\">\n {row.played}\n </td>\n <td className=\"px-3 py-2.5 text-center tabular-nums text-text-secondary\">\n {row.won}\n </td>\n <td className=\"px-3 py-2.5 text-center tabular-nums text-text-secondary\">\n {row.drawn}\n </td>\n <td className=\"px-3 py-2.5 text-center tabular-nums text-text-secondary\">\n {row.lost}\n </td>\n <td className=\"px-3 py-2.5 text-center tabular-nums text-text-secondary\">\n {row.goalsFor}\n </td>\n <td className=\"px-3 py-2.5 text-center tabular-nums text-text-secondary\">\n {row.goalsAgainst}\n </td>\n <td className=\"px-3 py-2.5 text-center tabular-nums text-text-secondary\">\n {row.goalsFor - row.goalsAgainst}\n </td>\n <td className=\"px-3 py-2.5 text-center font-bold tabular-nums text-text-primary\">\n {row.points}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </EmphasisPanel>\n )}\n </PageLayout>\n );\n}\n"],"mappings":"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"}