@burdenoff/microfe-crewfoundry 2026.704.6 → 2026.707.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 (150) hide show
  1. package/dist/crewfoundry/CrewFoundryRoutes.js +51 -43
  2. package/dist/crewfoundry/CrewFoundryRoutes.js.map +1 -1
  3. package/dist/crewfoundry/components/forms/formValues.js +5 -2
  4. package/dist/crewfoundry/components/forms/formValues.js.map +1 -1
  5. package/dist/crewfoundry/components/viz/AllocationBar.js +68 -0
  6. package/dist/crewfoundry/components/viz/AllocationBar.js.map +1 -0
  7. package/dist/crewfoundry/components/viz/AreaChart.js +102 -0
  8. package/dist/crewfoundry/components/viz/AreaChart.js.map +1 -0
  9. package/dist/crewfoundry/components/viz/AvatarStack.js +36 -0
  10. package/dist/crewfoundry/components/viz/AvatarStack.js.map +1 -0
  11. package/dist/crewfoundry/components/viz/BarChart.js +83 -0
  12. package/dist/crewfoundry/components/viz/BarChart.js.map +1 -0
  13. package/dist/crewfoundry/components/viz/CertificateCard.js +118 -0
  14. package/dist/crewfoundry/components/viz/CertificateCard.js.map +1 -0
  15. package/dist/crewfoundry/components/viz/DonutChart.js +109 -0
  16. package/dist/crewfoundry/components/viz/DonutChart.js.map +1 -0
  17. package/dist/crewfoundry/components/viz/HBarFunnel.js +54 -0
  18. package/dist/crewfoundry/components/viz/HBarFunnel.js.map +1 -0
  19. package/dist/crewfoundry/components/viz/Heatmap.js +91 -0
  20. package/dist/crewfoundry/components/viz/Heatmap.js.map +1 -0
  21. package/dist/crewfoundry/components/viz/KanbanBoard.js +50 -0
  22. package/dist/crewfoundry/components/viz/KanbanBoard.js.map +1 -0
  23. package/dist/crewfoundry/components/viz/LineChart.js +123 -0
  24. package/dist/crewfoundry/components/viz/LineChart.js.map +1 -0
  25. package/dist/crewfoundry/components/viz/OrgTree.js +83 -0
  26. package/dist/crewfoundry/components/viz/OrgTree.js.map +1 -0
  27. package/dist/crewfoundry/components/viz/PathSteps.js +68 -0
  28. package/dist/crewfoundry/components/viz/PathSteps.js.map +1 -0
  29. package/dist/crewfoundry/components/viz/ProgressRing.js +68 -0
  30. package/dist/crewfoundry/components/viz/ProgressRing.js.map +1 -0
  31. package/dist/crewfoundry/components/viz/RatingStars.js +51 -0
  32. package/dist/crewfoundry/components/viz/RatingStars.js.map +1 -0
  33. package/dist/crewfoundry/components/viz/SegmentedTabs.js +69 -0
  34. package/dist/crewfoundry/components/viz/SegmentedTabs.js.map +1 -0
  35. package/dist/crewfoundry/components/viz/SkillBar.js +3 -0
  36. package/dist/crewfoundry/components/viz/Sparkline.js +74 -0
  37. package/dist/crewfoundry/components/viz/Sparkline.js.map +1 -0
  38. package/dist/crewfoundry/components/viz/StatCard.js +60 -0
  39. package/dist/crewfoundry/components/viz/StatCard.js.map +1 -0
  40. package/dist/crewfoundry/components/viz/StepProgress.js +3 -0
  41. package/dist/crewfoundry/components/viz/Timeline.js +66 -0
  42. package/dist/crewfoundry/components/viz/Timeline.js.map +1 -0
  43. package/dist/crewfoundry/components/viz/index.js +23 -0
  44. package/dist/crewfoundry/components/viz/lib/Avatar.js +30 -0
  45. package/dist/crewfoundry/components/viz/lib/Avatar.js.map +1 -0
  46. package/dist/crewfoundry/components/viz/lib/CartesianFrame.js +119 -0
  47. package/dist/crewfoundry/components/viz/lib/CartesianFrame.js.map +1 -0
  48. package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js +35 -0
  49. package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js.map +1 -0
  50. package/dist/crewfoundry/components/viz/lib/format.js +21 -0
  51. package/dist/crewfoundry/components/viz/lib/format.js.map +1 -0
  52. package/dist/crewfoundry/components/viz/lib/geometry.js +69 -0
  53. package/dist/crewfoundry/components/viz/lib/geometry.js.map +1 -0
  54. package/dist/crewfoundry/components/viz/lib/hooks.js +39 -0
  55. package/dist/crewfoundry/components/viz/lib/hooks.js.map +1 -0
  56. package/dist/crewfoundry/components/viz/lib/palette.js +27 -0
  57. package/dist/crewfoundry/components/viz/lib/palette.js.map +1 -0
  58. package/dist/crewfoundry/lib/analytics.js +323 -0
  59. package/dist/crewfoundry/lib/analytics.js.map +1 -0
  60. package/dist/crewfoundry/lib/companyFinance.js +16 -0
  61. package/dist/crewfoundry/lib/companyFinance.js.map +1 -0
  62. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +226 -283
  63. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  64. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +107 -120
  65. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
  66. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +122 -162
  67. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
  68. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +121 -158
  69. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
  70. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +316 -211
  71. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
  72. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +75 -27
  73. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
  74. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +167 -165
  75. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
  76. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +168 -109
  77. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
  78. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +401 -290
  79. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
  80. package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js +0 -41
  81. package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js.map +1 -1
  82. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +84 -75
  83. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
  84. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +368 -174
  85. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
  86. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +236 -201
  87. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
  88. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +369 -196
  89. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
  90. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +269 -270
  91. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
  92. package/dist/crewfoundry/pages/HiringJobsPagePage.js +210 -110
  93. package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
  94. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +216 -178
  95. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
  96. package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js +385 -0
  97. package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js.map +1 -0
  98. package/dist/crewfoundry/pages/HrEmployeesPagePage.js +189 -130
  99. package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
  100. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +397 -241
  101. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
  102. package/dist/crewfoundry/pages/HrPayrollPagePage.js +262 -147
  103. package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
  104. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +345 -167
  105. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
  106. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +98 -24
  107. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
  108. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +1 -1
  109. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
  110. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +289 -108
  111. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
  112. package/dist/crewfoundry/pages/LearningCoursesPagePage.js +221 -114
  113. package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
  114. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +134 -135
  115. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
  116. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +148 -97
  117. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
  118. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +264 -157
  119. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
  120. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +85 -93
  121. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
  122. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +211 -122
  123. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
  124. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +94 -54
  125. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
  126. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +289 -140
  127. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
  128. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +169 -79
  129. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
  130. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +296 -125
  131. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
  132. package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js +187 -0
  133. package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js.map +1 -0
  134. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +140 -78
  135. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
  136. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +93 -43
  137. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
  138. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +250 -98
  139. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
  140. package/dist/crewfoundry/store/crewfoundryStore.js +142 -184
  141. package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
  142. package/dist/crewfoundry/utils/cn.js +10 -0
  143. package/dist/crewfoundry/utils/cn.js.map +1 -0
  144. package/dist/crewfoundry/utils/courseProgress.js +46 -0
  145. package/dist/crewfoundry/utils/courseProgress.js.map +1 -0
  146. package/dist/node_modules/clsx/dist/clsx.js +18 -0
  147. package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
  148. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
  149. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  150. package/package.json +1 -1
