@burdenoff/microfe-crewfoundry 2026.1013.2 → 2026.1029.2

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 (198) hide show
  1. package/dist/crewfoundry/CrewFoundryRoot.d.ts.map +1 -1
  2. package/dist/crewfoundry/CrewFoundryRoot.js +160 -256
  3. package/dist/crewfoundry/CrewFoundryRoot.js.map +1 -1
  4. package/dist/crewfoundry/CrewFoundryRoutes.d.ts.map +1 -1
  5. package/dist/crewfoundry/CrewFoundryRoutes.js +152 -192
  6. package/dist/crewfoundry/CrewFoundryRoutes.js.map +1 -1
  7. package/dist/crewfoundry/components/InlineError.d.ts +5 -0
  8. package/dist/crewfoundry/components/InlineError.d.ts.map +1 -0
  9. package/dist/crewfoundry/components/InlineError.js +17 -0
  10. package/dist/crewfoundry/components/InlineError.js.map +1 -0
  11. package/dist/crewfoundry/components/marketplace/BookServiceModal.d.ts +14 -0
  12. package/dist/crewfoundry/components/marketplace/BookServiceModal.d.ts.map +1 -0
  13. package/dist/crewfoundry/components/marketplace/BookServiceModal.js +75 -0
  14. package/dist/crewfoundry/components/marketplace/BookServiceModal.js.map +1 -0
  15. package/dist/crewfoundry/components/marketplace/MarketplaceTabs.d.ts +24 -0
  16. package/dist/crewfoundry/components/marketplace/MarketplaceTabs.d.ts.map +1 -0
  17. package/dist/crewfoundry/components/marketplace/MarketplaceTabs.js +47 -0
  18. package/dist/crewfoundry/components/marketplace/MarketplaceTabs.js.map +1 -0
  19. package/dist/crewfoundry/components/marketplace/ServiceListingModal.d.ts +12 -0
  20. package/dist/crewfoundry/components/marketplace/ServiceListingModal.d.ts.map +1 -0
  21. package/dist/crewfoundry/components/marketplace/ServiceListingModal.js +123 -0
  22. package/dist/crewfoundry/components/marketplace/ServiceListingModal.js.map +1 -0
  23. package/dist/crewfoundry/components/viz/CertificateCard.js +4 -118
  24. package/dist/crewfoundry/components/viz/PathSteps.js +3 -68
  25. package/dist/crewfoundry/components/viz/lib/geometry.js +5 -13
  26. package/dist/crewfoundry/components/viz/lib/geometry.js.map +1 -1
  27. package/dist/crewfoundry/lib/analytics.d.ts +1 -6
  28. package/dist/crewfoundry/lib/analytics.d.ts.map +1 -1
  29. package/dist/crewfoundry/lib/analytics.js +3 -18
  30. package/dist/crewfoundry/lib/analytics.js.map +1 -1
  31. package/dist/crewfoundry/lib/companyFinance.d.ts +3 -7
  32. package/dist/crewfoundry/lib/companyFinance.d.ts.map +1 -1
  33. package/dist/crewfoundry/lib/companyFinance.js +3 -8
  34. package/dist/crewfoundry/lib/companyFinance.js.map +1 -1
  35. package/dist/crewfoundry/lib/learning.d.ts +12 -0
  36. package/dist/crewfoundry/lib/learning.d.ts.map +1 -0
  37. package/dist/crewfoundry/lib/learning.js +26 -0
  38. package/dist/crewfoundry/lib/learning.js.map +1 -0
  39. package/dist/crewfoundry/lib/marketplace.d.ts +30 -0
  40. package/dist/crewfoundry/lib/marketplace.d.ts.map +1 -0
  41. package/dist/crewfoundry/lib/marketplace.js +91 -0
  42. package/dist/crewfoundry/lib/marketplace.js.map +1 -0
  43. package/dist/crewfoundry/lib/useEnsureLoaded.d.ts +7 -0
  44. package/dist/crewfoundry/lib/useEnsureLoaded.d.ts.map +1 -0
  45. package/dist/crewfoundry/lib/useEnsureLoaded.js +25 -0
  46. package/dist/crewfoundry/lib/useEnsureLoaded.js.map +1 -0
  47. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.d.ts.map +1 -1
  48. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +12 -25
  49. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
  50. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.d.ts.map +1 -1
  51. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +145 -157
  52. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
  53. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.d.ts.map +1 -1
  54. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +14 -14
  55. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
  56. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.d.ts.map +1 -1
  57. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +14 -14
  58. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
  59. package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.d.ts.map +1 -1
  60. package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js +71 -33
  61. package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js.map +1 -1
  62. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.d.ts.map +1 -1
  63. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +247 -173
  64. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
  65. package/dist/crewfoundry/pages/LearningCoursesPagePage.d.ts +12 -0
  66. package/dist/crewfoundry/pages/LearningCoursesPagePage.d.ts.map +1 -1
  67. package/dist/crewfoundry/pages/LearningCoursesPagePage.js +307 -293
  68. package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
  69. package/dist/crewfoundry/pages/LearningEnrollmentsPagePage.d.ts +2 -0
  70. package/dist/crewfoundry/pages/LearningEnrollmentsPagePage.d.ts.map +1 -0
  71. package/dist/crewfoundry/pages/LearningEnrollmentsPagePage.js +223 -0
  72. package/dist/crewfoundry/pages/LearningEnrollmentsPagePage.js.map +1 -0
  73. package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.d.ts +4 -0
  74. package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.d.ts.map +1 -1
  75. package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js +115 -160
  76. package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js.map +1 -1
  77. package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.d.ts.map +1 -1
  78. package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +165 -75
  79. package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
  80. package/dist/crewfoundry/pages/MarketplaceEscrowPagePage.d.ts +7 -0
  81. package/dist/crewfoundry/pages/MarketplaceEscrowPagePage.d.ts.map +1 -0
  82. package/dist/crewfoundry/pages/MarketplaceEscrowPagePage.js +175 -0
  83. package/dist/crewfoundry/pages/MarketplaceEscrowPagePage.js.map +1 -0
  84. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.d.ts.map +1 -1
  85. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +182 -223
  86. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
  87. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.d.ts.map +1 -1
  88. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +168 -227
  89. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
  90. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.d.ts.map +1 -1
  91. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +127 -290
  92. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
  93. package/dist/crewfoundry/store/crewfoundryStore.d.ts +138 -78
  94. package/dist/crewfoundry/store/crewfoundryStore.d.ts.map +1 -1
  95. package/dist/crewfoundry/store/crewfoundryStore.js +338 -244
  96. package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
  97. package/dist/crewfoundry/utils/dateUtils.d.ts +5 -0
  98. package/dist/crewfoundry/utils/dateUtils.d.ts.map +1 -1
  99. package/dist/crewfoundry/utils/dateUtils.js +10 -1
  100. package/dist/crewfoundry/utils/dateUtils.js.map +1 -1
  101. package/dist/generated/global-types.d.ts +5145 -1627
  102. package/dist/generated/global-types.d.ts.map +1 -1
  103. package/dist/generated/wspace-types.d.ts +100373 -34602
  104. package/dist/generated/wspace-types.d.ts.map +1 -1
  105. package/dist/utils/pageContext.d.ts.map +1 -1
  106. package/dist/utils/pageContext.js +0 -1
  107. package/dist/utils/pageContext.js.map +1 -1
  108. package/package.json +1 -1
  109. package/dist/crewfoundry/components/viz/CertificateCard.js.map +0 -1
  110. package/dist/crewfoundry/components/viz/PathSteps.js.map +0 -1
  111. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.d.ts +0 -2
  112. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.d.ts.map +0 -1
  113. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +0 -53
  114. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +0 -1
  115. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.d.ts +0 -2
  116. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.d.ts.map +0 -1
  117. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +0 -107
  118. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +0 -1
  119. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.d.ts +0 -2
  120. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.d.ts.map +0 -1
  121. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +0 -62
  122. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +0 -1
  123. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.d.ts +0 -2
  124. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.d.ts.map +0 -1
  125. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +0 -37
  126. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +0 -1
  127. package/dist/crewfoundry/pages/LearningCertificatesPagePage.d.ts +0 -2
  128. package/dist/crewfoundry/pages/LearningCertificatesPagePage.d.ts.map +0 -1
  129. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +0 -111
  130. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +0 -1
  131. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.d.ts +0 -2
  132. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.d.ts.map +0 -1
  133. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +0 -309
  134. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +0 -1
  135. package/dist/crewfoundry/pages/LearningLearningPagePage.d.ts +0 -2
  136. package/dist/crewfoundry/pages/LearningLearningPagePage.d.ts.map +0 -1
  137. package/dist/crewfoundry/pages/LearningLearningPagePage.js +0 -200
  138. package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +0 -1
  139. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.d.ts +0 -2
  140. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.d.ts.map +0 -1
  141. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +0 -190
  142. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +0 -1
  143. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.d.ts +0 -2
  144. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.d.ts.map +0 -1
  145. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +0 -230
  146. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +0 -1
  147. package/dist/crewfoundry/pages/LearningMyLearningPagePage.d.ts +0 -2
  148. package/dist/crewfoundry/pages/LearningMyLearningPagePage.d.ts.map +0 -1
  149. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +0 -293
  150. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +0 -1
  151. package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.d.ts +0 -2
  152. package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.d.ts.map +0 -1
  153. package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +0 -163
  154. package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +0 -1
  155. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.d.ts +0 -2
  156. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.d.ts.map +0 -1
  157. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +0 -365
  158. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +0 -1
  159. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.d.ts +0 -2
  160. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.d.ts.map +0 -1
  161. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +0 -224
  162. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +0 -1
  163. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.d.ts +0 -2
  164. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.d.ts.map +0 -1
  165. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +0 -180
  166. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +0 -1
  167. package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.d.ts +0 -2
  168. package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.d.ts.map +0 -1
  169. package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js +0 -38
  170. package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js.map +0 -1
  171. package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.d.ts +0 -2
  172. package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.d.ts.map +0 -1
  173. package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +0 -204
  174. package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +0 -1
  175. package/dist/crewfoundry/pages/PaymentsEscrowPagePage.d.ts +0 -2
  176. package/dist/crewfoundry/pages/PaymentsEscrowPagePage.d.ts.map +0 -1
  177. package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js +0 -55
  178. package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js.map +0 -1
  179. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.d.ts +0 -2
  180. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.d.ts.map +0 -1
  181. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +0 -335
  182. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +0 -1
  183. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.d.ts +0 -2
  184. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.d.ts.map +0 -1
  185. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +0 -160
  186. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +0 -1
  187. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.d.ts +0 -2
  188. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.d.ts.map +0 -1
  189. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js +0 -80
  190. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js.map +0 -1
  191. package/dist/crewfoundry/pages/PaymentsSecurityPagePage.d.ts +0 -2
  192. package/dist/crewfoundry/pages/PaymentsSecurityPagePage.d.ts.map +0 -1
  193. package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js +0 -191
  194. package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js.map +0 -1
  195. package/dist/crewfoundry/utils/courseProgress.d.ts +0 -33
  196. package/dist/crewfoundry/utils/courseProgress.d.ts.map +0 -1
  197. package/dist/crewfoundry/utils/courseProgress.js +0 -46
  198. package/dist/crewfoundry/utils/courseProgress.js.map +0 -1
