@burdenoff/microfe-crewfoundry 2026.704.6 → 2026.704.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crewfoundry/CrewFoundryRoutes.js +51 -43
- package/dist/crewfoundry/CrewFoundryRoutes.js.map +1 -1
- package/dist/crewfoundry/components/forms/formValues.js +5 -2
- package/dist/crewfoundry/components/forms/formValues.js.map +1 -1
- package/dist/crewfoundry/components/viz/AllocationBar.js +68 -0
- package/dist/crewfoundry/components/viz/AllocationBar.js.map +1 -0
- package/dist/crewfoundry/components/viz/AreaChart.js +102 -0
- package/dist/crewfoundry/components/viz/AreaChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/AvatarStack.js +36 -0
- package/dist/crewfoundry/components/viz/AvatarStack.js.map +1 -0
- package/dist/crewfoundry/components/viz/BarChart.js +83 -0
- package/dist/crewfoundry/components/viz/BarChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/CertificateCard.js +118 -0
- package/dist/crewfoundry/components/viz/CertificateCard.js.map +1 -0
- package/dist/crewfoundry/components/viz/DonutChart.js +109 -0
- package/dist/crewfoundry/components/viz/DonutChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/HBarFunnel.js +54 -0
- package/dist/crewfoundry/components/viz/HBarFunnel.js.map +1 -0
- package/dist/crewfoundry/components/viz/Heatmap.js +91 -0
- package/dist/crewfoundry/components/viz/Heatmap.js.map +1 -0
- package/dist/crewfoundry/components/viz/KanbanBoard.js +50 -0
- package/dist/crewfoundry/components/viz/KanbanBoard.js.map +1 -0
- package/dist/crewfoundry/components/viz/LineChart.js +123 -0
- package/dist/crewfoundry/components/viz/LineChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/OrgTree.js +83 -0
- package/dist/crewfoundry/components/viz/OrgTree.js.map +1 -0
- package/dist/crewfoundry/components/viz/PathSteps.js +68 -0
- package/dist/crewfoundry/components/viz/PathSteps.js.map +1 -0
- package/dist/crewfoundry/components/viz/ProgressRing.js +68 -0
- package/dist/crewfoundry/components/viz/ProgressRing.js.map +1 -0
- package/dist/crewfoundry/components/viz/RatingStars.js +51 -0
- package/dist/crewfoundry/components/viz/RatingStars.js.map +1 -0
- package/dist/crewfoundry/components/viz/SegmentedTabs.js +69 -0
- package/dist/crewfoundry/components/viz/SegmentedTabs.js.map +1 -0
- package/dist/crewfoundry/components/viz/SkillBar.js +3 -0
- package/dist/crewfoundry/components/viz/Sparkline.js +74 -0
- package/dist/crewfoundry/components/viz/Sparkline.js.map +1 -0
- package/dist/crewfoundry/components/viz/StatCard.js +60 -0
- package/dist/crewfoundry/components/viz/StatCard.js.map +1 -0
- package/dist/crewfoundry/components/viz/StepProgress.js +3 -0
- package/dist/crewfoundry/components/viz/Timeline.js +66 -0
- package/dist/crewfoundry/components/viz/Timeline.js.map +1 -0
- package/dist/crewfoundry/components/viz/index.js +23 -0
- package/dist/crewfoundry/components/viz/lib/Avatar.js +30 -0
- package/dist/crewfoundry/components/viz/lib/Avatar.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/CartesianFrame.js +119 -0
- package/dist/crewfoundry/components/viz/lib/CartesianFrame.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js +35 -0
- package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/format.js +21 -0
- package/dist/crewfoundry/components/viz/lib/format.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/geometry.js +69 -0
- package/dist/crewfoundry/components/viz/lib/geometry.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/hooks.js +39 -0
- package/dist/crewfoundry/components/viz/lib/hooks.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/palette.js +27 -0
- package/dist/crewfoundry/components/viz/lib/palette.js.map +1 -0
- package/dist/crewfoundry/lib/analytics.js +323 -0
- package/dist/crewfoundry/lib/analytics.js.map +1 -0
- package/dist/crewfoundry/lib/companyFinance.js +16 -0
- package/dist/crewfoundry/lib/companyFinance.js.map +1 -0
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +226 -283
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +107 -120
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +122 -162
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +121 -158
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +316 -211
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +75 -27
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +167 -165
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +168 -109
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +401 -290
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +84 -75
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +368 -174
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +236 -201
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +369 -196
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +269 -270
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +210 -110
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +216 -178
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js +385 -0
- package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js.map +1 -0
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js +189 -130
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +397 -241
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +262 -147
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +345 -167
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +98 -24
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +289 -108
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +221 -114
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +134 -135
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +148 -97
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +264 -157
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +85 -93
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +211 -122
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +94 -54
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +289 -140
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +169 -79
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +296 -125
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js +187 -0
- package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js.map +1 -0
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +140 -78
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +93 -43
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +250 -98
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
- package/dist/crewfoundry/utils/cn.js +10 -0
- package/dist/crewfoundry/utils/cn.js.map +1 -0
- package/dist/crewfoundry/utils/courseProgress.js +46 -0
- package/dist/crewfoundry/utils/courseProgress.js.map +1 -0
- package/dist/node_modules/clsx/dist/clsx.js +18 -0
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,161 +1,310 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
2
|
+
import { getInitials as t } from "../components/viz/lib/format.js";
|
|
3
|
+
import { RatingStars as n } from "../components/viz/RatingStars.js";
|
|
4
|
+
import "../components/viz/index.js";
|
|
5
|
+
import { useMemo as r, useState as i } from "react";
|
|
6
|
+
import { CalendarDays as a, CheckCircle2 as o, Clock3 as s, MessageSquare as c, PauseCircle as l, Star as u } from "lucide-react";
|
|
7
|
+
import { useLocation as d, useNavigate as f } from "react-router-dom";
|
|
8
|
+
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
9
|
+
import { Badge as h, Button as g, Card as _, CardContent as v, CardHeader as y, CardTitle as b, EmphasisPanel as x, GradientText as S, IllustratedEmptyState as C, Input as w, PagePurpose as T, Spinner as E } from "@burdenoff/fe-libs/ui";
|
|
6
10
|
//#region src/crewfoundry/pages/MarketplaceServiceDetailsPagePage.tsx
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
function D(e) {
|
|
12
|
+
switch (e) {
|
|
13
|
+
case "active": return {
|
|
14
|
+
label: "Available for new projects",
|
|
15
|
+
icon: o,
|
|
16
|
+
className: "text-status-success-text"
|
|
17
|
+
};
|
|
18
|
+
case "pending": return {
|
|
19
|
+
label: "Pending review",
|
|
20
|
+
icon: s,
|
|
21
|
+
className: "text-status-warning-text"
|
|
22
|
+
};
|
|
23
|
+
default: return {
|
|
24
|
+
label: "Not currently available",
|
|
25
|
+
icon: l,
|
|
26
|
+
className: "text-text-secondary"
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function O() {
|
|
31
|
+
let o = f(), l = d(), { marketplaceServices: O, initialized: k } = e(), A = new URLSearchParams(l.search).get("id"), j = O.find((e) => e.id === A) ?? O[0], M = r(() => j ? O.filter((e) => e.provider === j.provider) : [], [O, j]), [N, P] = i(null), F = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), [I, L] = i(F);
|
|
32
|
+
if (!k && !j) return /* @__PURE__ */ p("div", {
|
|
10
33
|
className: "flex min-h-[60vh] items-center justify-center p-6",
|
|
11
|
-
children: /* @__PURE__ */
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
34
|
+
children: /* @__PURE__ */ p(E, { size: "lg" })
|
|
35
|
+
});
|
|
36
|
+
if (!j) return /* @__PURE__ */ p("div", {
|
|
37
|
+
className: "p-6",
|
|
38
|
+
children: /* @__PURE__ */ p(C, {
|
|
39
|
+
illustration: "empty-search",
|
|
40
|
+
title: "Service not found",
|
|
41
|
+
description: "This service is no longer available."
|
|
42
|
+
})
|
|
43
|
+
});
|
|
44
|
+
let R = M.find((e) => e.id === N) ?? j, z = D(j.status), B = z.icon;
|
|
45
|
+
return /* @__PURE__ */ m("div", {
|
|
46
|
+
className: "space-y-6 p-6",
|
|
47
|
+
children: [/* @__PURE__ */ m("div", {
|
|
48
|
+
className: "text-xs text-text-secondary",
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ p("button", {
|
|
51
|
+
type: "button",
|
|
52
|
+
className: "hover:text-text-primary",
|
|
53
|
+
onClick: () => o("../marketplace/marketplace-page"),
|
|
54
|
+
children: "Marketplace"
|
|
55
|
+
}),
|
|
56
|
+
/* @__PURE__ */ p("span", {
|
|
57
|
+
className: "mx-1",
|
|
58
|
+
children: "/"
|
|
59
|
+
}),
|
|
60
|
+
/* @__PURE__ */ p("span", {
|
|
61
|
+
className: "text-text-primary",
|
|
62
|
+
children: j.title
|
|
63
|
+
})
|
|
64
|
+
]
|
|
65
|
+
}), /* @__PURE__ */ m("div", {
|
|
66
|
+
className: "grid gap-6 lg:grid-cols-3",
|
|
67
|
+
children: [/* @__PURE__ */ m("div", {
|
|
68
|
+
className: "space-y-6 lg:col-span-2",
|
|
69
|
+
children: [
|
|
70
|
+
/* @__PURE__ */ m("div", {
|
|
71
|
+
className: "flex flex-col gap-4 sm:flex-row sm:items-start",
|
|
72
|
+
children: [/* @__PURE__ */ p("span", {
|
|
73
|
+
className: "flex h-20 w-20 shrink-0 items-center justify-center rounded-full bg-action-primary-bg text-2xl font-semibold text-action-primary-text",
|
|
74
|
+
"aria-hidden": "true",
|
|
75
|
+
children: t(j.provider)
|
|
76
|
+
}), /* @__PURE__ */ m("div", {
|
|
77
|
+
className: "min-w-0 flex-1 space-y-2",
|
|
78
|
+
children: [
|
|
79
|
+
/* @__PURE__ */ p("h1", {
|
|
80
|
+
className: "text-2xl font-semibold",
|
|
81
|
+
children: /* @__PURE__ */ p(S, { children: j.provider })
|
|
82
|
+
}),
|
|
83
|
+
/* @__PURE__ */ p("p", {
|
|
84
|
+
className: "text-sm text-text-secondary",
|
|
85
|
+
children: j.title
|
|
86
|
+
}),
|
|
87
|
+
/* @__PURE__ */ m("div", {
|
|
88
|
+
className: "flex flex-wrap items-center gap-3",
|
|
89
|
+
children: [
|
|
90
|
+
/* @__PURE__ */ p(n, {
|
|
91
|
+
value: j.rating,
|
|
92
|
+
count: j.reviews,
|
|
93
|
+
showValue: !0,
|
|
94
|
+
size: 16
|
|
95
|
+
}),
|
|
96
|
+
/* @__PURE__ */ m("span", {
|
|
97
|
+
className: "flex items-center gap-1 text-xs text-text-secondary",
|
|
98
|
+
children: [/* @__PURE__ */ p(s, { className: "h-3 w-3" }), j.deliveryTime]
|
|
99
|
+
}),
|
|
100
|
+
/* @__PURE__ */ p(h, {
|
|
101
|
+
variant: "outline",
|
|
102
|
+
className: "text-[10px]",
|
|
103
|
+
children: j.category
|
|
104
|
+
})
|
|
105
|
+
]
|
|
106
|
+
}),
|
|
107
|
+
/* @__PURE__ */ p("div", {
|
|
108
|
+
className: "flex flex-wrap gap-1.5 pt-1",
|
|
109
|
+
children: j.skills.map((e) => /* @__PURE__ */ p(h, {
|
|
110
|
+
variant: "secondary",
|
|
111
|
+
className: "text-xs",
|
|
112
|
+
children: e
|
|
113
|
+
}, e))
|
|
114
|
+
})
|
|
115
|
+
]
|
|
116
|
+
})]
|
|
21
117
|
}),
|
|
22
|
-
/* @__PURE__ */
|
|
118
|
+
/* @__PURE__ */ p(T, { children: "See exactly what this service includes, what it costs, and how others rated it — use the booking panel to pick a package and request an engagement." }),
|
|
119
|
+
/* @__PURE__ */ m(x, { children: [/* @__PURE__ */ p("div", {
|
|
120
|
+
className: "mb-2 text-lg font-semibold",
|
|
121
|
+
children: "About this service"
|
|
122
|
+
}), /* @__PURE__ */ p("p", {
|
|
23
123
|
className: "text-sm text-text-secondary",
|
|
24
|
-
children:
|
|
124
|
+
children: j.description
|
|
125
|
+
})] }),
|
|
126
|
+
/* @__PURE__ */ m("div", {
|
|
127
|
+
className: "space-y-3",
|
|
128
|
+
children: [/* @__PURE__ */ p("h2", {
|
|
129
|
+
className: "text-lg font-semibold",
|
|
130
|
+
children: "Services offered"
|
|
131
|
+
}), /* @__PURE__ */ p("div", {
|
|
132
|
+
className: "grid gap-3 sm:grid-cols-2 xl:grid-cols-3",
|
|
133
|
+
children: M.map((e) => {
|
|
134
|
+
let t = e.id === R.id;
|
|
135
|
+
return /* @__PURE__ */ m("button", {
|
|
136
|
+
type: "button",
|
|
137
|
+
onClick: () => P(e.id),
|
|
138
|
+
"aria-pressed": t,
|
|
139
|
+
className: `flex flex-col rounded-lg border p-4 text-left transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] ${t ? "border-action-primary-bg bg-action-primary-bg/5" : "border-border-subtle hover:bg-bg-sunken/50"}`,
|
|
140
|
+
children: [
|
|
141
|
+
/* @__PURE__ */ m("div", {
|
|
142
|
+
className: "flex items-start justify-between gap-2",
|
|
143
|
+
children: [/* @__PURE__ */ p("p", {
|
|
144
|
+
className: "text-sm font-semibold",
|
|
145
|
+
children: e.title
|
|
146
|
+
}), /* @__PURE__ */ p("span", {
|
|
147
|
+
className: "whitespace-nowrap text-[11px] text-text-secondary",
|
|
148
|
+
children: e.deliveryTime
|
|
149
|
+
})]
|
|
150
|
+
}),
|
|
151
|
+
/* @__PURE__ */ m("p", {
|
|
152
|
+
className: "mt-1 text-xl font-bold tabular-nums",
|
|
153
|
+
children: [
|
|
154
|
+
"$",
|
|
155
|
+
e.price.toLocaleString(),
|
|
156
|
+
/* @__PURE__ */ m("span", {
|
|
157
|
+
className: "text-xs font-normal text-text-secondary",
|
|
158
|
+
children: ["/", e.priceType]
|
|
159
|
+
})
|
|
160
|
+
]
|
|
161
|
+
}),
|
|
162
|
+
/* @__PURE__ */ p("p", {
|
|
163
|
+
className: "mt-2 line-clamp-3 text-xs text-text-secondary",
|
|
164
|
+
children: e.description
|
|
165
|
+
})
|
|
166
|
+
]
|
|
167
|
+
}, e.id);
|
|
168
|
+
})
|
|
169
|
+
})]
|
|
25
170
|
}),
|
|
26
|
-
/* @__PURE__ */
|
|
27
|
-
className: "
|
|
28
|
-
children:
|
|
171
|
+
/* @__PURE__ */ m("div", {
|
|
172
|
+
className: "space-y-3",
|
|
173
|
+
children: [/* @__PURE__ */ p("h2", {
|
|
174
|
+
className: "text-lg font-semibold",
|
|
175
|
+
children: "Reviews"
|
|
176
|
+
}), /* @__PURE__ */ p(_, { children: /* @__PURE__ */ m(v, {
|
|
177
|
+
className: "flex flex-col items-center gap-2 p-6 text-center",
|
|
178
|
+
children: [/* @__PURE__ */ m("div", {
|
|
179
|
+
className: "flex items-center gap-2",
|
|
180
|
+
children: [
|
|
181
|
+
/* @__PURE__ */ p(u, {
|
|
182
|
+
className: "h-6 w-6 text-status-warning-text",
|
|
183
|
+
fill: "currentColor"
|
|
184
|
+
}),
|
|
185
|
+
/* @__PURE__ */ p("span", {
|
|
186
|
+
className: "text-2xl font-bold tabular-nums",
|
|
187
|
+
children: j.rating.toFixed(1)
|
|
188
|
+
}),
|
|
189
|
+
/* @__PURE__ */ p("span", {
|
|
190
|
+
className: "text-sm text-text-secondary",
|
|
191
|
+
children: "/ 5"
|
|
192
|
+
})
|
|
193
|
+
]
|
|
194
|
+
}), /* @__PURE__ */ m("p", {
|
|
195
|
+
className: "text-sm text-text-secondary",
|
|
196
|
+
children: [
|
|
197
|
+
"Based on ",
|
|
198
|
+
j.reviews.toLocaleString(),
|
|
199
|
+
" ",
|
|
200
|
+
j.reviews === 1 ? "review" : "reviews",
|
|
201
|
+
". Individual review notes aren't published for this listing yet."
|
|
202
|
+
]
|
|
203
|
+
})]
|
|
204
|
+
}) })]
|
|
29
205
|
})
|
|
30
|
-
] }), /* @__PURE__ */ l("div", {
|
|
31
|
-
className: "flex gap-2",
|
|
32
|
-
children: [/* @__PURE__ */ l(d, {
|
|
33
|
-
variant: "outline",
|
|
34
|
-
onClick: () => b("../marketplace/messaging-page"),
|
|
35
|
-
children: [/* @__PURE__ */ c(r, { className: "h-4 w-4 mr-1" }), "Contact"]
|
|
36
|
-
}), /* @__PURE__ */ c(d, {
|
|
37
|
-
disabled: !0,
|
|
38
|
-
title: "Hiring is coming soon",
|
|
39
|
-
"aria-label": "Hire now — coming soon",
|
|
40
|
-
children: "Hire Now · Coming soon"
|
|
41
|
-
})]
|
|
42
|
-
})]
|
|
43
|
-
}),
|
|
44
|
-
/* @__PURE__ */ c(_, {
|
|
45
|
-
storageKey: "crewfoundry-service-details",
|
|
46
|
-
steps: [
|
|
47
|
-
{
|
|
48
|
-
id: "contact",
|
|
49
|
-
label: "Message the provider",
|
|
50
|
-
description: "Ask questions before you commit to hiring.",
|
|
51
|
-
icon: /* @__PURE__ */ c(r, { className: "h-4 w-4" }),
|
|
52
|
-
onClick: () => b("../marketplace/messaging-page")
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
id: "compare",
|
|
56
|
-
label: "Compare other services",
|
|
57
|
-
description: "Browse similar offerings on the marketplace.",
|
|
58
|
-
icon: /* @__PURE__ */ c(a, { className: "h-4 w-4" }),
|
|
59
|
-
onClick: () => b("../marketplace/marketplace-services-page")
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
id: "bookings",
|
|
63
|
-
label: "Manage your bookings",
|
|
64
|
-
description: "Track engagements you have already arranged.",
|
|
65
|
-
icon: /* @__PURE__ */ c(t, { className: "h-4 w-4" }),
|
|
66
|
-
onClick: () => b("../marketplace/booking-management-page")
|
|
67
|
-
}
|
|
68
206
|
]
|
|
69
|
-
}),
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
/* @__PURE__ */
|
|
74
|
-
className: "
|
|
207
|
+
}), /* @__PURE__ */ p("div", {
|
|
208
|
+
className: "lg:col-span-1",
|
|
209
|
+
children: /* @__PURE__ */ m(_, {
|
|
210
|
+
className: "lg:sticky lg:top-6",
|
|
211
|
+
children: [/* @__PURE__ */ p(y, { children: /* @__PURE__ */ p(b, {
|
|
212
|
+
className: "text-lg",
|
|
213
|
+
children: "Book this service"
|
|
214
|
+
}) }), /* @__PURE__ */ m(v, {
|
|
215
|
+
className: "space-y-5",
|
|
75
216
|
children: [
|
|
76
|
-
/* @__PURE__ */
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
217
|
+
/* @__PURE__ */ m("fieldset", {
|
|
218
|
+
className: "space-y-2",
|
|
219
|
+
children: [/* @__PURE__ */ p("legend", {
|
|
220
|
+
className: "mb-1 text-sm font-medium",
|
|
221
|
+
children: "Package"
|
|
222
|
+
}), M.map((e) => {
|
|
223
|
+
let t = e.id === R.id;
|
|
224
|
+
return /* @__PURE__ */ m("button", {
|
|
225
|
+
type: "button",
|
|
226
|
+
onClick: () => P(e.id),
|
|
227
|
+
"aria-pressed": t,
|
|
228
|
+
className: `flex w-full items-center justify-between gap-3 rounded-lg border px-3 py-2.5 text-left transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] ${t ? "border-action-primary-bg bg-action-primary-bg/5" : "border-border-subtle hover:bg-bg-sunken/50"}`,
|
|
229
|
+
children: [/* @__PURE__ */ m("span", {
|
|
230
|
+
className: "flex items-center gap-2 min-w-0",
|
|
231
|
+
children: [/* @__PURE__ */ p("span", {
|
|
232
|
+
className: `flex h-4 w-4 shrink-0 items-center justify-center rounded-full border ${t ? "border-action-primary-bg" : "border-border-strong"}`,
|
|
233
|
+
"aria-hidden": "true",
|
|
234
|
+
children: t ? /* @__PURE__ */ p("span", { className: "h-2 w-2 rounded-full bg-action-primary-bg" }) : null
|
|
235
|
+
}), /* @__PURE__ */ p("span", {
|
|
236
|
+
className: "truncate text-sm",
|
|
237
|
+
children: e.title
|
|
238
|
+
})]
|
|
239
|
+
}), /* @__PURE__ */ m("span", {
|
|
240
|
+
className: "whitespace-nowrap text-sm font-semibold tabular-nums",
|
|
241
|
+
children: ["$", e.price.toLocaleString()]
|
|
242
|
+
})]
|
|
243
|
+
}, e.id);
|
|
244
|
+
})]
|
|
80
245
|
}),
|
|
81
|
-
/* @__PURE__ */
|
|
82
|
-
className: "
|
|
83
|
-
children: [
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
246
|
+
/* @__PURE__ */ m("div", {
|
|
247
|
+
className: "space-y-1.5",
|
|
248
|
+
children: [/* @__PURE__ */ p("label", {
|
|
249
|
+
htmlFor: "booking-date",
|
|
250
|
+
className: "text-sm font-medium",
|
|
251
|
+
children: "Date"
|
|
252
|
+
}), /* @__PURE__ */ m("div", {
|
|
253
|
+
className: "relative",
|
|
254
|
+
children: [/* @__PURE__ */ p(a, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ p(w, {
|
|
255
|
+
id: "booking-date",
|
|
256
|
+
type: "date",
|
|
257
|
+
min: F,
|
|
258
|
+
value: I,
|
|
259
|
+
onChange: (e) => L(e.target.value),
|
|
260
|
+
className: "pl-9"
|
|
261
|
+
})]
|
|
262
|
+
})]
|
|
94
263
|
}),
|
|
95
|
-
/* @__PURE__ */
|
|
96
|
-
className: "
|
|
97
|
-
children: [
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
264
|
+
/* @__PURE__ */ m("div", {
|
|
265
|
+
className: "flex items-center justify-between border-t border-border-subtle pt-3",
|
|
266
|
+
children: [/* @__PURE__ */ p("span", {
|
|
267
|
+
className: "text-sm font-medium",
|
|
268
|
+
children: "Total price"
|
|
269
|
+
}), /* @__PURE__ */ m("span", {
|
|
270
|
+
className: "text-lg font-bold tabular-nums",
|
|
271
|
+
children: [
|
|
272
|
+
"$",
|
|
273
|
+
R.price.toLocaleString(),
|
|
274
|
+
/* @__PURE__ */ m("span", {
|
|
275
|
+
className: "text-xs font-normal text-text-secondary",
|
|
276
|
+
children: ["/", R.priceType]
|
|
277
|
+
})
|
|
278
|
+
]
|
|
279
|
+
})]
|
|
108
280
|
}),
|
|
109
|
-
/* @__PURE__ */
|
|
110
|
-
className: "
|
|
111
|
-
children:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
281
|
+
/* @__PURE__ */ m("div", {
|
|
282
|
+
className: "space-y-2",
|
|
283
|
+
children: [/* @__PURE__ */ p(g, {
|
|
284
|
+
className: "w-full",
|
|
285
|
+
disabled: !0,
|
|
286
|
+
title: "Booking is coming soon",
|
|
287
|
+
"aria-label": "Book now — coming soon",
|
|
288
|
+
children: "Book Now · Coming soon"
|
|
289
|
+
}), /* @__PURE__ */ m(g, {
|
|
290
|
+
variant: "outline",
|
|
291
|
+
className: "w-full",
|
|
292
|
+
onClick: () => o("../marketplace/messaging-page"),
|
|
293
|
+
children: [/* @__PURE__ */ p(c, { className: "mr-1 h-4 w-4" }), "Message"]
|
|
294
|
+
})]
|
|
122
295
|
}),
|
|
123
|
-
/* @__PURE__ */
|
|
124
|
-
className:
|
|
125
|
-
children: "
|
|
296
|
+
/* @__PURE__ */ m("p", {
|
|
297
|
+
className: `flex items-center justify-center gap-1.5 text-xs ${z.className}`,
|
|
298
|
+
children: [/* @__PURE__ */ p(B, { className: "h-3.5 w-3.5" }), z.label]
|
|
126
299
|
})
|
|
127
300
|
]
|
|
128
|
-
})
|
|
129
|
-
]
|
|
130
|
-
}),
|
|
131
|
-
/* @__PURE__ */ l(m, { children: [
|
|
132
|
-
/* @__PURE__ */ c("div", {
|
|
133
|
-
className: "mb-2 text-lg font-semibold",
|
|
134
|
-
children: "About this Service"
|
|
135
|
-
}),
|
|
136
|
-
/* @__PURE__ */ c("p", {
|
|
137
|
-
className: "text-sm text-text-secondary",
|
|
138
|
-
children: T.description
|
|
139
|
-
}),
|
|
140
|
-
/* @__PURE__ */ c("div", {
|
|
141
|
-
className: "flex flex-wrap gap-1 mt-3",
|
|
142
|
-
children: T.skills.map((e) => /* @__PURE__ */ c(u, {
|
|
143
|
-
variant: "outline",
|
|
144
|
-
children: e
|
|
145
|
-
}, e))
|
|
301
|
+
})]
|
|
146
302
|
})
|
|
147
|
-
|
|
148
|
-
]
|
|
149
|
-
}) : /* @__PURE__ */ c("div", {
|
|
150
|
-
className: "p-6",
|
|
151
|
-
children: /* @__PURE__ */ c(g, {
|
|
152
|
-
illustration: "empty-search",
|
|
153
|
-
title: "Service not found",
|
|
154
|
-
description: "This service is no longer available."
|
|
155
|
-
})
|
|
303
|
+
})]
|
|
304
|
+
})]
|
|
156
305
|
});
|
|
157
306
|
}
|
|
158
307
|
//#endregion
|
|
159
|
-
export {
|
|
308
|
+
export { O as MarketplaceServiceDetailsPagePage };
|
|
160
309
|
|
|
161
310
|
//# sourceMappingURL=MarketplaceServiceDetailsPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarketplaceServiceDetailsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/MarketplaceServiceDetailsPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n Card,\n CardContent,\n EmphasisPanel,\n GradientText,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n Spinner,\n} from '@burdenoff/fe-libs/ui';\nimport { Clock, DollarSign, MessageSquare, Star, Users } from 'lucide-react';\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function MarketplaceServiceDetailsPagePage() {\n const navigate = useNavigate();\n const location = useLocation();\n const { marketplaceServices, initialized } = useCrewFoundryStore();\n const selectedId = new URLSearchParams(location.search).get('id');\n const svc = marketplaceServices.find((s) => s.id === selectedId) ?? marketplaceServices[0];\n if (!initialized && !svc) {\n return (\n <div className=\"flex min-h-[60vh] items-center justify-center p-6\">\n <Spinner size=\"lg\" />\n </div>\n );\n }\n\n if (!svc)\n return (\n <div className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"Service not found\"\n description=\"This service is no longer available.\"\n />\n </div>\n );\n\n return (\n <div className=\"space-y-6 p-6 max-w-4xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>{svc.title}</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">by {svc.provider}</p>\n <PagePurpose className=\"mt-2\">\n See exactly what this service includes, what it costs, and how others rated it — use it\n to compare offerings and hire the right provider for your project.\n </PagePurpose>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" onClick={() => navigate('../marketplace/messaging-page')}>\n <MessageSquare className=\"h-4 w-4 mr-1\" />\n Contact\n </Button>\n {/* No hire/engagement mutation exists yet, so this stays an honest\n disabled control rather than a silently-dead primary CTA. */}\n <Button disabled title=\"Hiring is coming soon\" aria-label=\"Hire now — coming soon\">\n Hire Now · Coming soon\n </Button>\n </div>\n </div>\n\n <NextSteps\n storageKey=\"crewfoundry-service-details\"\n steps={[\n {\n id: 'contact',\n label: 'Message the provider',\n description: 'Ask questions before you commit to hiring.',\n icon: <MessageSquare className=\"h-4 w-4\" />,\n onClick: () => navigate('../marketplace/messaging-page'),\n },\n {\n id: 'compare',\n label: 'Compare other services',\n description: 'Browse similar offerings on the marketplace.',\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => navigate('../marketplace/marketplace-services-page'),\n },\n {\n id: 'bookings',\n label: 'Manage your bookings',\n description: 'Track engagements you have already arranged.',\n icon: <Clock className=\"h-4 w-4\" />,\n onClick: () => navigate('../marketplace/booking-management-page'),\n },\n ]}\n />\n\n <div className=\"grid gap-4 md:grid-cols-4\">\n <Card>\n <CardContent className=\"p-4 text-center\">\n <DollarSign className=\"h-5 w-5 mx-auto text-text-secondary mb-1\" />\n <p className=\"text-lg font-bold\">${svc.price.toLocaleString()}</p>\n <p className=\"text-xs text-text-secondary\">per {svc.priceType}</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"p-4 text-center\">\n <Star className=\"h-5 w-5 mx-auto text-status-warning-text mb-1\" />\n <p className=\"text-lg font-bold\">{svc.rating}/5</p>\n <p className=\"text-xs text-text-secondary\">{svc.reviews} reviews</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"p-4 text-center\">\n <Clock className=\"h-5 w-5 mx-auto text-text-secondary mb-1\" />\n <p className=\"text-lg font-bold\">{svc.deliveryTime}</p>\n <p className=\"text-xs text-text-secondary\">Delivery</p>\n </CardContent>\n </Card>\n <Card>\n <CardContent className=\"p-4 text-center\">\n <Users className=\"h-5 w-5 mx-auto text-text-secondary mb-1\" />\n <p className=\"text-lg font-bold\">{svc.category}</p>\n <p className=\"text-xs text-text-secondary\">Category</p>\n </CardContent>\n </Card>\n </div>\n <EmphasisPanel>\n <div className=\"mb-2 text-lg font-semibold\">About this Service</div>\n <p className=\"text-sm text-text-secondary\">{svc.description}</p>\n <div className=\"flex flex-wrap gap-1 mt-3\">\n {svc.skills.map((s) => (\n <Badge key={s} variant=\"outline\">\n {s}\n </Badge>\n ))}\n </div>\n </EmphasisPanel>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MarketplaceServiceDetailsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/MarketplaceServiceDetailsPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n EmphasisPanel,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n Spinner,\n} from '@burdenoff/fe-libs/ui';\nimport {\n CalendarDays,\n CheckCircle2,\n Clock3,\n MessageSquare,\n PauseCircle,\n Star,\n} from 'lucide-react';\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore, type MarketplaceService } from '../store/crewfoundryStore';\nimport { RatingStars, getInitials } 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 for new projects',\n icon: CheckCircle2,\n className: 'text-status-success-text',\n };\n case 'pending':\n return { label: 'Pending review', icon: Clock3, className: 'text-status-warning-text' };\n default:\n return { label: 'Not currently available', icon: PauseCircle, className: 'text-text-secondary' };\n }\n}\n\nexport function MarketplaceServiceDetailsPagePage() {\n const navigate = useNavigate();\n const location = useLocation();\n const { marketplaceServices, initialized } = useCrewFoundryStore();\n const selectedId = new URLSearchParams(location.search).get('id');\n const svc = marketplaceServices.find((s) => s.id === selectedId) ?? marketplaceServices[0];\n\n // Real \"packages\": every service this same provider actually offers. The\n // backend exposes a single price per service (no synthetic tiers), so each\n // package is a genuine listing — the viewed service is pre-selected.\n const providerPackages = useMemo(\n () =>\n svc\n ? marketplaceServices.filter((s) => s.provider === svc.provider)\n : ([] as MarketplaceService[]),\n [marketplaceServices, svc]\n );\n\n const [selectedPackageId, setSelectedPackageId] = useState<string | null>(null);\n const today = new Date().toISOString().slice(0, 10);\n const [bookingDate, setBookingDate] = useState(today);\n\n if (!initialized && !svc) {\n return (\n <div className=\"flex min-h-[60vh] items-center justify-center p-6\">\n <Spinner size=\"lg\" />\n </div>\n );\n }\n\n if (!svc) {\n return (\n <div className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"Service not found\"\n description=\"This service is no longer available.\"\n />\n </div>\n );\n }\n\n const selectedPackage = providerPackages.find((p) => p.id === selectedPackageId) ?? svc;\n const availability = availabilityOf(svc.status);\n const AvailabilityIcon = availability.icon;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"text-xs text-text-secondary\">\n <button\n type=\"button\"\n className=\"hover:text-text-primary\"\n onClick={() => navigate('../marketplace/marketplace-page')}\n >\n Marketplace\n </button>\n <span className=\"mx-1\">/</span>\n <span className=\"text-text-primary\">{svc.title}</span>\n </div>\n\n <div className=\"grid gap-6 lg:grid-cols-3\">\n {/* ── Left: provider + service detail ─────────────────────────── */}\n <div className=\"space-y-6 lg:col-span-2\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start\">\n <span\n className=\"flex h-20 w-20 shrink-0 items-center justify-center rounded-full bg-action-primary-bg text-2xl font-semibold text-action-primary-text\"\n aria-hidden=\"true\"\n >\n {getInitials(svc.provider)}\n </span>\n <div className=\"min-w-0 flex-1 space-y-2\">\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>{svc.provider}</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">{svc.title}</p>\n <div className=\"flex flex-wrap items-center gap-3\">\n <RatingStars value={svc.rating} count={svc.reviews} showValue size={16} />\n <span className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Clock3 className=\"h-3 w-3\" />\n {svc.deliveryTime}\n </span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {svc.category}\n </Badge>\n </div>\n <div className=\"flex flex-wrap gap-1.5 pt-1\">\n {svc.skills.map((skill) => (\n <Badge key={skill} variant=\"secondary\" className=\"text-xs\">\n {skill}\n </Badge>\n ))}\n </div>\n </div>\n </div>\n\n <PagePurpose>\n See exactly what this service includes, what it costs, and how others rated it — use the\n booking panel to pick a package and request an engagement.\n </PagePurpose>\n\n <EmphasisPanel>\n <div className=\"mb-2 text-lg font-semibold\">About this service</div>\n <p className=\"text-sm text-text-secondary\">{svc.description}</p>\n </EmphasisPanel>\n\n {/* Services offered — real listings from this provider */}\n <div className=\"space-y-3\">\n <h2 className=\"text-lg font-semibold\">Services offered</h2>\n <div className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {providerPackages.map((pkg) => {\n const active = pkg.id === selectedPackage.id;\n return (\n <button\n key={pkg.id}\n type=\"button\"\n onClick={() => setSelectedPackageId(pkg.id)}\n aria-pressed={active}\n className={`flex flex-col rounded-lg border p-4 text-left transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] ${\n active\n ? 'border-action-primary-bg bg-action-primary-bg/5'\n : 'border-border-subtle hover:bg-bg-sunken/50'\n }`}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"text-sm font-semibold\">{pkg.title}</p>\n <span className=\"whitespace-nowrap text-[11px] text-text-secondary\">\n {pkg.deliveryTime}\n </span>\n </div>\n <p className=\"mt-1 text-xl font-bold tabular-nums\">\n ${pkg.price.toLocaleString()}\n <span className=\"text-xs font-normal text-text-secondary\">/{pkg.priceType}</span>\n </p>\n <p className=\"mt-2 line-clamp-3 text-xs text-text-secondary\">{pkg.description}</p>\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Reviews — backend stores only an aggregate rating + count, not\n individual review bodies, so we report that honestly rather than\n inventing reviewer cards. */}\n <div className=\"space-y-3\">\n <h2 className=\"text-lg font-semibold\">Reviews</h2>\n <Card>\n <CardContent className=\"flex flex-col items-center gap-2 p-6 text-center\">\n <div className=\"flex items-center gap-2\">\n <Star className=\"h-6 w-6 text-status-warning-text\" fill=\"currentColor\" />\n <span className=\"text-2xl font-bold tabular-nums\">{svc.rating.toFixed(1)}</span>\n <span className=\"text-sm text-text-secondary\">/ 5</span>\n </div>\n <p className=\"text-sm text-text-secondary\">\n Based on {svc.reviews.toLocaleString()}{' '}\n {svc.reviews === 1 ? 'review' : 'reviews'}. Individual review notes aren't\n published for this listing yet.\n </p>\n </CardContent>\n </Card>\n </div>\n </div>\n\n {/* ── Right: sticky booking panel ─────────────────────────────── */}\n <div className=\"lg:col-span-1\">\n <Card className=\"lg:sticky lg:top-6\">\n <CardHeader>\n <CardTitle className=\"text-lg\">Book this service</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-5\">\n <fieldset className=\"space-y-2\">\n <legend className=\"mb-1 text-sm font-medium\">Package</legend>\n {providerPackages.map((pkg) => {\n const active = pkg.id === selectedPackage.id;\n return (\n <button\n key={pkg.id}\n type=\"button\"\n onClick={() => setSelectedPackageId(pkg.id)}\n aria-pressed={active}\n className={`flex w-full items-center justify-between gap-3 rounded-lg border px-3 py-2.5 text-left transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] ${\n active\n ? 'border-action-primary-bg bg-action-primary-bg/5'\n : 'border-border-subtle hover:bg-bg-sunken/50'\n }`}\n >\n <span className=\"flex items-center gap-2 min-w-0\">\n <span\n className={`flex h-4 w-4 shrink-0 items-center justify-center rounded-full border ${\n active ? 'border-action-primary-bg' : 'border-border-strong'\n }`}\n aria-hidden=\"true\"\n >\n {active ? (\n <span className=\"h-2 w-2 rounded-full bg-action-primary-bg\" />\n ) : null}\n </span>\n <span className=\"truncate text-sm\">{pkg.title}</span>\n </span>\n <span className=\"whitespace-nowrap text-sm font-semibold tabular-nums\">\n ${pkg.price.toLocaleString()}\n </span>\n </button>\n );\n })}\n </fieldset>\n\n <div className=\"space-y-1.5\">\n <label htmlFor=\"booking-date\" className=\"text-sm font-medium\">\n Date\n </label>\n <div className=\"relative\">\n <CalendarDays className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <Input\n id=\"booking-date\"\n type=\"date\"\n min={today}\n value={bookingDate}\n onChange={(event) => setBookingDate(event.target.value)}\n className=\"pl-9\"\n />\n </div>\n </div>\n\n <div className=\"flex items-center justify-between border-t border-border-subtle pt-3\">\n <span className=\"text-sm font-medium\">Total price</span>\n <span className=\"text-lg font-bold tabular-nums\">\n ${selectedPackage.price.toLocaleString()}\n <span className=\"text-xs font-normal text-text-secondary\">\n /{selectedPackage.priceType}\n </span>\n </span>\n </div>\n\n <div className=\"space-y-2\">\n {/* No createCrewBooking mutation exists in the backend yet, so\n Book Now stays an honest disabled control — the panel is\n fully interactive but does not fake a booking. */}\n <Button\n className=\"w-full\"\n disabled\n title=\"Booking is coming soon\"\n aria-label=\"Book now — coming soon\"\n >\n Book Now · Coming soon\n </Button>\n <Button\n variant=\"outline\"\n className=\"w-full\"\n onClick={() => navigate('../marketplace/messaging-page')}\n >\n <MessageSquare className=\"mr-1 h-4 w-4\" />\n Message\n </Button>\n </div>\n\n <p className={`flex items-center justify-center gap-1.5 text-xs ${availability.className}`}>\n <AvailabilityIcon className=\"h-3.5 w-3.5\" />\n {availability.label}\n </p>\n </CardContent>\n </Card>\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|