@@ -1,172 +1,261 @@
1
1
  import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
- import { formatEnumLabel as t } from "../utils/formatEnumLabel.js";
3
- import { ShoppingBag as n, Star as r, Users as i } from "lucide-react";
4
- import { useNavigate as a } from "react-router-dom";
5
- import { jsx as o, jsxs as s } from "react/jsx-runtime";
6
- import { Badge as c, Card as l, CardContent as u, CardDescription as d, CardHeader as f, CardTitle as p, GlassCard as m, GradientText as h, PagePurpose as g, Pagination as _ } from "@burdenoff/fe-libs/ui";
7
- import { usePagination as v } from "@burdenoff/fe-libs/shared/hooks";
8
- import { useI18n as y } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
2
+ import { getInitials as t } from "../components/viz/lib/format.js";
3
+ import { RatingStars as n } from "../components/viz/RatingStars.js";
4
+ import { SegmentedTabs as r } from "../components/viz/SegmentedTabs.js";
5
+ import "../components/viz/index.js";
6
+ import { useEffect as i, useMemo as a, useState as o } from "react";
7
+ import { CheckCircle2 as s, Clock3 as c, PauseCircle as l, Search as u, ShoppingBag as d, Star as f, Users as p } from "lucide-react";
8
+ import { useNavigate as m } from "react-router-dom";
9
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
10
+ import { Button as _, CardContent as v, CardHeader as y, CardTitle as b, GlassCard as x, GradientText as S, IllustratedEmptyState as C, Input as w, PagePurpose as T, Pagination as E } from "@burdenoff/fe-libs/ui";
11
+ import { usePagination as D } from "@burdenoff/fe-libs/shared/hooks";
12
+ import { useI18n as O } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
9
13
  //#region src/crewfoundry/pages/MarketplaceMarketplacePagePage.tsx