@@ -1,184 +1,139 @@
1
1
  import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
- import { BookOpen as t, GraduationCap as n, Star as r, Users as i } from "lucide-react";
3
- import { jsx as a, jsxs as o } from "react/jsx-runtime";
4
- import { Badge as s, Card as c, CardContent as l, CardHeader as u, CardTitle as d, GlassCard as f, GradientText as p, IllustratedEmptyState as m, PagePurpose as h, Pagination as g, ResponsiveTable as _ } from "@burdenoff/fe-libs/ui";
5
- import { usePagination as v } from "@burdenoff/fe-libs/shared/hooks";
2
+ import { DonutChart as t } from "../components/viz/DonutChart.js";
3
+ import { StatCard as n } from "../components/viz/StatCard.js";
4
+ import { SkillBar as r } from "../components/viz/SkillBar.js";
5
+ import { SegmentedTabs as i } from "../components/viz/SegmentedTabs.js";
6
+ import "../components/viz/index.js";
7
+ import { InlineError as a } from "../components/InlineError.js";
8
+ import { ENROLLMENT_STATUS_LABEL as o } from "../lib/learning.js";
9
+ import { useEnsureLoaded as s } from "../lib/useEnsureLoaded.js";
10
+ import { LEARNING_TABS as c } from "./LearningCoursesPagePage.js";
11
+ import { useMemo as l } from "react";
12
+ import { useNavigate as u } from "react-router";
13
+ import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
14
+ import { Card as m, CardContent as h, CardDescription as g, CardHeader as _, CardTitle as v, GradientText as y, IllustratedEmptyState as b, PagePurpose as x, Spinner as S } from "@burdenoff/fe-libs/ui";
6
15
  //#region src/crewfoundry/pages/LearningLearningAnalyticsPagePage.tsx
7
- function y() {
8
- let { courses: y } = e(), { page: b, pageSize: x, offset: S, setPage: C } = v({ initialPageSize: 10 }), w = y.reduce((e, t) => e + t.enrolled, 0), T = y.reduce((e, t) => e + t.completed, 0), E = y.filter((e) => e.status === "active").length, D = (y.reduce((e, t) => e + t.rating, 0) / Math.max(y.length, 1)).toFixed(1), O = y.reduce((e, t) => (e[t.category] = (e[t.category] || 0) + t.enrolled, e), {}), k = Object.entries(O).sort(([, e], [, t]) => t - e), A = y.slice(S, S + x);
9
- return /* @__PURE__ */ o("div", {
16
+ function C() {
17
+ let C = u(), { trainingCompletion: w, learningLoaded: T, fetchLearning: E } = e(), D = s(T, E), O = l(() => w.reduce((e, t) => ({
18
+ enrolled: e.enrolled + t.totalEnrolled,
19
+ notStarted: e.notStarted + t.notStartedCount,
20
+ inProgress: e.inProgress + t.inProgressCount,
21
+ completed: e.completed + t.completedCount
22
+ }), {
23
+ enrolled: 0,
24
+ notStarted: 0,
25
+ inProgress: 0,
26
+ completed: 0
27
+ }), [w]), k = O.enrolled === 0 ? 0 : Math.round(O.completed / O.enrolled * 100), A = [...w].sort((e, t) => t.totalEnrolled - e.totalEnrolled);
28
+ return /* @__PURE__ */ p("div", {
10
29
  className: "space-y-6 p-6",
11
30
  children: [
12
- /* @__PURE__ */ o("div", { children: [
13
- /* @__PURE__ */ a("h1", {
31
+ /* @__PURE__ */ p("div", { children: [
32
+ /* @__PURE__ */ f("h1", {
14
33
  className: "text-2xl font-semibold",
15
- children: /* @__PURE__ */ a(p, { children: "Learning Analytics" })
34
+ children: /* @__PURE__ */ f(y, { children: "Training Completion" })
16
35
  }),
17
- /* @__PURE__ */ a("p", {
36
+ /* @__PURE__ */ p("p", {
18
37
  className: "text-sm text-text-secondary",
19
- children: "Training metrics and engagement insights"
38
+ children: [
39
+ "Completion across ",
40
+ w.length,
41
+ " active courses"
42
+ ]
20
43
  }),
21
- /* @__PURE__ */ a(h, {
44
+ /* @__PURE__ */ f(x, {
22
45
  className: "mt-1",
23
- children: "See how learning is landing across your organization — completion rates, popular courses, and skill growth to guide your L&D strategy."
46
+ children: "See which required training is getting done and where people are stuck, so you can follow up before a compliance or onboarding deadline slips."
24
47
  })
25
48
  ] }),
26
- /* @__PURE__ */ o("div", {
27
- className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
49
+ /* @__PURE__ */ f(i, {
50
+ "aria-label": "Learning sections",
51
+ variant: "underline",
52
+ value: "completion",
53
+ onChange: (e) => {
54
+ let t = c.find((t) => t.id === e);
55
+ t && e !== "completion" && C(t.path);
56
+ },
57
+ tabs: c.map(({ id: e, label: t }) => ({
58
+ id: e,
59
+ label: t
60
+ }))
61
+ }),
62
+ /* @__PURE__ */ f(a, { message: D }),
63
+ !T && !D ? /* @__PURE__ */ f("div", {
64
+ className: "flex min-h-[240px] items-center justify-center",
65
+ children: /* @__PURE__ */ f(S, { size: "lg" })
66
+ }) : /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ p("div", {
67
+ className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-4",
28
68
  children: [
29
- /* @__PURE__ */ o(f, {
30
- treatment: "glass",
31
- glow: !0,
32
- className: "border-border-seam",
33
- children: [/* @__PURE__ */ o(u, {
34
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
35
- children: [/* @__PURE__ */ a(d, {
36
- className: "text-sm font-medium",
37
- children: "Total Enrollments"
38
- }), /* @__PURE__ */ a(i, { className: "h-4 w-4 text-text-secondary" })]
39
- }), /* @__PURE__ */ a(l, { children: /* @__PURE__ */ a("div", {
40
- className: "text-2xl font-bold tabular-nums",
41
- children: w
42
- }) })]
69
+ /* @__PURE__ */ f(n, {
70
+ label: "Enrollments",
71
+ value: O.enrolled
43
72
  }),
44
- /* @__PURE__ */ o(f, {
45
- treatment: "metric",
46
- className: "border-border-seam",
47
- children: [/* @__PURE__ */ o(u, {
48
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
49
- children: [/* @__PURE__ */ a(d, {
50
- className: "text-sm font-medium",
51
- children: "Completions"
52
- }), /* @__PURE__ */ a(n, { className: "h-4 w-4 text-status-success-text" })]
53
- }), /* @__PURE__ */ o(l, { children: [/* @__PURE__ */ a("div", {
54
- className: "text-2xl font-bold tabular-nums",
55
- children: T
56
- }), /* @__PURE__ */ o("p", {
57
- className: "text-xs text-text-secondary",
58
- children: [w > 0 ? Math.round(T / w * 100) : 0, "% rate"]
59
- })] })]
73
+ /* @__PURE__ */ f(n, {
74
+ label: "In Progress",
75
+ value: O.inProgress
60
76
  }),
61
- /* @__PURE__ */ o(f, {
62
- treatment: "metric",
63
- className: "border-border-seam",
64
- children: [/* @__PURE__ */ o(u, {
65
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
66
- children: [/* @__PURE__ */ a(d, {
67
- className: "text-sm font-medium",
68
- children: "Avg Rating"
69
- }), /* @__PURE__ */ a(r, { className: "h-4 w-4 text-status-warning-text" })]
70
- }), /* @__PURE__ */ a(l, { children: /* @__PURE__ */ o("div", {
71
- className: "text-2xl font-bold tabular-nums",
72
- children: [D, "/5"]
73
- }) })]
77
+ /* @__PURE__ */ f(n, {
78
+ label: "Completed",
79
+ value: O.completed
74
80
  }),
75
- /* @__PURE__ */ o(f, {
76
- treatment: "metric",
77
- className: "border-border-seam",
78
- children: [/* @__PURE__ */ o(u, {
79
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
80
- children: [/* @__PURE__ */ a(d, {
81
- className: "text-sm font-medium",
82
- children: "Active Courses"
83
- }), /* @__PURE__ */ a(t, { className: "h-4 w-4 text-text-secondary" })]
84
- }), /* @__PURE__ */ o(l, { children: [/* @__PURE__ */ a("div", {
85
- className: "text-2xl font-bold tabular-nums",
86
- children: E
87
- }), /* @__PURE__ */ o("p", {
88
- className: "text-xs text-text-secondary",
89
- children: [
90
- "of ",
91
- y.length,
92
- " total"
93
- ]
94
- })] })]
81
+ /* @__PURE__ */ f(n, {
82
+ label: "Completion Rate",
83
+ value: `${k}%`
95
84
  })
96
85
  ]
97
- }),
98
- /* @__PURE__ */ o("div", {
99
- className: "grid gap-4 md:grid-cols-2",
100
- children: [/* @__PURE__ */ o(c, { children: [/* @__PURE__ */ a(u, { children: /* @__PURE__ */ a(d, { children: "Category Distribution" }) }), /* @__PURE__ */ a(l, {
101
- className: "space-y-3",
102
- children: k.length === 0 ? /* @__PURE__ */ a("p", {
103
- className: "text-sm text-text-secondary",
104
- children: "No enrollment data yet."
105
- }) : k.map(([e, t]) => /* @__PURE__ */ o("div", {
106
- className: "flex items-center justify-between",
107
- children: [/* @__PURE__ */ a("span", {
108
- className: "text-sm",
109
- children: e
110
- }), /* @__PURE__ */ o("div", {
111
- className: "flex items-center gap-2",
112
- children: [/* @__PURE__ */ a("span", {
113
- className: "text-sm font-medium",
114
- children: t
115
- }), /* @__PURE__ */ o(s, {
116
- variant: "outline",
117
- className: "text-[10px]",
118
- children: [w > 0 ? Math.round(t / w * 100) : 0, "%"]
119
- })]
120
- })]
121
- }, e))
122
- })] }), /* @__PURE__ */ o(c, { children: [/* @__PURE__ */ a(u, { children: /* @__PURE__ */ a(d, { children: "Course Performance" }) }), /* @__PURE__ */ o(l, {
123
- className: "space-y-3",
124
- children: [/* @__PURE__ */ a(_, {
125
- columns: [
126
- {
127
- key: "title",
128
- header: "Course",
129
- priority: "primary",
130
- cell: (e) => /* @__PURE__ */ a("span", {
131
- className: "font-medium",
132
- children: e.title
133
- })
134
- },
135
- {
136
- key: "enrolled",
137
- header: "Enrolled",
138
- priority: "secondary",
139
- headerClassName: "text-right",
140
- cellClassName: "md:text-right",
141
- cell: (e) => e.enrolled
142
- },
143
- {
144
- key: "completed",
145
- header: "Completed",
146
- priority: "secondary",
147
- headerClassName: "text-right",
148
- cellClassName: "md:text-right",
149
- cell: (e) => e.completed
150
- },
151
- {
152
- key: "rating",
153
- header: "Rating",
154
- priority: "secondary",
155
- headerClassName: "text-right",
156
- cellClassName: "md:text-right",
157
- cell: (e) => /* @__PURE__ */ o("span", {
158
- className: "inline-flex items-center gap-1 md:justify-end",
159
- children: [/* @__PURE__ */ a(r, { className: "h-3 w-3 text-status-warning-text" }), e.rating]
160
- })
161
- }
162
- ],
163
- data: A,
164
- rowKey: (e) => e.id,
165
- emptyState: /* @__PURE__ */ a(m, {
166
- illustration: "empty-generic",
167
- title: "No courses yet",
168
- description: "Course performance will appear here once courses are added."
169
- })
170
- }), y.length > x && /* @__PURE__ */ a(g, {
171
- page: b,
172
- pageSize: x,
173
- totalItems: y.length,
174
- onPageChange: C
86
+ }), O.enrolled === 0 ? /* @__PURE__ */ f(b, {
87
+ illustration: "empty-data",
88
+ title: "No training activity yet",
89
+ description: "Completion appears here once employees are enrolled in active courses."
90
+ }) : /* @__PURE__ */ p("div", {
91
+ className: "grid gap-6 lg:grid-cols-3",
92
+ children: [/* @__PURE__ */ p(m, { children: [/* @__PURE__ */ p(_, { children: [/* @__PURE__ */ f(v, {
93
+ className: "text-base",
94
+ children: "Status mix"
95
+ }), /* @__PURE__ */ f(g, { children: "Every enrollment in an active course" })] }), /* @__PURE__ */ f(h, { children: /* @__PURE__ */ f(t, {
96
+ segments: [
97
+ {
98
+ label: o.not_started,
99
+ value: O.notStarted
100
+ },
101
+ {
102
+ label: o.in_progress,
103
+ value: O.inProgress
104
+ },
105
+ {
106
+ label: o.completed,
107
+ value: O.completed
108
+ }
109
+ ],
110
+ centerLabel: `${k}%`,
111
+ centerCaption: "completed",
112
+ showLegend: !0
113
+ }) })] }), /* @__PURE__ */ p(m, {
114
+ className: "lg:col-span-2",
115
+ children: [/* @__PURE__ */ p(_, { children: [/* @__PURE__ */ f(v, {
116
+ className: "text-base",
117
+ children: "By course"
118
+ }), /* @__PURE__ */ f(g, { children: "Share of enrolled employees who completed it" })] }), /* @__PURE__ */ f(h, {
119
+ className: "space-y-4",
120
+ children: A.map((e) => /* @__PURE__ */ f("button", {
121
+ type: "button",
122
+ className: "block w-full text-left",
123
+ onClick: () => C(`../learning/course-details-page?id=${encodeURIComponent(e.courseId)}`),
124
+ children: /* @__PURE__ */ f(r, {
125
+ label: e.courseTitle,
126
+ value: e.completionRate,
127
+ levelLabel: `${e.completedCount}/${e.totalEnrolled} · ${Math.round(e.completionRate)}%`
128
+ })
129
+ }, e.courseId))
175
130
  })]
176
- })] })]
177
- })
131
+ })]
132
+ })] })
178
133
  ]
179
134
  });
180
135
  }
181
136
  //#endregion
182
- export { y as LearningLearningAnalyticsPagePage };
137
+ export { C as LearningLearningAnalyticsPagePage };
183
138
 
184
139
  //# sourceMappingURL=LearningLearningAnalyticsPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LearningLearningAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/LearningLearningAnalyticsPagePage.tsx"],"sourcesContent":["import { BookOpen, GraduationCap, Star, Users } from 'lucide-react';\nimport {\n Badge,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n Pagination,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\nimport { useCrewFoundryStore, type LearningCourse } from '../store/crewfoundryStore';\n\nexport function LearningLearningAnalyticsPagePage() {\n const { courses } = useCrewFoundryStore();\n const { page, pageSize, offset, setPage } = usePagination({ initialPageSize: 10 });\n\n const totalEnrolled = courses.reduce((sum, course) => sum + course.enrolled, 0);\n const totalCompleted = courses.reduce((sum, course) => sum + course.completed, 0);\n const activeCourses = courses.filter((course) => course.status === 'active').length;\n const avgRating = (\n courses.reduce((sum, course) => sum + course.rating, 0) / Math.max(courses.length, 1)\n ).toFixed(1);\n\n const categoryDistribution = courses.reduce<Record<string, number>>((acc, course) => {\n acc[course.category] = (acc[course.category] || 0) + course.enrolled;\n return acc;\n }, {});\n const sortedCategories = Object.entries(categoryDistribution).sort(([, a], [, b]) => b - a);\n\n const pagedCourses = courses.slice(offset, offset + pageSize);\n\n const columns: ResponsiveTableColumn<LearningCourse>[] = [\n {\n key: 'title',\n header: 'Course',\n priority: 'primary',\n cell: (course) => <span className=\"font-medium\">{course.title}</span>,\n },\n {\n key: 'enrolled',\n header: 'Enrolled',\n priority: 'secondary',\n headerClassName: 'text-right',\n cellClassName: 'md:text-right',\n cell: (course) => course.enrolled,\n },\n {\n key: 'completed',\n header: 'Completed',\n priority: 'secondary',\n headerClassName: 'text-right',\n cellClassName: 'md:text-right',\n cell: (course) => course.completed,\n },\n {\n key: 'rating',\n header: 'Rating',\n priority: 'secondary',\n headerClassName: 'text-right',\n cellClassName: 'md:text-right',\n cell: (course) => (\n <span className=\"inline-flex items-center gap-1 md:justify-end\">\n <Star className=\"h-3 w-3 text-status-warning-text\" />\n {course.rating}\n </span>\n ),\n },\n ];\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Learning Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Training metrics and engagement insights</p>\n <PagePurpose className=\"mt-1\">\n See how learning is landing across your organization — completion rates, popular courses,\n and skill growth to guide your L&amp;D strategy.\n </PagePurpose>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Enrollments</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{totalEnrolled}</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Completions</CardTitle>\n <GraduationCap className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{totalCompleted}</div>\n <p className=\"text-xs text-text-secondary\">\n {totalEnrolled > 0 ? Math.round((totalCompleted / totalEnrolled) * 100) : 0}% rate\n </p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Avg Rating</CardTitle>\n <Star className=\"h-4 w-4 text-status-warning-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{avgRating}/5</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Active Courses</CardTitle>\n <BookOpen className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activeCourses}</div>\n <p className=\"text-xs text-text-secondary\">of {courses.length} total</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle>Category Distribution</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {sortedCategories.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">No enrollment data yet.</p>\n ) : (\n sortedCategories.map(([category, count]) => (\n <div key={category} className=\"flex items-center justify-between\">\n <span className=\"text-sm\">{category}</span>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium\">{count}</span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {totalEnrolled > 0 ? Math.round((count / totalEnrolled) * 100) : 0}%\n </Badge>\n </div>\n </div>\n ))\n )}\n </CardContent>\n </Card>\n <Card>\n <CardHeader>\n <CardTitle>Course Performance</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n <ResponsiveTable\n columns={columns}\n data={pagedCourses}\n rowKey={(course) => course.id}\n emptyState={\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No courses yet\"\n description=\"Course performance will appear here once courses are added.\"\n />\n }\n />\n {courses.length > pageSize && (\n <Pagination\n page={page}\n pageSize={pageSize}\n totalItems={courses.length}\n onPageChange={setPage}\n />\n )}\n </CardContent>\n </Card>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"LearningLearningAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/LearningLearningAnalyticsPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport {\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n Spinner,\n} from '@burdenoff/fe-libs/ui';\nimport { useNavigate } from 'react-router';\nimport { InlineError } from '../components/InlineError';\nimport { DonutChart, SegmentedTabs, SkillBar, StatCard } from '../components/viz';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\nimport { ENROLLMENT_STATUS_LABEL } from '../lib/learning';\nimport { useEnsureLoaded } from '../lib/useEnsureLoaded';\nimport { LEARNING_TABS } from './LearningCoursesPagePage';\n\n/**\n * Manager completion dashboard, read straight from\n * `crewTrainingCompletionDashboard` (active courses only).\n */\nexport function LearningLearningAnalyticsPagePage() {\n const navigate = useNavigate();\n const { trainingCompletion, learningLoaded, fetchLearning } = useCrewFoundryStore();\n const loadError = useEnsureLoaded(learningLoaded, fetchLearning);\n\n const totals = useMemo(\n () =>\n trainingCompletion.reduce(\n (acc, row) => ({\n enrolled: acc.enrolled + row.totalEnrolled,\n notStarted: acc.notStarted + row.notStartedCount,\n inProgress: acc.inProgress + row.inProgressCount,\n completed: acc.completed + row.completedCount,\n }),\n { enrolled: 0, notStarted: 0, inProgress: 0, completed: 0 }\n ),\n [trainingCompletion]\n );\n const overallRate =\n totals.enrolled === 0 ? 0 : Math.round((totals.completed / totals.enrolled) * 100);\n const ranked = [...trainingCompletion].sort((a, b) => b.totalEnrolled - a.totalEnrolled);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Training Completion</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Completion across {trainingCompletion.length} active courses\n </p>\n <PagePurpose className=\"mt-1\">\n See which required training is getting done and where people are stuck, so you can follow\n up before a compliance or onboarding deadline slips.\n </PagePurpose>\n </div>\n\n <SegmentedTabs\n aria-label=\"Learning sections\"\n variant=\"underline\"\n value=\"completion\"\n onChange={(id) => {\n const tab = LEARNING_TABS.find((item) => item.id === id);\n if (tab && id !== 'completion') navigate(tab.path);\n }}\n tabs={LEARNING_TABS.map(({ id, label }) => ({ id, label }))}\n />\n\n <InlineError message={loadError} />\n\n {!learningLoaded && !loadError ? (\n <div className=\"flex min-h-[240px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : (\n <>\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n <StatCard label=\"Enrollments\" value={totals.enrolled} />\n <StatCard label=\"In Progress\" value={totals.inProgress} />\n <StatCard label=\"Completed\" value={totals.completed} />\n <StatCard label=\"Completion Rate\" value={`${overallRate}%`} />\n </div>\n\n {totals.enrolled === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No training activity yet\"\n description=\"Completion appears here once employees are enrolled in active courses.\"\n />\n ) : (\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Status mix</CardTitle>\n <CardDescription>Every enrollment in an active course</CardDescription>\n </CardHeader>\n <CardContent>\n <DonutChart\n segments={[\n { label: ENROLLMENT_STATUS_LABEL.not_started, value: totals.notStarted },\n { label: ENROLLMENT_STATUS_LABEL.in_progress, value: totals.inProgress },\n { label: ENROLLMENT_STATUS_LABEL.completed, value: totals.completed },\n ]}\n centerLabel={`${overallRate}%`}\n centerCaption=\"completed\"\n showLegend\n />\n </CardContent>\n </Card>\n <Card className=\"lg:col-span-2\">\n <CardHeader>\n <CardTitle className=\"text-base\">By course</CardTitle>\n <CardDescription>Share of enrolled employees who completed it</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {ranked.map((row) => (\n <button\n key={row.courseId}\n type=\"button\"\n className=\"block w-full text-left\"\n onClick={() =>\n navigate(\n `../learning/course-details-page?id=${encodeURIComponent(row.courseId)}`\n )\n }\n >\n <SkillBar\n label={row.courseTitle}\n value={row.completionRate}\n levelLabel={`${row.completedCount}/${row.totalEnrolled} · ${Math.round(row.completionRate)}%`}\n />\n </button>\n ))}\n </CardContent>\n </Card>\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"MarketplaceBookingManagementPagePage.d.ts","sourceRoot":"","sources":["../../../src/crewfoundry/pages/MarketplaceBookingManagementPagePage.tsx"],"names":[],"mappings":"AAaA,wBAAgB,oCAAoC,gCA0EnD"}
1
+ {"version":3,"file":"MarketplaceBookingManagementPagePage.d.ts","sourceRoot":"","sources":["../../../src/crewfoundry/pages/MarketplaceBookingManagementPagePage.tsx"],"names":[],"mappings":"AAwCA,wBAAgB,oCAAoC,gCA+KnD"}
@@ -1,90 +1,180 @@
1
- import { Calendar as e, CheckCircle as t, Clock as n, Plus as r } from "lucide-react";
2
- import { jsx as i, jsxs as a } from "react/jsx-runtime";
3
- import { Button as o, Card as s, CardContent as c, CardHeader as l, CardTitle as u, GlassCard as d, GradientText as f, IllustratedEmptyState as p, PagePurpose as m } from "@burdenoff/fe-libs/ui";
1
+ import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
+ import { StatCard as t } from "../components/viz/StatCard.js";
3
+ import { SegmentedTabs as n } from "../components/viz/SegmentedTabs.js";
4
+ import "../components/viz/index.js";
5
+ import { formatDate as r } from "../utils/dateUtils.js";
6
+ import { InlineError as i } from "../components/InlineError.js";
7
+ import { useEnsureLoaded as a } from "../lib/useEnsureLoaded.js";
8
+ import { MarketplaceTabs as o } from "../components/marketplace/MarketplaceTabs.js";
9
+ import { BOOKING_ACTION_LABEL as s, BOOKING_STATUS_LABEL as c, allowedBookingTransitions as l, formatRate as u } from "../lib/marketplace.js";
10
+ import { useState as d } from "react";
11
+ import { useNavigate as f } from "react-router";
12
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
13
+ import { Badge as h, Button as g, Card as _, CardContent as v, GradientText as y, IllustratedEmptyState as b, PagePurpose as x, ResponsiveTable as S, Spinner as C } from "@burdenoff/fe-libs/ui";
4
14
  //#region src/crewfoundry/pages/MarketplaceBookingManagementPagePage.tsx
5
- function h() {
6
- return /* @__PURE__ */ a("div", {
15
+ var w = {
16
+ requested: "outline",
17
+ confirmed: "default",
18
+ completed: "secondary",
19
+ cancelled: "secondary"
20
+ };
21
+ function T() {
22
+ let T = f(), { bookings: E, marketplaceLoaded: D, fetchMarketplace: O, updateBookingStatus: k, initParams: A } = e(), j = a(D, O), [M, N] = d("provider"), [P, F] = d(null), [I, L] = d(null), R = A.actorId, z = E.filter((e) => e.providerActorId === R), B = E.filter((e) => e.clientActorId === R), V = M === "provider" ? z : B, H = (e, t) => e.filter((e) => e.status === t).length, U = async (e, t) => {
23
+ F(null), L(e.id);
24
+ try {
25
+ await k(e.id, t);
26
+ } catch (e) {
27
+ F(e instanceof Error ? e.message : "Unable to update booking");
28
+ } finally {
29
+ L(null);
30
+ }
31
+ }, W = [
32
+ {
33
+ key: "service",
34
+ header: "Service",
35
+ priority: "primary",
36
+ cell: (e) => /* @__PURE__ */ p("button", {
37
+ type: "button",
38
+ className: "text-left font-medium hover:underline",
39
+ onClick: () => T(`../marketplace/service-details-page?id=${encodeURIComponent(e.listingId)}`),
40
+ children: e.listingTitle
41
+ })
42
+ },
43
+ {
44
+ key: "party",
45
+ header: M === "provider" ? "Booked by" : "Provider",
46
+ cell: (e) => /* @__PURE__ */ p("span", { children: M === "provider" ? e.clientName : e.providerName })
47
+ },
48
+ {
49
+ key: "when",
50
+ header: "Scheduled",
51
+ cell: (e) => /* @__PURE__ */ p("span", {
52
+ className: "text-text-secondary",
53
+ children: e.scheduledStart ? `${r(e.scheduledStart)}${e.scheduledEnd ? ` – ${r(e.scheduledEnd)}` : ""}` : "Not scheduled"
54
+ })
55
+ },
56
+ {
57
+ key: "rate",
58
+ header: "Agreed rate",
59
+ cell: (e) => /* @__PURE__ */ p("span", {
60
+ className: "tabular-nums",
61
+ children: u(e)
62
+ })
63
+ },
64
+ {
65
+ key: "status",
66
+ header: "Status",
67
+ cell: (e) => /* @__PURE__ */ p(h, {
68
+ variant: w[e.status],
69
+ className: "text-[10px]",
70
+ children: c[e.status]
71
+ })
72
+ },
73
+ {
74
+ key: "actions",
75
+ header: "",
76
+ cellClassName: "md:text-right",
77
+ cell: (e) => {
78
+ let t = l(e, R);
79
+ return t.length === 0 ? /* @__PURE__ */ p("span", {
80
+ className: "text-xs text-text-muted",
81
+ children: "—"
82
+ }) : /* @__PURE__ */ p("div", {
83
+ className: "flex flex-wrap justify-end gap-1",
84
+ children: t.map((t) => /* @__PURE__ */ p(g, {
85
+ size: "sm",
86
+ variant: t === "cancelled" ? "ghost" : "outline",
87
+ disabled: I === e.id,
88
+ onClick: () => void U(e, t),
89
+ children: s[t]
90
+ }, t))
91
+ });
92
+ }
93
+ }
94
+ ];
95
+ return /* @__PURE__ */ m("div", {
7
96
  className: "space-y-6 p-6",
8
97
  children: [
9
- /* @__PURE__ */ a("div", {
10
- className: "flex items-center justify-between",
11
- children: [/* @__PURE__ */ a("div", { children: [
12
- /* @__PURE__ */ i("h1", {
13
- className: "text-2xl font-semibold",
14
- children: /* @__PURE__ */ i(f, { children: "Booking Management" })
15
- }),
16
- /* @__PURE__ */ i("p", {
17
- className: "text-sm text-text-secondary",
18
- children: "Manage service provider appointments"
19
- }),
20
- /* @__PURE__ */ i(m, {
21
- className: "mt-1",
22
- children: "Manage your service bookings — review upcoming engagements, confirm schedules, and keep your client commitments on track."
23
- })
24
- ] }), /* @__PURE__ */ a(o, {
25
- size: "sm",
26
- disabled: !0,
27
- title: "Booking creation is coming soon",
28
- children: [/* @__PURE__ */ i(r, { className: "mr-1 h-4 w-4" }), "New Booking · Coming soon"]
29
- })]
30
- }),
31
- /* @__PURE__ */ a("div", {
32
- className: "grid gap-4 md:grid-cols-3",
98
+ /* @__PURE__ */ m("div", { children: [
99
+ /* @__PURE__ */ p("h1", {
100
+ className: "text-2xl font-semibold",
101
+ children: /* @__PURE__ */ p(y, { children: "Bookings" })
102
+ }),
103
+ /* @__PURE__ */ m("p", {
104
+ className: "text-sm text-text-secondary",
105
+ children: [
106
+ z.length,
107
+ " for your services · ",
108
+ B.length,
109
+ " you made"
110
+ ]
111
+ }),
112
+ /* @__PURE__ */ p(x, {
113
+ className: "mt-1",
114
+ children: "Confirm requests for your services, mark work completed, and keep track of the services you have booked from others."
115
+ })
116
+ ] }),
117
+ /* @__PURE__ */ p(o, { value: "bookings" }),
118
+ /* @__PURE__ */ p(i, { message: j ?? P }),
119
+ /* @__PURE__ */ m("div", {
120
+ className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-4",
33
121
  children: [
34
- /* @__PURE__ */ a(d, {
35
- treatment: "glass",
36
- glow: !0,
37
- className: "border-border-seam",
38
- children: [/* @__PURE__ */ a(l, {
39
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
40
- children: [/* @__PURE__ */ i(u, {
41
- className: "text-sm font-medium",
42
- children: "Upcoming"
43
- }), /* @__PURE__ */ i(e, { className: "h-4 w-4 text-status-info-text" })]
44
- }), /* @__PURE__ */ i(c, { children: /* @__PURE__ */ i("div", {
45
- className: "text-2xl font-bold tabular-nums",
46
- children: 0
47
- }) })]
122
+ /* @__PURE__ */ p(t, {
123
+ label: "Requested",
124
+ value: H(V, "requested")
125
+ }),
126
+ /* @__PURE__ */ p(t, {
127
+ label: "Confirmed",
128
+ value: H(V, "confirmed")
48
129
  }),
49
- /* @__PURE__ */ a(d, {
50
- treatment: "metric",
51
- className: "border-border-seam",
52
- children: [/* @__PURE__ */ a(l, {
53
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
54
- children: [/* @__PURE__ */ i(u, {
55
- className: "text-sm font-medium",
56
- children: "Confirmed"
57
- }), /* @__PURE__ */ i(t, { className: "h-4 w-4 text-status-success-text" })]
58
- }), /* @__PURE__ */ i(c, { children: /* @__PURE__ */ i("div", {
59
- className: "text-2xl font-bold tabular-nums",
60
- children: 0
61
- }) })]
130
+ /* @__PURE__ */ p(t, {
131
+ label: "Completed",
132
+ value: H(V, "completed")
62
133
  }),
63
- /* @__PURE__ */ a(d, {
64
- treatment: "metric",
65
- className: "border-border-seam",
66
- children: [/* @__PURE__ */ a(l, {
67
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
68
- children: [/* @__PURE__ */ i(u, {
69
- className: "text-sm font-medium",
70
- children: "Pending"
71
- }), /* @__PURE__ */ i(n, { className: "h-4 w-4 text-status-warning-text" })]
72
- }), /* @__PURE__ */ i(c, { children: /* @__PURE__ */ i("div", {
73
- className: "text-2xl font-bold tabular-nums",
74
- children: 0
75
- }) })]
134
+ /* @__PURE__ */ p(t, {
135
+ label: "Cancelled",
136
+ value: H(V, "cancelled")
76
137
  })
77
138
  ]
78
139
  }),
79
- /* @__PURE__ */ a(s, { children: [/* @__PURE__ */ i(l, { children: /* @__PURE__ */ i(u, { children: "All Bookings" }) }), /* @__PURE__ */ i(c, { children: /* @__PURE__ */ i(p, {
80
- illustration: "empty-generic",
81
- title: "No bookings yet",
82
- description: "Once booking creation ships, your scheduled service appointments will appear here."
83
- }) })] })
140
+ /* @__PURE__ */ p(n, {
141
+ "aria-label": "Booking perspective",
142
+ value: M,
143
+ onChange: (e) => N(e),
144
+ tabs: [{
145
+ id: "provider",
146
+ label: "Requests for my services",
147
+ count: z.length
148
+ }, {
149
+ id: "client",
150
+ label: "My bookings",
151
+ count: B.length
152
+ }]
153
+ }),
154
+ !D && !j ? /* @__PURE__ */ p("div", {
155
+ className: "flex min-h-[240px] items-center justify-center",
156
+ children: /* @__PURE__ */ p(C, { size: "lg" })
157
+ }) : V.length === 0 ? /* @__PURE__ */ p(b, {
158
+ illustration: "empty-data",
159
+ title: M === "provider" ? "No booking requests yet" : "You haven't booked anything",
160
+ description: M === "provider" ? "Requests appear here when a colleague books one of your services." : "Browse the marketplace to book a colleague or contractor.",
161
+ action: /* @__PURE__ */ p(g, {
162
+ size: "sm",
163
+ onClick: () => T("../marketplace/marketplace-page"),
164
+ children: "Browse the marketplace"
165
+ })
166
+ }) : /* @__PURE__ */ p(_, { children: /* @__PURE__ */ p(v, {
167
+ className: "pt-6",
168
+ children: /* @__PURE__ */ p(S, {
169
+ data: V,
170
+ rowKey: (e) => e.id,
171
+ columns: W
172
+ })
173
+ }) })
84
174
  ]
85
175
  });
86
176
  }
87
177
  //#endregion
88
- export { h as MarketplaceBookingManagementPagePage };
178
+ export { T as MarketplaceBookingManagementPagePage };
89
179
 
90
180
  //# sourceMappingURL=MarketplaceBookingManagementPagePage.js.map