10
- function b() {
11
- let { t: b } = y(), x = a(), { marketplaceServices: S } = e(), C = (e, t) => {
12
- let n = b(e);
14
+ function k(e) {
15
+ switch (e) {
16
+ case "active": return {
17
+ label: "Available",
18
+ icon: s,
19
+ className: "bg-status-success-bg text-status-success-text"
20
+ };
21
+ case "pending": return {
22
+ label: "Pending",
23
+ icon: c,
24
+ className: "bg-status-warning-bg text-status-warning-text"
25
+ };
26
+ default: return {
27
+ label: "Unavailable",
28
+ icon: l,
29
+ className: "bg-bg-sunken text-text-secondary"
30
+ };
31
+ }
32
+ }
33
+ function A() {
34
+ let { t: s } = O(), l = m(), { marketplaceServices: A } = e(), j = (e, t) => {
35
+ let n = s(e);
13
36
  return n === e ? t : n;
14
- }, { page: w, pageSize: T, offset: E, setPage: D } = v({ initialPageSize: 9 }), O = S.length > 0 ? (S.reduce((e, t) => e + t.rating, 0) / S.length).toFixed(1) : "0.0", k = S.slice(E, E + T), A = (e) => x(`../marketplace/service-details-page?id=${e}`);
15
- return /* @__PURE__ */ s("div", {
37
+ }, { page: M, pageSize: N, offset: P, setPage: F } = D({ initialPageSize: 9 }), [I, L] = o(""), [R, z] = o("all"), B = a(() => {
38
+ let e = /* @__PURE__ */ new Map();
39
+ for (let t of A) e.set(t.category, (e.get(t.category) ?? 0) + 1);
40
+ let t = [{
41
+ id: "all",
42
+ label: "All",
43
+ count: A.length
44
+ }];
45
+ for (let [n, r] of [...e.entries()].sort((e, t) => e[0].localeCompare(t[0]))) t.push({
46
+ id: n,
47
+ label: n,
48
+ count: r
49
+ });
50
+ return t;
51
+ }, [A]), V = a(() => {
52
+ let e = I.trim().toLowerCase();
53
+ return A.filter((t) => R !== "all" && t.category !== R ? !1 : e ? `${t.title} ${t.provider} ${t.category} ${t.skills.join(" ")}`.toLowerCase().includes(e) : !0);
54
+ }, [
55
+ A,
56
+ I,
57
+ R
58
+ ]);
59
+ i(() => {
60
+ F(1);
61
+ }, [
62
+ I,
63
+ R,
64
+ F
65
+ ]);
66
+ let H = A.length > 0 ? (A.reduce((e, t) => e + t.rating, 0) / A.length).toFixed(1) : "0.0", U = A.reduce((e, t) => e + t.reviews, 0), W = V.slice(P, P + N), G = (e) => l(`../marketplace/service-details-page?id=${e}`);
67
+ return /* @__PURE__ */ g("div", {
16
68
  className: "space-y-6 p-6",
17
69
  children: [
18
- /* @__PURE__ */ s("div", { children: [
19
- /* @__PURE__ */ o("h1", {
70
+ /* @__PURE__ */ g("div", { children: [
71
+ /* @__PURE__ */ h("h1", {
20
72
  className: "text-2xl font-semibold",
21
- children: /* @__PURE__ */ o(h, { children: C("crewfoundry.marketplace.title", "HR Services Marketplace") })
73
+ children: /* @__PURE__ */ h(S, { children: j("crewfoundry.marketplace.title", "Talent Marketplace") })
22
74
  }),
23
- /* @__PURE__ */ o("p", {
75
+ /* @__PURE__ */ h("p", {
24
76
  className: "text-sm text-text-secondary",
25
- children: C("crewfoundry.marketplace.subtitle", "Find and hire professional HR service providers")
77
+ children: j("crewfoundry.marketplace.subtitle", "Book vetted specialists and services")
26
78
  }),
27
- /* @__PURE__ */ o(g, {
79
+ /* @__PURE__ */ h(T, {
28
80
  className: "mt-1",
29
- children: "Discover freelancers and services for your projects — browse the marketplace to find and hire the right talent on demand."
81
+ children: "Discover freelancers and services for your projects — search, filter by category, and hire the right talent on demand."
30
82
  })
31
83
  ] }),
32
- /* @__PURE__ */ s("div", {
84
+ /* @__PURE__ */ g("div", {
33
85
  className: "grid gap-4 md:grid-cols-3",
34
86
  children: [
35
- /* @__PURE__ */ s(m, {
87
+ /* @__PURE__ */ g(x, {
36
88
  treatment: "glass",
37
89
  glow: !0,
38
90
  className: "border-border-seam",
39
- children: [/* @__PURE__ */ s(f, {
91
+ children: [/* @__PURE__ */ g(y, {
40
92
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
41
- children: [/* @__PURE__ */ o(p, {
93
+ children: [/* @__PURE__ */ h(b, {
42
94
  className: "text-sm font-medium",
43
- children: C("crewfoundry.marketplace.stats.services", "Services")
44
- }), /* @__PURE__ */ o(n, { className: "h-4 w-4 text-text-secondary" })]
45
- }), /* @__PURE__ */ o(u, { children: /* @__PURE__ */ o("div", {
95
+ children: j("crewfoundry.marketplace.stats.services", "Services")
96
+ }), /* @__PURE__ */ h(d, { className: "h-4 w-4 text-text-secondary" })]
97
+ }), /* @__PURE__ */ h(v, { children: /* @__PURE__ */ h("div", {
46
98
  className: "text-2xl font-bold tabular-nums",
47
- children: S.length
99
+ children: A.length
48
100
  }) })]
49
101
  }),
50
- /* @__PURE__ */ s(m, {
102
+ /* @__PURE__ */ g(x, {
51
103
  treatment: "metric",
52
104
  className: "border-border-seam",
53
- children: [/* @__PURE__ */ s(f, {
105
+ children: [/* @__PURE__ */ g(y, {
54
106
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
55
- children: [/* @__PURE__ */ o(p, {
107
+ children: [/* @__PURE__ */ h(b, {
56
108
  className: "text-sm font-medium",
57
- children: C("crewfoundry.marketplace.stats.avgRating", "Avg Rating")
58
- }), /* @__PURE__ */ o(r, { className: "h-4 w-4 text-status-warning-text" })]
59
- }), /* @__PURE__ */ o(u, { children: /* @__PURE__ */ o("div", {
109
+ children: j("crewfoundry.marketplace.stats.avgRating", "Avg Rating")
110
+ }), /* @__PURE__ */ h(f, { className: "h-4 w-4 text-status-warning-text" })]
111
+ }), /* @__PURE__ */ h(v, { children: /* @__PURE__ */ h("div", {
60
112
  className: "text-2xl font-bold tabular-nums",
61
- children: O
113
+ children: H
62
114
  }) })]
63
115
  }),
64
- /* @__PURE__ */ s(m, {
116
+ /* @__PURE__ */ g(x, {
65
117
  treatment: "metric",
66
118
  className: "border-border-seam",
67
- children: [/* @__PURE__ */ s(f, {
119
+ children: [/* @__PURE__ */ g(y, {
68
120
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
69
- children: [/* @__PURE__ */ o(p, {
121
+ children: [/* @__PURE__ */ h(b, {
70
122
  className: "text-sm font-medium",
71
- children: C("crewfoundry.marketplace.stats.totalReviews", "Total Reviews")
72
- }), /* @__PURE__ */ o(i, { className: "h-4 w-4 text-text-secondary" })]
73
- }), /* @__PURE__ */ o(u, { children: /* @__PURE__ */ o("div", {
123
+ children: j("crewfoundry.marketplace.stats.totalReviews", "Total Reviews")
124
+ }), /* @__PURE__ */ h(p, { className: "h-4 w-4 text-text-secondary" })]
125
+ }), /* @__PURE__ */ h(v, { children: /* @__PURE__ */ h("div", {
74
126
  className: "text-2xl font-bold tabular-nums",
75
- children: S.reduce((e, t) => e + t.reviews, 0)
127
+ children: U
76
128
  }) })]
77
129
  })
78
130
  ]
79
131
  }),
80
- /* @__PURE__ */ o("h2", {
81
- className: "text-lg font-medium",
82
- children: C("crewfoundry.marketplace.featured.title", "Featured Services")
132
+ /* @__PURE__ */ g("div", {
133
+ className: "flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between",
134
+ children: [/* @__PURE__ */ g("div", {
135
+ className: "relative w-full max-w-sm",
136
+ children: [/* @__PURE__ */ h(u, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ h(w, {
137
+ placeholder: "Search services, providers, skills…",
138
+ className: "pl-9",
139
+ value: I,
140
+ onChange: (e) => L(e.target.value),
141
+ "aria-label": "Search marketplace services"
142
+ })]
143
+ }), /* @__PURE__ */ h("div", {
144
+ className: "-mx-1 overflow-x-auto px-1 pb-1",
145
+ children: /* @__PURE__ */ h(r, {
146
+ tabs: B,
147
+ value: R,
148
+ onChange: z,
149
+ "aria-label": "Filter services by category"
150
+ })
151
+ })]
83
152
  }),
84
- /* @__PURE__ */ o("div", {
153
+ W.length === 0 ? /* @__PURE__ */ h(C, {
154
+ illustration: "empty-search",
155
+ title: "No services found",
156
+ description: "Try a different search term or category to find the help you need."
157
+ }) : /* @__PURE__ */ h("div", {
85
158
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
86
- children: k.map((e) => /* @__PURE__ */ s(l, {
87
- role: "button",
88
- tabIndex: 0,
89
- "aria-label": `View details for ${e.title}`,
90
- onClick: () => A(e.id),
91
- onKeyDown: (t) => {
92
- (t.key === "Enter" || t.key === " ") && (t.preventDefault(), A(e.id));
93
- },
94
- className: "hover:shadow-md transition-shadow cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-bg",
95
- children: [/* @__PURE__ */ s(f, { children: [
96
- /* @__PURE__ */ s("div", {
97
- className: "flex items-center justify-between",
98
- children: [/* @__PURE__ */ o(c, {
99
- variant: "outline",
100
- className: "text-[10px]",
101
- children: e.category
102
- }), /* @__PURE__ */ o(c, {
103
- variant: e.status === "active" ? "default" : "secondary",
104
- className: "text-[10px]",
105
- children: t(e.status)
106
- })]
107
- }),
108
- /* @__PURE__ */ o(p, {
109
- className: "text-base mt-2",
110
- children: e.title
111
- }),
112
- /* @__PURE__ */ o(d, { children: e.provider })
113
- ] }), /* @__PURE__ */ s(u, { children: [
114
- /* @__PURE__ */ o("p", {
115
- className: "text-sm text-text-secondary mb-3",
116
- children: e.description
117
- }),
118
- /* @__PURE__ */ o("div", {
119
- className: "flex flex-wrap gap-1 mb-3",
120
- children: e.skills.map((e) => /* @__PURE__ */ o(c, {
121
- variant: "outline",
122
- className: "text-[9px]",
123
- children: e
124
- }, e))
125
- }),
126
- /* @__PURE__ */ s("div", {
127
- className: "flex items-center justify-between text-sm",
128
- children: [/* @__PURE__ */ s("span", {
129
- className: "font-bold",
130
- children: [
131
- "$",
132
- e.price.toLocaleString(),
133
- /* @__PURE__ */ s("span", {
134
- className: "text-xs font-normal text-text-secondary",
135
- children: ["/", e.priceType]
136
- })
137
- ]
138
- }), /* @__PURE__ */ s("span", {
139
- className: "flex items-center gap-1",
140
- children: [
141
- /* @__PURE__ */ o(r, { className: "h-3 w-3 text-status-warning-text" }),
142
- e.rating,
143
- " (",
144
- e.reviews,
145
- ")"
146
- ]
147
- })]
148
- }),
149
- /* @__PURE__ */ s("p", {
150
- className: "text-xs text-text-secondary mt-1",
159
+ children: W.map((e) => {
160
+ let r = k(e.status), i = r.icon;
161
+ return /* @__PURE__ */ h(x, {
162
+ treatment: "glass",
163
+ role: "button",
164
+ tabIndex: 0,
165
+ "aria-label": `View and book ${e.title} by ${e.provider}`,
166
+ onClick: () => G(e.id),
167
+ onKeyDown: (t) => {
168
+ (t.key === "Enter" || t.key === " ") && (t.preventDefault(), G(e.id));
169
+ },
170
+ className: "cursor-pointer border-border-seam transition-shadow hover:shadow-elevation-2 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]",
171
+ children: /* @__PURE__ */ g(v, {
172
+ className: "flex h-full flex-col gap-3 p-4",
151
173
  children: [
152
- C("crewfoundry.marketplace.card.delivery", "Delivery"),
153
- ": ",
154
- e.deliveryTime
174
+ /* @__PURE__ */ g("div", {
175
+ className: "flex items-start justify-between gap-2",
176
+ children: [/* @__PURE__ */ g("div", {
177
+ className: "flex items-center gap-2.5",
178
+ children: [/* @__PURE__ */ h("span", {
179
+ className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-action-primary-bg text-sm font-semibold text-action-primary-text",
180
+ "aria-hidden": "true",
181
+ children: t(e.provider)
182
+ }), /* @__PURE__ */ g("div", {
183
+ className: "min-w-0",
184
+ children: [/* @__PURE__ */ h("p", {
185
+ className: "truncate text-sm font-semibold",
186
+ children: e.provider
187
+ }), /* @__PURE__ */ h("span", {
188
+ className: "inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] text-text-secondary",
189
+ children: e.category
190
+ })]
191
+ })]
192
+ }), /* @__PURE__ */ g("div", {
193
+ className: "shrink-0 text-right",
194
+ children: [/* @__PURE__ */ g("p", {
195
+ className: "text-base font-bold tabular-nums",
196
+ children: ["$", e.price.toLocaleString()]
197
+ }), /* @__PURE__ */ g("p", {
198
+ className: "text-[10px] text-text-secondary",
199
+ children: ["/", e.priceType]
200
+ })]
201
+ })]
202
+ }),
203
+ /* @__PURE__ */ h("p", {
204
+ className: "text-sm font-medium",
205
+ children: e.title
206
+ }),
207
+ /* @__PURE__ */ g("div", {
208
+ className: "flex flex-wrap items-center gap-2",
209
+ children: [/* @__PURE__ */ h(n, {
210
+ value: e.rating,
211
+ count: e.reviews,
212
+ showValue: !0,
213
+ size: 14
214
+ }), /* @__PURE__ */ g("span", {
215
+ className: `inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-medium ${r.className}`,
216
+ children: [/* @__PURE__ */ h(i, { className: "h-3 w-3" }), r.label]
217
+ })]
218
+ }),
219
+ /* @__PURE__ */ h("p", {
220
+ className: "line-clamp-2 text-xs text-text-secondary",
221
+ children: e.description
222
+ }),
223
+ /* @__PURE__ */ h("div", {
224
+ className: "flex flex-wrap gap-1",
225
+ children: e.skills.slice(0, 4).map((e) => /* @__PURE__ */ h("span", {
226
+ className: "rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] text-text-secondary",
227
+ children: e
228
+ }, e))
229
+ }),
230
+ /* @__PURE__ */ h("div", {
231
+ className: "mt-auto flex items-center justify-between pt-1 text-[11px] text-text-secondary",
232
+ children: /* @__PURE__ */ g("span", {
233
+ className: "flex items-center gap-1",
234
+ children: [/* @__PURE__ */ h(c, { className: "h-3 w-3" }), e.deliveryTime]
235
+ })
236
+ }),
237
+ /* @__PURE__ */ h(_, {
238
+ className: "w-full",
239
+ onClick: (t) => {
240
+ t.stopPropagation(), G(e.id);
241
+ },
242
+ children: j("crewfoundry.marketplace.card.book", "View & Book")
243
+ })
155
244
  ]
156
245
  })
157
- ] })]
158
- }, e.id))
246
+ }, e.id);
247
+ })
159
248
  }),
160
- /* @__PURE__ */ o(_, {
161
- page: w,
162
- pageSize: T,
163
- totalItems: S.length,
164
- onPageChange: D
165
- })
249
+ V.length > N ? /* @__PURE__ */ h(E, {
250
+ page: M,
251
+ pageSize: N,
252
+ totalItems: V.length,
253
+ onPageChange: F
254
+ }) : null
166
255
  ]
167
256
  });
168
257
  }
169
258
  //#endregion
170
- export { b as MarketplaceMarketplacePagePage };
259
+ export { A as MarketplaceMarketplacePagePage };
171
260
 
172
261
  //# sourceMappingURL=MarketplaceMarketplacePagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MarketplaceMarketplacePagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/MarketplaceMarketplacePagePage.tsx"],"sourcesContent":["import {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n Pagination,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\nimport { ShoppingBag, Star, Users } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\n\nexport function MarketplaceMarketplacePagePage() {\n const { t: translate } = useI18n();\n const navigate = useNavigate();\n const { marketplaceServices } = useCrewFoundryStore();\n const t = (key: string, fallback: string) => {\n const value = translate(key);\n return value === key ? fallback : value;\n };\n const { page, pageSize, offset, setPage } = usePagination({ initialPageSize: 9 });\n const avgRating =\n marketplaceServices.length > 0\n ? (\n marketplaceServices.reduce((s, m) => s + m.rating, 0) / marketplaceServices.length\n ).toFixed(1)\n : '0.0';\n const pagedServices = marketplaceServices.slice(offset, offset + pageSize);\n const openService = (id: string) => navigate(`../marketplace/service-details-page?id=${id}`);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>\n {t('crewfoundry.marketplace.title', 'HR Services Marketplace')}\n </GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {t('crewfoundry.marketplace.subtitle', 'Find and hire professional HR service providers')}\n </p>\n <PagePurpose className=\"mt-1\">\n Discover freelancers and services for your projects — browse the marketplace to find and\n hire the right talent on demand.\n </PagePurpose>\n </div>\n <div className=\"grid gap-4 md:grid-cols-3\">\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\">\n {t('crewfoundry.marketplace.stats.services', 'Services')}\n </CardTitle>\n <ShoppingBag className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{marketplaceServices.length}</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\">\n {t('crewfoundry.marketplace.stats.avgRating', 'Avg Rating')}\n </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}</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\">\n {t('crewfoundry.marketplace.stats.totalReviews', 'Total Reviews')}\n </CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {marketplaceServices.reduce((s, m) => s + m.reviews, 0)}\n </div>\n </CardContent>\n </GlassCard>\n </div>\n <h2 className=\"text-lg font-medium\">\n {t('crewfoundry.marketplace.featured.title', 'Featured Services')}\n </h2>\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {pagedServices.map((svc) => (\n <Card\n key={svc.id}\n role=\"button\"\n tabIndex={0}\n aria-label={`View details for ${svc.title}`}\n onClick={() => openService(svc.id)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n openService(svc.id);\n }\n }}\n className=\"hover:shadow-md transition-shadow cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-action-primary-bg\"\n >\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {svc.category}\n </Badge>\n <Badge\n variant={svc.status === 'active' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {formatEnumLabel(svc.status)}\n </Badge>\n </div>\n <CardTitle className=\"text-base mt-2\">{svc.title}</CardTitle>\n <CardDescription>{svc.provider}</CardDescription>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-text-secondary mb-3\">{svc.description}</p>\n <div className=\"flex flex-wrap gap-1 mb-3\">\n {svc.skills.map((s) => (\n <Badge key={s} variant=\"outline\" className=\"text-[9px]\">\n {s}\n </Badge>\n ))}\n </div>\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"font-bold\">\n ${svc.price.toLocaleString()}\n <span className=\"text-xs font-normal text-text-secondary\">/{svc.priceType}</span>\n </span>\n <span className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" />\n {svc.rating} ({svc.reviews})\n </span>\n </div>\n <p className=\"text-xs text-text-secondary mt-1\">\n {t('crewfoundry.marketplace.card.delivery', 'Delivery')}: {svc.deliveryTime}\n </p>\n </CardContent>\n </Card>\n ))}\n </div>\n <Pagination\n page={page}\n pageSize={pageSize}\n totalItems={marketplaceServices.length}\n onPageChange={setPage}\n />\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MarketplaceMarketplacePagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/MarketplaceMarketplacePagePage.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport {\n Button,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n Pagination,\n} from '@burdenoff/fe-libs/ui';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\nimport { CheckCircle2, Clock3, PauseCircle, Search, ShoppingBag, Star, Users } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore, type MarketplaceService } from '../store/crewfoundryStore';\nimport { RatingStars, SegmentedTabs, getInitials, type SegmentedTab } from '../components/viz';\n\n/** Honest availability derived from the real service `status` enum (never \"Booked\"). */\nfunction availabilityOf(status: MarketplaceService['status']): {\n label: string;\n icon: typeof CheckCircle2;\n className: string;\n} {\n switch (status) {\n case 'active':\n return {\n label: 'Available',\n icon: CheckCircle2,\n className: 'bg-status-success-bg text-status-success-text',\n };\n case 'pending':\n return {\n label: 'Pending',\n icon: Clock3,\n className: 'bg-status-warning-bg text-status-warning-text',\n };\n default:\n return {\n label: 'Unavailable',\n icon: PauseCircle,\n className: 'bg-bg-sunken text-text-secondary',\n };\n }\n}\n\nexport function MarketplaceMarketplacePagePage() {\n const { t: translate } = useI18n();\n const navigate = useNavigate();\n const { marketplaceServices } = useCrewFoundryStore();\n const t = (key: string, fallback: string) => {\n const value = translate(key);\n return value === key ? fallback : value;\n };\n const { page, pageSize, offset, setPage } = usePagination({ initialPageSize: 9 });\n const [search, setSearch] = useState('');\n const [category, setCategory] = useState('all');\n\n const categoryTabs = useMemo<SegmentedTab[]>(() => {\n const counts = new Map<string, number>();\n for (const svc of marketplaceServices) {\n counts.set(svc.category, (counts.get(svc.category) ?? 0) + 1);\n }\n const tabs: SegmentedTab[] = [{ id: 'all', label: 'All', count: marketplaceServices.length }];\n for (const [name, count] of [...counts.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {\n tabs.push({ id: name, label: name, count });\n }\n return tabs;\n }, [marketplaceServices]);\n\n const filtered = useMemo(() => {\n const query = search.trim().toLowerCase();\n return marketplaceServices.filter((svc) => {\n if (category !== 'all' && svc.category !== category) {\n return false;\n }\n if (!query) {\n return true;\n }\n return `${svc.title} ${svc.provider} ${svc.category} ${svc.skills.join(' ')}`\n .toLowerCase()\n .includes(query);\n });\n }, [marketplaceServices, search, category]);\n\n useEffect(() => {\n setPage(1);\n }, [search, category, setPage]);\n\n const avgRating =\n marketplaceServices.length > 0\n ? (\n marketplaceServices.reduce((s, m) => s + m.rating, 0) / marketplaceServices.length\n ).toFixed(1)\n : '0.0';\n const totalReviews = marketplaceServices.reduce((s, m) => s + m.reviews, 0);\n const pagedServices = filtered.slice(offset, offset + pageSize);\n const openService = (id: string) => navigate(`../marketplace/service-details-page?id=${id}`);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>{t('crewfoundry.marketplace.title', 'Talent Marketplace')}</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {t('crewfoundry.marketplace.subtitle', 'Book vetted specialists and services')}\n </p>\n <PagePurpose className=\"mt-1\">\n Discover freelancers and services for your projects — search, filter by category, and hire\n the right talent on demand.\n </PagePurpose>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\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\">\n {t('crewfoundry.marketplace.stats.services', 'Services')}\n </CardTitle>\n <ShoppingBag className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{marketplaceServices.length}</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\">\n {t('crewfoundry.marketplace.stats.avgRating', 'Avg Rating')}\n </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}</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\">\n {t('crewfoundry.marketplace.stats.totalReviews', 'Total Reviews')}\n </CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{totalReviews}</div>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"relative w-full max-w-sm\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <Input\n placeholder=\"Search services, providers, skills…\"\n className=\"pl-9\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n aria-label=\"Search marketplace services\"\n />\n </div>\n <div className=\"-mx-1 overflow-x-auto px-1 pb-1\">\n <SegmentedTabs\n tabs={categoryTabs}\n value={category}\n onChange={setCategory}\n aria-label=\"Filter services by category\"\n />\n </div>\n </div>\n\n {pagedServices.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No services found\"\n description=\"Try a different search term or category to find the help you need.\"\n />\n ) : (\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {pagedServices.map((svc) => {\n const availability = availabilityOf(svc.status);\n const AvailabilityIcon = availability.icon;\n return (\n <GlassCard\n key={svc.id}\n treatment=\"glass\"\n role=\"button\"\n tabIndex={0}\n aria-label={`View and book ${svc.title} by ${svc.provider}`}\n onClick={() => openService(svc.id)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n openService(svc.id);\n }\n }}\n className=\"cursor-pointer border-border-seam transition-shadow hover:shadow-elevation-2 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <CardContent className=\"flex h-full flex-col gap-3 p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex items-center gap-2.5\">\n <span\n className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-action-primary-bg text-sm font-semibold text-action-primary-text\"\n aria-hidden=\"true\"\n >\n {getInitials(svc.provider)}\n </span>\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-semibold\">{svc.provider}</p>\n <span className=\"inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] text-text-secondary\">\n {svc.category}\n </span>\n </div>\n </div>\n <div className=\"shrink-0 text-right\">\n <p className=\"text-base font-bold tabular-nums\">${svc.price.toLocaleString()}</p>\n <p className=\"text-[10px] text-text-secondary\">/{svc.priceType}</p>\n </div>\n </div>\n\n <p className=\"text-sm font-medium\">{svc.title}</p>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <RatingStars value={svc.rating} count={svc.reviews} showValue size={14} />\n <span\n className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-medium ${availability.className}`}\n >\n <AvailabilityIcon className=\"h-3 w-3\" />\n {availability.label}\n </span>\n </div>\n\n <p className=\"line-clamp-2 text-xs text-text-secondary\">{svc.description}</p>\n\n <div className=\"flex flex-wrap gap-1\">\n {svc.skills.slice(0, 4).map((skill) => (\n <span\n key={skill}\n className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] text-text-secondary\"\n >\n {skill}\n </span>\n ))}\n </div>\n\n <div className=\"mt-auto flex items-center justify-between pt-1 text-[11px] text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <Clock3 className=\"h-3 w-3\" />\n {svc.deliveryTime}\n </span>\n </div>\n\n <Button\n className=\"w-full\"\n onClick={(event) => {\n event.stopPropagation();\n openService(svc.id);\n }}\n >\n {t('crewfoundry.marketplace.card.book', 'View & Book')}\n </Button>\n </CardContent>\n </GlassCard>\n );\n })}\n </div>\n )}\n\n {filtered.length > pageSize ? (\n <Pagination\n page={page}\n pageSize={pageSize}\n totalItems={filtered.length}\n onPageChange={setPage}\n />\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}