@burdenoff/microfe-crewfoundry 2026.704.3 → 2026.704.4
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/pages/AdminAdminPagePage.js +76 -75
- package/dist/crewfoundry/pages/AdminAdminPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +118 -117
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +115 -114
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +105 -104
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js +52 -51
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +94 -93
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js +97 -96
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +68 -67
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js +96 -95
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +153 -152
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +107 -106
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +77 -76
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +80 -79
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +102 -101
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +126 -125
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +64 -63
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +96 -95
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +127 -126
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +118 -117
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +123 -122
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +77 -76
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +49 -48
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +62 -61
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPagePage.js +72 -71
- package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +70 -69
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +57 -56
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +58 -57
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +122 -121
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +70 -69
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +41 -40
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +65 -64
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +75 -74
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +60 -59
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +53 -52
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js +37 -36
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +126 -125
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +62 -61
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js +50 -49
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +72 -71
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +40 -39
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +130 -129
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +60 -59
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js +177 -146
- package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
- package/dist/crewfoundry/utils/formatEnumLabel.js +8 -0
- package/dist/crewfoundry/utils/formatEnumLabel.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import { formatEnumLabel as t } from "../utils/formatEnumLabel.js";
|
|
3
|
+
import { useMemo as n, useState as r } from "react";
|
|
4
|
+
import { Briefcase as i, Calendar as a, DollarSign as o, MessageSquare as s, Star as c, TrendingUp as l, Video as u } from "lucide-react";
|
|
5
|
+
import { useLocation as d, useNavigate as f } from "react-router-dom";
|
|
6
|
+
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
7
|
+
import { Badge as h, Button as g, Card as _, CardContent as v, CardDescription as y, CardHeader as b, CardTitle as x, GlassCard as S, GradientText as C, IllustratedEmptyState as w, NextSteps as T, PagePurpose as E, Separator as D, Tabs as O, TabsContent as k, TabsList as A, TabsTrigger as j } from "@burdenoff/fe-libs/ui";
|
|
7
8
|
//#region src/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.tsx
|
|
8
|
-
var
|
|
9
|
-
function
|
|
10
|
-
let [
|
|
9
|
+
var M = (e) => e.split(" ").map((e) => e[0] ?? "").join("").slice(0, 2).toUpperCase() || "—";
|
|
10
|
+
function N() {
|
|
11
|
+
let [N, P] = r("overview"), F = f(), I = d(), { marketplaceServices: L } = e(), R = new URLSearchParams(I.search).get("id"), z = L.find((e) => e.id === R) ?? L[0], B = z?.provider ?? "", V = n(() => L.filter((e) => e.provider === B), [L, B]), H = n(() => Array.from(new Set(V.flatMap((e) => e.skills))).slice(0, 20), [V]), U = n(() => Array.from(new Set(V.map((e) => e.category))), [V]), W = n(() => V.map((e) => ({
|
|
11
12
|
id: e.id,
|
|
12
13
|
title: e.title,
|
|
13
14
|
price: e.priceType === "hourly" ? `$${e.price}/hr` : e.priceType === "monthly" ? `$${e.price}/mo` : `$${e.price}`,
|
|
@@ -16,111 +17,111 @@ function M() {
|
|
|
16
17
|
delivery: e.deliveryTime,
|
|
17
18
|
rating: e.rating,
|
|
18
19
|
reviews: e.reviews
|
|
19
|
-
})), [
|
|
20
|
+
})), [V]), G = V.length > 0 ? (V.reduce((e, t) => e + t.rating, 0) / V.length).toFixed(1) : "0.0", K = V.reduce((e, t) => e + t.reviews, 0), q = V.length > 0 ? Math.min(...V.map((e) => e.price)) : 0, J = Number(G) >= 4.5 && K > 0, Y = [
|
|
20
21
|
{
|
|
21
22
|
label: "Services",
|
|
22
|
-
value: `${
|
|
23
|
+
value: `${V.length}`
|
|
23
24
|
},
|
|
24
25
|
{
|
|
25
26
|
label: "Avg Rating",
|
|
26
|
-
value:
|
|
27
|
+
value: G
|
|
27
28
|
},
|
|
28
29
|
{
|
|
29
30
|
label: "Total Reviews",
|
|
30
|
-
value: `${
|
|
31
|
+
value: `${K}`
|
|
31
32
|
},
|
|
32
33
|
{
|
|
33
34
|
label: "Starting Rate",
|
|
34
|
-
value: `$${
|
|
35
|
+
value: `$${q.toLocaleString()}`
|
|
35
36
|
}
|
|
36
37
|
];
|
|
37
|
-
return
|
|
38
|
+
return z ? /* @__PURE__ */ m("div", {
|
|
38
39
|
className: "space-y-6 p-6",
|
|
39
40
|
children: [
|
|
40
|
-
/* @__PURE__ */
|
|
41
|
+
/* @__PURE__ */ p(S, {
|
|
41
42
|
treatment: "glass",
|
|
42
43
|
glow: !0,
|
|
43
44
|
className: "border-border-seam",
|
|
44
|
-
children: /* @__PURE__ */
|
|
45
|
+
children: /* @__PURE__ */ p(v, {
|
|
45
46
|
className: "pt-6",
|
|
46
|
-
children: /* @__PURE__ */
|
|
47
|
+
children: /* @__PURE__ */ m("div", {
|
|
47
48
|
className: "flex items-start gap-6",
|
|
48
|
-
children: [/* @__PURE__ */
|
|
49
|
+
children: [/* @__PURE__ */ p("div", {
|
|
49
50
|
className: "flex h-24 w-24 shrink-0 items-center justify-center rounded-2xl bg-gradient-to-br from-primary to-primary/60 text-action-primary-text text-3xl font-semibold",
|
|
50
|
-
children:
|
|
51
|
-
}), /* @__PURE__ */
|
|
51
|
+
children: M(B)
|
|
52
|
+
}), /* @__PURE__ */ m("div", {
|
|
52
53
|
className: "flex-1 space-y-2",
|
|
53
54
|
children: [
|
|
54
|
-
/* @__PURE__ */
|
|
55
|
+
/* @__PURE__ */ m("div", {
|
|
55
56
|
className: "flex items-center gap-3 flex-wrap",
|
|
56
|
-
children: [/* @__PURE__ */
|
|
57
|
+
children: [/* @__PURE__ */ p("h1", {
|
|
57
58
|
className: "text-2xl font-semibold",
|
|
58
|
-
children: /* @__PURE__ */
|
|
59
|
-
}),
|
|
59
|
+
children: /* @__PURE__ */ p(C, { children: B })
|
|
60
|
+
}), J ? /* @__PURE__ */ p(h, { children: "Top Rated" }) : null]
|
|
60
61
|
}),
|
|
61
|
-
/* @__PURE__ */
|
|
62
|
+
/* @__PURE__ */ p("p", {
|
|
62
63
|
className: "text-sm font-medium",
|
|
63
|
-
children:
|
|
64
|
+
children: U.length > 0 ? U.join(" · ") : "Marketplace provider"
|
|
64
65
|
}),
|
|
65
|
-
/* @__PURE__ */
|
|
66
|
+
/* @__PURE__ */ m("div", {
|
|
66
67
|
className: "flex flex-wrap items-center gap-4 text-xs text-text-secondary",
|
|
67
68
|
children: [
|
|
68
|
-
/* @__PURE__ */
|
|
69
|
+
/* @__PURE__ */ m("span", {
|
|
69
70
|
className: "flex items-center gap-1",
|
|
70
71
|
children: [
|
|
71
|
-
/* @__PURE__ */
|
|
72
|
+
/* @__PURE__ */ p(c, { className: "h-3 w-3 text-status-warning-text" }),
|
|
72
73
|
" ",
|
|
73
|
-
W,
|
|
74
|
-
" (",
|
|
75
74
|
G,
|
|
75
|
+
" (",
|
|
76
|
+
K,
|
|
76
77
|
" ",
|
|
77
78
|
"reviews)"
|
|
78
79
|
]
|
|
79
80
|
}),
|
|
80
|
-
/* @__PURE__ */
|
|
81
|
+
/* @__PURE__ */ m("span", {
|
|
81
82
|
className: "flex items-center gap-1",
|
|
82
83
|
children: [
|
|
83
|
-
/* @__PURE__ */
|
|
84
|
+
/* @__PURE__ */ p(i, { className: "h-3 w-3" }),
|
|
84
85
|
" ",
|
|
85
|
-
|
|
86
|
+
V.length,
|
|
86
87
|
" services"
|
|
87
88
|
]
|
|
88
89
|
}),
|
|
89
|
-
/* @__PURE__ */
|
|
90
|
+
/* @__PURE__ */ m("span", {
|
|
90
91
|
className: "flex items-center gap-1",
|
|
91
92
|
children: [
|
|
92
|
-
/* @__PURE__ */
|
|
93
|
+
/* @__PURE__ */ p(o, { className: "h-3 w-3" }),
|
|
93
94
|
" from $",
|
|
94
|
-
|
|
95
|
+
q.toLocaleString()
|
|
95
96
|
]
|
|
96
97
|
})
|
|
97
98
|
]
|
|
98
99
|
}),
|
|
99
|
-
/* @__PURE__ */
|
|
100
|
+
/* @__PURE__ */ m("div", {
|
|
100
101
|
className: "flex gap-2 pt-2 flex-wrap",
|
|
101
102
|
children: [
|
|
102
|
-
/* @__PURE__ */
|
|
103
|
+
/* @__PURE__ */ m(g, {
|
|
103
104
|
size: "sm",
|
|
104
|
-
onClick: () =>
|
|
105
|
-
children: [/* @__PURE__ */
|
|
105
|
+
onClick: () => F("../../marketplace/messaging-page"),
|
|
106
|
+
children: [/* @__PURE__ */ p(s, { className: "h-3 w-3 mr-1" }), " Send Proposal"]
|
|
106
107
|
}),
|
|
107
|
-
/* @__PURE__ */
|
|
108
|
+
/* @__PURE__ */ m(g, {
|
|
108
109
|
size: "sm",
|
|
109
110
|
variant: "outline",
|
|
110
111
|
disabled: !0,
|
|
111
112
|
title: "Video intro is coming soon",
|
|
112
113
|
"aria-label": "Video intro — coming soon",
|
|
113
|
-
children: [/* @__PURE__ */
|
|
114
|
+
children: [/* @__PURE__ */ p(u, { className: "h-3 w-3 mr-1" }), " Video Intro · Coming soon"]
|
|
114
115
|
}),
|
|
115
|
-
/* @__PURE__ */
|
|
116
|
+
/* @__PURE__ */ m(g, {
|
|
116
117
|
size: "sm",
|
|
117
118
|
variant: "outline",
|
|
118
|
-
onClick: () =>
|
|
119
|
-
children: [/* @__PURE__ */
|
|
119
|
+
onClick: () => P("availability"),
|
|
120
|
+
children: [/* @__PURE__ */ p(a, { className: "h-3 w-3 mr-1" }), " Schedule Call"]
|
|
120
121
|
})
|
|
121
122
|
]
|
|
122
123
|
}),
|
|
123
|
-
/* @__PURE__ */
|
|
124
|
+
/* @__PURE__ */ p(E, {
|
|
124
125
|
className: "pt-2",
|
|
125
126
|
children: "A freelancer's full profile — skills, listed services, and performance — so you can vet them thoroughly and decide whether to hire before you reach out."
|
|
126
127
|
})
|
|
@@ -129,111 +130,111 @@ function M() {
|
|
|
129
130
|
})
|
|
130
131
|
})
|
|
131
132
|
}),
|
|
132
|
-
/* @__PURE__ */
|
|
133
|
+
/* @__PURE__ */ p(T, {
|
|
133
134
|
storageKey: "crewfoundry-freelancer-profile-enhanced",
|
|
134
135
|
steps: [
|
|
135
136
|
{
|
|
136
137
|
id: "services",
|
|
137
138
|
label: "Review their services",
|
|
138
139
|
description: "See exactly what this freelancer offers and at what price.",
|
|
139
|
-
icon: /* @__PURE__ */
|
|
140
|
-
onClick: () =>
|
|
140
|
+
icon: /* @__PURE__ */ p(i, { className: "h-4 w-4" }),
|
|
141
|
+
onClick: () => P("services")
|
|
141
142
|
},
|
|
142
143
|
{
|
|
143
144
|
id: "availability",
|
|
144
145
|
label: "Check availability",
|
|
145
146
|
description: "Find open slots before you schedule a call.",
|
|
146
|
-
icon: /* @__PURE__ */
|
|
147
|
-
onClick: () =>
|
|
147
|
+
icon: /* @__PURE__ */ p(a, { className: "h-4 w-4" }),
|
|
148
|
+
onClick: () => P("availability")
|
|
148
149
|
},
|
|
149
150
|
{
|
|
150
151
|
id: "performance",
|
|
151
152
|
label: "Inspect performance",
|
|
152
153
|
description: "Look at ratings and delivery history to reduce risk.",
|
|
153
|
-
icon: /* @__PURE__ */
|
|
154
|
-
onClick: () =>
|
|
154
|
+
icon: /* @__PURE__ */ p(l, { className: "h-4 w-4" }),
|
|
155
|
+
onClick: () => P("analytics")
|
|
155
156
|
}
|
|
156
157
|
]
|
|
157
158
|
}),
|
|
158
|
-
/* @__PURE__ */
|
|
159
|
+
/* @__PURE__ */ p("div", {
|
|
159
160
|
className: "grid gap-4 md:grid-cols-4",
|
|
160
|
-
children:
|
|
161
|
+
children: Y.map((e) => /* @__PURE__ */ p(_, { children: /* @__PURE__ */ m(v, {
|
|
161
162
|
className: "pt-6",
|
|
162
|
-
children: [/* @__PURE__ */
|
|
163
|
+
children: [/* @__PURE__ */ p("p", {
|
|
163
164
|
className: "text-xs text-text-secondary",
|
|
164
165
|
children: e.label
|
|
165
|
-
}), /* @__PURE__ */
|
|
166
|
+
}), /* @__PURE__ */ p("p", {
|
|
166
167
|
className: "text-lg font-bold",
|
|
167
168
|
children: e.value
|
|
168
169
|
})]
|
|
169
170
|
}) }, e.label))
|
|
170
171
|
}),
|
|
171
|
-
/* @__PURE__ */
|
|
172
|
-
value:
|
|
173
|
-
onValueChange:
|
|
172
|
+
/* @__PURE__ */ m(O, {
|
|
173
|
+
value: N,
|
|
174
|
+
onValueChange: P,
|
|
174
175
|
children: [
|
|
175
|
-
/* @__PURE__ */
|
|
176
|
-
/* @__PURE__ */
|
|
176
|
+
/* @__PURE__ */ m(A, { children: [
|
|
177
|
+
/* @__PURE__ */ p(j, {
|
|
177
178
|
value: "overview",
|
|
178
179
|
children: "Overview"
|
|
179
180
|
}),
|
|
180
|
-
/* @__PURE__ */
|
|
181
|
+
/* @__PURE__ */ p(j, {
|
|
181
182
|
value: "services",
|
|
182
183
|
children: "Services"
|
|
183
184
|
}),
|
|
184
|
-
/* @__PURE__ */
|
|
185
|
+
/* @__PURE__ */ p(j, {
|
|
185
186
|
value: "availability",
|
|
186
187
|
children: "Availability"
|
|
187
188
|
}),
|
|
188
|
-
/* @__PURE__ */
|
|
189
|
+
/* @__PURE__ */ p(j, {
|
|
189
190
|
value: "analytics",
|
|
190
191
|
children: "Performance"
|
|
191
192
|
})
|
|
192
193
|
] }),
|
|
193
|
-
/* @__PURE__ */
|
|
194
|
+
/* @__PURE__ */ p(k, {
|
|
194
195
|
value: "overview",
|
|
195
196
|
className: "space-y-6 mt-4",
|
|
196
|
-
children: /* @__PURE__ */
|
|
197
|
+
children: /* @__PURE__ */ m("div", {
|
|
197
198
|
className: "grid gap-6 lg:grid-cols-3",
|
|
198
|
-
children: [/* @__PURE__ */
|
|
199
|
+
children: [/* @__PURE__ */ p("div", {
|
|
199
200
|
className: "lg:col-span-2 space-y-4",
|
|
200
|
-
children: /* @__PURE__ */
|
|
201
|
+
children: /* @__PURE__ */ m(_, { children: [/* @__PURE__ */ p(b, { children: /* @__PURE__ */ p(x, {
|
|
201
202
|
className: "text-base",
|
|
202
203
|
children: "Summary"
|
|
203
|
-
}) }), /* @__PURE__ */
|
|
204
|
+
}) }), /* @__PURE__ */ m(v, {
|
|
204
205
|
className: "text-sm text-text-secondary space-y-3",
|
|
205
|
-
children: [/* @__PURE__ */
|
|
206
|
-
|
|
206
|
+
children: [/* @__PURE__ */ m("p", { children: [
|
|
207
|
+
B,
|
|
207
208
|
" offers ",
|
|
208
|
-
|
|
209
|
+
V.length,
|
|
209
210
|
" ",
|
|
210
|
-
|
|
211
|
+
V.length === 1 ? "service" : "services",
|
|
211
212
|
" on the marketplace",
|
|
212
|
-
|
|
213
|
+
U.length > 0 ? ` across ${U.join(", ")}` : "",
|
|
213
214
|
"."
|
|
214
|
-
] }), /* @__PURE__ */
|
|
215
|
+
] }), /* @__PURE__ */ m("p", { children: [
|
|
215
216
|
"Across all listings the provider holds an average rating of ",
|
|
216
|
-
|
|
217
|
+
G,
|
|
217
218
|
" from",
|
|
218
219
|
" ",
|
|
219
|
-
|
|
220
|
+
K,
|
|
220
221
|
" reviews, with rates starting at $",
|
|
221
|
-
|
|
222
|
+
q.toLocaleString(),
|
|
222
223
|
"."
|
|
223
224
|
] })]
|
|
224
225
|
})] })
|
|
225
|
-
}), /* @__PURE__ */
|
|
226
|
+
}), /* @__PURE__ */ p("div", {
|
|
226
227
|
className: "space-y-4",
|
|
227
|
-
children: /* @__PURE__ */
|
|
228
|
+
children: /* @__PURE__ */ m(_, { children: [/* @__PURE__ */ p(b, { children: /* @__PURE__ */ p(x, {
|
|
228
229
|
className: "text-sm",
|
|
229
230
|
children: "Expertise Areas"
|
|
230
|
-
}) }), /* @__PURE__ */
|
|
231
|
+
}) }), /* @__PURE__ */ p(v, {
|
|
231
232
|
className: "flex flex-wrap gap-1.5",
|
|
232
|
-
children:
|
|
233
|
+
children: H.length > 0 ? H.map((e) => /* @__PURE__ */ p(h, {
|
|
233
234
|
variant: "secondary",
|
|
234
235
|
className: "text-xs",
|
|
235
236
|
children: e
|
|
236
|
-
}, e)) : /* @__PURE__ */
|
|
237
|
+
}, e)) : /* @__PURE__ */ p("p", {
|
|
237
238
|
className: "text-xs text-text-secondary",
|
|
238
239
|
children: "No skills listed yet."
|
|
239
240
|
})
|
|
@@ -241,96 +242,96 @@ function M() {
|
|
|
241
242
|
})]
|
|
242
243
|
})
|
|
243
244
|
}),
|
|
244
|
-
/* @__PURE__ */
|
|
245
|
+
/* @__PURE__ */ p(k, {
|
|
245
246
|
value: "services",
|
|
246
247
|
className: "mt-4",
|
|
247
|
-
children:
|
|
248
|
+
children: W.length > 0 ? /* @__PURE__ */ p("div", {
|
|
248
249
|
className: "grid gap-4 md:grid-cols-2",
|
|
249
|
-
children:
|
|
250
|
+
children: W.map((e) => /* @__PURE__ */ m(_, { children: [/* @__PURE__ */ m(b, { children: [/* @__PURE__ */ m("div", {
|
|
250
251
|
className: "flex items-center justify-between",
|
|
251
|
-
children: [/* @__PURE__ */
|
|
252
|
+
children: [/* @__PURE__ */ p(x, {
|
|
252
253
|
className: "text-sm",
|
|
253
254
|
children: e.title
|
|
254
|
-
}), /* @__PURE__ */
|
|
255
|
+
}), /* @__PURE__ */ p(h, {
|
|
255
256
|
variant: "outline",
|
|
256
257
|
className: "text-xs",
|
|
257
|
-
children: e.type
|
|
258
|
+
children: t(e.type)
|
|
258
259
|
})]
|
|
259
|
-
}), /* @__PURE__ */
|
|
260
|
+
}), /* @__PURE__ */ p(y, {
|
|
260
261
|
className: "text-xs",
|
|
261
262
|
children: e.description
|
|
262
|
-
})] }), /* @__PURE__ */
|
|
263
|
+
})] }), /* @__PURE__ */ m(v, {
|
|
263
264
|
className: "pt-0",
|
|
264
|
-
children: [/* @__PURE__ */
|
|
265
|
+
children: [/* @__PURE__ */ p(D, { className: "mb-3" }), /* @__PURE__ */ m("div", {
|
|
265
266
|
className: "flex items-center justify-between",
|
|
266
|
-
children: [/* @__PURE__ */
|
|
267
|
+
children: [/* @__PURE__ */ m("div", {
|
|
267
268
|
className: "space-y-0.5",
|
|
268
|
-
children: [/* @__PURE__ */
|
|
269
|
+
children: [/* @__PURE__ */ p("p", {
|
|
269
270
|
className: "text-sm font-semibold",
|
|
270
271
|
children: e.price
|
|
271
|
-
}), /* @__PURE__ */
|
|
272
|
+
}), /* @__PURE__ */ m("p", {
|
|
272
273
|
className: "text-[10px] text-text-secondary",
|
|
273
274
|
children: ["Delivery: ", e.delivery]
|
|
274
275
|
})]
|
|
275
|
-
}), /* @__PURE__ */
|
|
276
|
+
}), /* @__PURE__ */ p(g, {
|
|
276
277
|
size: "sm",
|
|
277
278
|
variant: "outline",
|
|
278
|
-
onClick: () =>
|
|
279
|
+
onClick: () => F(`../../marketplace/service-details-page?id=${e.id}`),
|
|
279
280
|
children: "View"
|
|
280
281
|
})]
|
|
281
282
|
})]
|
|
282
283
|
})] }, e.id))
|
|
283
|
-
}) : /* @__PURE__ */
|
|
284
|
+
}) : /* @__PURE__ */ p(w, {
|
|
284
285
|
illustration: "empty-generic",
|
|
285
286
|
title: "No services listed",
|
|
286
287
|
description: "This provider has not published any services yet."
|
|
287
288
|
})
|
|
288
289
|
}),
|
|
289
|
-
/* @__PURE__ */
|
|
290
|
+
/* @__PURE__ */ p(k, {
|
|
290
291
|
value: "availability",
|
|
291
292
|
className: "mt-4",
|
|
292
|
-
children: /* @__PURE__ */
|
|
293
|
+
children: /* @__PURE__ */ m(_, { children: [/* @__PURE__ */ m(b, { children: [/* @__PURE__ */ p(x, {
|
|
293
294
|
className: "text-base",
|
|
294
295
|
children: "Availability"
|
|
295
|
-
}), /* @__PURE__ */
|
|
296
|
+
}), /* @__PURE__ */ p(y, { children: "Real-time scheduling with this provider" })] }), /* @__PURE__ */ p(v, { children: /* @__PURE__ */ p(w, {
|
|
296
297
|
illustration: "empty-generic",
|
|
297
298
|
title: "Scheduling is coming soon",
|
|
298
299
|
description: "Live availability and consultation booking will appear here once the scheduling backend ships. In the meantime, send a message to arrange a time.",
|
|
299
|
-
action: /* @__PURE__ */
|
|
300
|
+
action: /* @__PURE__ */ m(g, {
|
|
300
301
|
size: "sm",
|
|
301
|
-
onClick: () =>
|
|
302
|
-
children: [/* @__PURE__ */
|
|
302
|
+
onClick: () => F("../../marketplace/messaging-page"),
|
|
303
|
+
children: [/* @__PURE__ */ p(s, { className: "h-3 w-3 mr-1" }), " Message provider"]
|
|
303
304
|
})
|
|
304
305
|
}) })] })
|
|
305
306
|
}),
|
|
306
|
-
/* @__PURE__ */
|
|
307
|
+
/* @__PURE__ */ p(k, {
|
|
307
308
|
value: "analytics",
|
|
308
309
|
className: "mt-4",
|
|
309
|
-
children: /* @__PURE__ */
|
|
310
|
+
children: /* @__PURE__ */ m(_, { children: [/* @__PURE__ */ m(b, { children: [/* @__PURE__ */ p(x, {
|
|
310
311
|
className: "text-base",
|
|
311
312
|
children: "Service Performance"
|
|
312
|
-
}), /* @__PURE__ */
|
|
313
|
+
}), /* @__PURE__ */ p(y, { children: "Ratings and reviews per listed service" })] }), /* @__PURE__ */ p(v, {
|
|
313
314
|
className: "space-y-3",
|
|
314
|
-
children:
|
|
315
|
+
children: V.length > 0 ? V.map((e) => /* @__PURE__ */ m("div", {
|
|
315
316
|
className: "flex items-center justify-between",
|
|
316
|
-
children: [/* @__PURE__ */
|
|
317
|
+
children: [/* @__PURE__ */ m("div", {
|
|
317
318
|
className: "min-w-0",
|
|
318
|
-
children: [/* @__PURE__ */
|
|
319
|
+
children: [/* @__PURE__ */ p("p", {
|
|
319
320
|
className: "text-sm font-medium truncate",
|
|
320
321
|
children: e.title
|
|
321
|
-
}), /* @__PURE__ */
|
|
322
|
+
}), /* @__PURE__ */ p("p", {
|
|
322
323
|
className: "text-xs text-text-secondary",
|
|
323
324
|
children: e.category
|
|
324
325
|
})]
|
|
325
|
-
}), /* @__PURE__ */
|
|
326
|
+
}), /* @__PURE__ */ m("div", {
|
|
326
327
|
className: "flex items-center gap-2 text-sm shrink-0",
|
|
327
328
|
children: [
|
|
328
|
-
/* @__PURE__ */
|
|
329
|
-
/* @__PURE__ */
|
|
329
|
+
/* @__PURE__ */ p(c, { className: "h-3.5 w-3.5 text-status-warning-text" }),
|
|
330
|
+
/* @__PURE__ */ p("span", {
|
|
330
331
|
className: "font-semibold",
|
|
331
332
|
children: e.rating
|
|
332
333
|
}),
|
|
333
|
-
/* @__PURE__ */
|
|
334
|
+
/* @__PURE__ */ m("span", {
|
|
334
335
|
className: "text-xs text-text-secondary",
|
|
335
336
|
children: [
|
|
336
337
|
"(",
|
|
@@ -340,7 +341,7 @@ function M() {
|
|
|
340
341
|
})
|
|
341
342
|
]
|
|
342
343
|
})]
|
|
343
|
-
}, e.id)) : /* @__PURE__ */
|
|
344
|
+
}, e.id)) : /* @__PURE__ */ p("p", {
|
|
344
345
|
className: "text-sm text-text-secondary",
|
|
345
346
|
children: "No performance data yet."
|
|
346
347
|
})
|
|
@@ -349,9 +350,9 @@ function M() {
|
|
|
349
350
|
]
|
|
350
351
|
})
|
|
351
352
|
]
|
|
352
|
-
}) : /* @__PURE__ */
|
|
353
|
+
}) : /* @__PURE__ */ p("div", {
|
|
353
354
|
className: "p-6",
|
|
354
|
-
children: /* @__PURE__ */
|
|
355
|
+
children: /* @__PURE__ */ p(w, {
|
|
355
356
|
illustration: "empty-search",
|
|
356
357
|
title: "Provider not found",
|
|
357
358
|
description: "This freelancer is no longer available on the marketplace."
|
|
@@ -359,6 +360,6 @@ function M() {
|
|
|
359
360
|
});
|
|
360
361
|
}
|
|
361
362
|
//#endregion
|
|
362
|
-
export {
|
|
363
|
+
export { N as MarketplaceFreelancerProfilePageEnhancedPage };
|
|
363
364
|
|
|
364
365
|
//# sourceMappingURL=MarketplaceFreelancerProfilePageEnhancedPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarketplaceFreelancerProfilePageEnhancedPage.js","names":[],"sources":["../../../src/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n Separator,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Briefcase,\n Calendar,\n DollarSign,\n MessageSquare,\n Star,\n TrendingUp,\n Video,\n} from 'lucide-react';\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nconst initialsOf = (name: string): string =>\n name\n .split(' ')\n .map((part) => part[0] ?? '')\n .join('')\n .slice(0, 2)\n .toUpperCase() || '—';\n\nexport function MarketplaceFreelancerProfilePageEnhancedPage() {\n const [selectedTab, setSelectedTab] = useState('overview');\n const navigate = useNavigate();\n const location = useLocation();\n const { marketplaceServices } = useCrewFoundryStore();\n const selectedId = new URLSearchParams(location.search).get('id');\n\n const baseService =\n marketplaceServices.find((service) => service.id === selectedId) ?? marketplaceServices[0];\n const providerName = baseService?.provider ?? '';\n\n const providerServices = useMemo(\n () => marketplaceServices.filter((service) => service.provider === providerName),\n [marketplaceServices, providerName]\n );\n\n const skills = useMemo(\n () => Array.from(new Set(providerServices.flatMap((service) => service.skills))).slice(0, 20),\n [providerServices]\n );\n\n const categories = useMemo(\n () => Array.from(new Set(providerServices.map((service) => service.category))),\n [providerServices]\n );\n\n const services = useMemo(\n () =>\n providerServices.map((service) => ({\n id: service.id,\n title: service.title,\n price:\n service.priceType === 'hourly'\n ? `$${service.price}/hr`\n : service.priceType === 'monthly'\n ? `$${service.price}/mo`\n : `$${service.price}`,\n type: service.priceType,\n description: service.description,\n delivery: service.deliveryTime,\n rating: service.rating,\n reviews: service.reviews,\n })),\n [providerServices]\n );\n\n const avgRating =\n providerServices.length > 0\n ? (\n providerServices.reduce((sum, service) => sum + service.rating, 0) /\n providerServices.length\n ).toFixed(1)\n : '0.0';\n const totalReviews = providerServices.reduce((sum, service) => sum + service.reviews, 0);\n const startingRate =\n providerServices.length > 0 ? Math.min(...providerServices.map((service) => service.price)) : 0;\n const isTopRated = Number(avgRating) >= 4.5 && totalReviews > 0;\n\n const stats = [\n { label: 'Services', value: `${providerServices.length}` },\n { label: 'Avg Rating', value: avgRating },\n { label: 'Total Reviews', value: `${totalReviews}` },\n { label: 'Starting Rate', value: `$${startingRate.toLocaleString()}` },\n ];\n\n if (!baseService) {\n return (\n <div className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"Provider not found\"\n description=\"This freelancer is no longer available on the marketplace.\"\n />\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardContent className=\"pt-6\">\n <div className=\"flex items-start gap-6\">\n <div className=\"flex h-24 w-24 shrink-0 items-center justify-center rounded-2xl bg-gradient-to-br from-primary to-primary/60 text-action-primary-text text-3xl font-semibold\">\n {initialsOf(providerName)}\n </div>\n <div className=\"flex-1 space-y-2\">\n <div className=\"flex items-center gap-3 flex-wrap\">\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>{providerName}</GradientText>\n </h1>\n {isTopRated ? <Badge>Top Rated</Badge> : null}\n </div>\n <p className=\"text-sm font-medium\">\n {categories.length > 0 ? categories.join(' · ') : 'Marketplace provider'}\n </p>\n <div className=\"flex flex-wrap items-center gap-4 text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" /> {avgRating} ({totalReviews}{' '}\n reviews)\n </span>\n <span className=\"flex items-center gap-1\">\n <Briefcase className=\"h-3 w-3\" /> {providerServices.length} services\n </span>\n <span className=\"flex items-center gap-1\">\n <DollarSign className=\"h-3 w-3\" /> from ${startingRate.toLocaleString()}\n </span>\n </div>\n <div className=\"flex gap-2 pt-2 flex-wrap\">\n <Button size=\"sm\" onClick={() => navigate('../../marketplace/messaging-page')}>\n <MessageSquare className=\"h-3 w-3 mr-1\" /> Send Proposal\n </Button>\n {/* No video-intro/call surface exists yet — honest disabled control. */}\n <Button\n size=\"sm\"\n variant=\"outline\"\n disabled\n title=\"Video intro is coming soon\"\n aria-label=\"Video intro — coming soon\"\n >\n <Video className=\"h-3 w-3 mr-1\" /> Video Intro · Coming soon\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => setSelectedTab('availability')}>\n <Calendar className=\"h-3 w-3 mr-1\" /> Schedule Call\n </Button>\n </div>\n <PagePurpose className=\"pt-2\">\n A freelancer's full profile — skills, listed services, and performance — so you\n can vet them thoroughly and decide whether to hire before you reach out.\n </PagePurpose>\n </div>\n </div>\n </CardContent>\n </GlassCard>\n\n <NextSteps\n storageKey=\"crewfoundry-freelancer-profile-enhanced\"\n steps={[\n {\n id: 'services',\n label: 'Review their services',\n description: 'See exactly what this freelancer offers and at what price.',\n icon: <Briefcase className=\"h-4 w-4\" />,\n onClick: () => setSelectedTab('services'),\n },\n {\n id: 'availability',\n label: 'Check availability',\n description: 'Find open slots before you schedule a call.',\n icon: <Calendar className=\"h-4 w-4\" />,\n onClick: () => setSelectedTab('availability'),\n },\n {\n id: 'performance',\n label: 'Inspect performance',\n description: 'Look at ratings and delivery history to reduce risk.',\n icon: <TrendingUp className=\"h-4 w-4\" />,\n onClick: () => setSelectedTab('analytics'),\n },\n ]}\n />\n\n <div className=\"grid gap-4 md:grid-cols-4\">\n {stats.map((stat) => (\n <Card key={stat.label}>\n <CardContent className=\"pt-6\">\n <p className=\"text-xs text-text-secondary\">{stat.label}</p>\n <p className=\"text-lg font-bold\">{stat.value}</p>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <Tabs value={selectedTab} onValueChange={setSelectedTab}>\n <TabsList>\n <TabsTrigger value=\"overview\">Overview</TabsTrigger>\n <TabsTrigger value=\"services\">Services</TabsTrigger>\n <TabsTrigger value=\"availability\">Availability</TabsTrigger>\n <TabsTrigger value=\"analytics\">Performance</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"overview\" className=\"space-y-6 mt-4\">\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <div className=\"lg:col-span-2 space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Summary</CardTitle>\n </CardHeader>\n <CardContent className=\"text-sm text-text-secondary space-y-3\">\n <p>\n {providerName} offers {providerServices.length}{' '}\n {providerServices.length === 1 ? 'service' : 'services'} on the marketplace\n {categories.length > 0 ? ` across ${categories.join(', ')}` : ''}.\n </p>\n <p>\n Across all listings the provider holds an average rating of {avgRating} from{' '}\n {totalReviews} reviews, with rates starting at ${startingRate.toLocaleString()}.\n </p>\n </CardContent>\n </Card>\n </div>\n <div className=\"space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">Expertise Areas</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-wrap gap-1.5\">\n {skills.length > 0 ? (\n skills.map((s) => (\n <Badge key={s} variant=\"secondary\" className=\"text-xs\">\n {s}\n </Badge>\n ))\n ) : (\n <p className=\"text-xs text-text-secondary\">No skills listed yet.</p>\n )}\n </CardContent>\n </Card>\n </div>\n </div>\n </TabsContent>\n\n <TabsContent value=\"services\" className=\"mt-4\">\n {services.length > 0 ? (\n <div className=\"grid gap-4 md:grid-cols-2\">\n {services.map((svc) => (\n <Card key={svc.id}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-sm\">{svc.title}</CardTitle>\n <Badge variant=\"outline\" className=\"text-xs\">\n {svc.type}\n </Badge>\n </div>\n <CardDescription className=\"text-xs\">{svc.description}</CardDescription>\n </CardHeader>\n <CardContent className=\"pt-0\">\n <Separator className=\"mb-3\" />\n <div className=\"flex items-center justify-between\">\n <div className=\"space-y-0.5\">\n <p className=\"text-sm font-semibold\">{svc.price}</p>\n <p className=\"text-[10px] text-text-secondary\">Delivery: {svc.delivery}</p>\n </div>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() =>\n navigate(`../../marketplace/service-details-page?id=${svc.id}`)\n }\n >\n View\n </Button>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n ) : (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No services listed\"\n description=\"This provider has not published any services yet.\"\n />\n )}\n </TabsContent>\n\n <TabsContent value=\"availability\" className=\"mt-4\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Availability</CardTitle>\n <CardDescription>Real-time scheduling with this provider</CardDescription>\n </CardHeader>\n <CardContent>\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"Scheduling is coming soon\"\n description=\"Live availability and consultation booking will appear here once the scheduling backend ships. In the meantime, send a message to arrange a time.\"\n action={\n <Button size=\"sm\" onClick={() => navigate('../../marketplace/messaging-page')}>\n <MessageSquare className=\"h-3 w-3 mr-1\" /> Message provider\n </Button>\n }\n />\n </CardContent>\n </Card>\n </TabsContent>\n\n <TabsContent value=\"analytics\" className=\"mt-4\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Service Performance</CardTitle>\n <CardDescription>Ratings and reviews per listed service</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {providerServices.length > 0 ? (\n providerServices.map((service) => (\n <div key={service.id} className=\"flex items-center justify-between\">\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium truncate\">{service.title}</p>\n <p className=\"text-xs text-text-secondary\">{service.category}</p>\n </div>\n <div className=\"flex items-center gap-2 text-sm shrink-0\">\n <Star className=\"h-3.5 w-3.5 text-status-warning-text\" />\n <span className=\"font-semibold\">{service.rating}</span>\n <span className=\"text-xs text-text-secondary\">({service.reviews})</span>\n </div>\n </div>\n ))\n ) : (\n <p className=\"text-sm text-text-secondary\">No performance data yet.</p>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MarketplaceFreelancerProfilePageEnhancedPage.js","names":[],"sources":["../../../src/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n Separator,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Briefcase,\n Calendar,\n DollarSign,\n MessageSquare,\n Star,\n TrendingUp,\n Video,\n} from 'lucide-react';\nimport { useLocation, useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\n\nconst initialsOf = (name: string): string =>\n name\n .split(' ')\n .map((part) => part[0] ?? '')\n .join('')\n .slice(0, 2)\n .toUpperCase() || '—';\n\nexport function MarketplaceFreelancerProfilePageEnhancedPage() {\n const [selectedTab, setSelectedTab] = useState('overview');\n const navigate = useNavigate();\n const location = useLocation();\n const { marketplaceServices } = useCrewFoundryStore();\n const selectedId = new URLSearchParams(location.search).get('id');\n\n const baseService =\n marketplaceServices.find((service) => service.id === selectedId) ?? marketplaceServices[0];\n const providerName = baseService?.provider ?? '';\n\n const providerServices = useMemo(\n () => marketplaceServices.filter((service) => service.provider === providerName),\n [marketplaceServices, providerName]\n );\n\n const skills = useMemo(\n () => Array.from(new Set(providerServices.flatMap((service) => service.skills))).slice(0, 20),\n [providerServices]\n );\n\n const categories = useMemo(\n () => Array.from(new Set(providerServices.map((service) => service.category))),\n [providerServices]\n );\n\n const services = useMemo(\n () =>\n providerServices.map((service) => ({\n id: service.id,\n title: service.title,\n price:\n service.priceType === 'hourly'\n ? `$${service.price}/hr`\n : service.priceType === 'monthly'\n ? `$${service.price}/mo`\n : `$${service.price}`,\n type: service.priceType,\n description: service.description,\n delivery: service.deliveryTime,\n rating: service.rating,\n reviews: service.reviews,\n })),\n [providerServices]\n );\n\n const avgRating =\n providerServices.length > 0\n ? (\n providerServices.reduce((sum, service) => sum + service.rating, 0) /\n providerServices.length\n ).toFixed(1)\n : '0.0';\n const totalReviews = providerServices.reduce((sum, service) => sum + service.reviews, 0);\n const startingRate =\n providerServices.length > 0 ? Math.min(...providerServices.map((service) => service.price)) : 0;\n const isTopRated = Number(avgRating) >= 4.5 && totalReviews > 0;\n\n const stats = [\n { label: 'Services', value: `${providerServices.length}` },\n { label: 'Avg Rating', value: avgRating },\n { label: 'Total Reviews', value: `${totalReviews}` },\n { label: 'Starting Rate', value: `$${startingRate.toLocaleString()}` },\n ];\n\n if (!baseService) {\n return (\n <div className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"Provider not found\"\n description=\"This freelancer is no longer available on the marketplace.\"\n />\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardContent className=\"pt-6\">\n <div className=\"flex items-start gap-6\">\n <div className=\"flex h-24 w-24 shrink-0 items-center justify-center rounded-2xl bg-gradient-to-br from-primary to-primary/60 text-action-primary-text text-3xl font-semibold\">\n {initialsOf(providerName)}\n </div>\n <div className=\"flex-1 space-y-2\">\n <div className=\"flex items-center gap-3 flex-wrap\">\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>{providerName}</GradientText>\n </h1>\n {isTopRated ? <Badge>Top Rated</Badge> : null}\n </div>\n <p className=\"text-sm font-medium\">\n {categories.length > 0 ? categories.join(' · ') : 'Marketplace provider'}\n </p>\n <div className=\"flex flex-wrap items-center gap-4 text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" /> {avgRating} ({totalReviews}{' '}\n reviews)\n </span>\n <span className=\"flex items-center gap-1\">\n <Briefcase className=\"h-3 w-3\" /> {providerServices.length} services\n </span>\n <span className=\"flex items-center gap-1\">\n <DollarSign className=\"h-3 w-3\" /> from ${startingRate.toLocaleString()}\n </span>\n </div>\n <div className=\"flex gap-2 pt-2 flex-wrap\">\n <Button size=\"sm\" onClick={() => navigate('../../marketplace/messaging-page')}>\n <MessageSquare className=\"h-3 w-3 mr-1\" /> Send Proposal\n </Button>\n {/* No video-intro/call surface exists yet — honest disabled control. */}\n <Button\n size=\"sm\"\n variant=\"outline\"\n disabled\n title=\"Video intro is coming soon\"\n aria-label=\"Video intro — coming soon\"\n >\n <Video className=\"h-3 w-3 mr-1\" /> Video Intro · Coming soon\n </Button>\n <Button size=\"sm\" variant=\"outline\" onClick={() => setSelectedTab('availability')}>\n <Calendar className=\"h-3 w-3 mr-1\" /> Schedule Call\n </Button>\n </div>\n <PagePurpose className=\"pt-2\">\n A freelancer's full profile — skills, listed services, and performance — so you\n can vet them thoroughly and decide whether to hire before you reach out.\n </PagePurpose>\n </div>\n </div>\n </CardContent>\n </GlassCard>\n\n <NextSteps\n storageKey=\"crewfoundry-freelancer-profile-enhanced\"\n steps={[\n {\n id: 'services',\n label: 'Review their services',\n description: 'See exactly what this freelancer offers and at what price.',\n icon: <Briefcase className=\"h-4 w-4\" />,\n onClick: () => setSelectedTab('services'),\n },\n {\n id: 'availability',\n label: 'Check availability',\n description: 'Find open slots before you schedule a call.',\n icon: <Calendar className=\"h-4 w-4\" />,\n onClick: () => setSelectedTab('availability'),\n },\n {\n id: 'performance',\n label: 'Inspect performance',\n description: 'Look at ratings and delivery history to reduce risk.',\n icon: <TrendingUp className=\"h-4 w-4\" />,\n onClick: () => setSelectedTab('analytics'),\n },\n ]}\n />\n\n <div className=\"grid gap-4 md:grid-cols-4\">\n {stats.map((stat) => (\n <Card key={stat.label}>\n <CardContent className=\"pt-6\">\n <p className=\"text-xs text-text-secondary\">{stat.label}</p>\n <p className=\"text-lg font-bold\">{stat.value}</p>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <Tabs value={selectedTab} onValueChange={setSelectedTab}>\n <TabsList>\n <TabsTrigger value=\"overview\">Overview</TabsTrigger>\n <TabsTrigger value=\"services\">Services</TabsTrigger>\n <TabsTrigger value=\"availability\">Availability</TabsTrigger>\n <TabsTrigger value=\"analytics\">Performance</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"overview\" className=\"space-y-6 mt-4\">\n <div className=\"grid gap-6 lg:grid-cols-3\">\n <div className=\"lg:col-span-2 space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Summary</CardTitle>\n </CardHeader>\n <CardContent className=\"text-sm text-text-secondary space-y-3\">\n <p>\n {providerName} offers {providerServices.length}{' '}\n {providerServices.length === 1 ? 'service' : 'services'} on the marketplace\n {categories.length > 0 ? ` across ${categories.join(', ')}` : ''}.\n </p>\n <p>\n Across all listings the provider holds an average rating of {avgRating} from{' '}\n {totalReviews} reviews, with rates starting at ${startingRate.toLocaleString()}.\n </p>\n </CardContent>\n </Card>\n </div>\n <div className=\"space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-sm\">Expertise Areas</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-wrap gap-1.5\">\n {skills.length > 0 ? (\n skills.map((s) => (\n <Badge key={s} variant=\"secondary\" className=\"text-xs\">\n {s}\n </Badge>\n ))\n ) : (\n <p className=\"text-xs text-text-secondary\">No skills listed yet.</p>\n )}\n </CardContent>\n </Card>\n </div>\n </div>\n </TabsContent>\n\n <TabsContent value=\"services\" className=\"mt-4\">\n {services.length > 0 ? (\n <div className=\"grid gap-4 md:grid-cols-2\">\n {services.map((svc) => (\n <Card key={svc.id}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-sm\">{svc.title}</CardTitle>\n <Badge variant=\"outline\" className=\"text-xs\">\n {formatEnumLabel(svc.type)}\n </Badge>\n </div>\n <CardDescription className=\"text-xs\">{svc.description}</CardDescription>\n </CardHeader>\n <CardContent className=\"pt-0\">\n <Separator className=\"mb-3\" />\n <div className=\"flex items-center justify-between\">\n <div className=\"space-y-0.5\">\n <p className=\"text-sm font-semibold\">{svc.price}</p>\n <p className=\"text-[10px] text-text-secondary\">Delivery: {svc.delivery}</p>\n </div>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() =>\n navigate(`../../marketplace/service-details-page?id=${svc.id}`)\n }\n >\n View\n </Button>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n ) : (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No services listed\"\n description=\"This provider has not published any services yet.\"\n />\n )}\n </TabsContent>\n\n <TabsContent value=\"availability\" className=\"mt-4\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Availability</CardTitle>\n <CardDescription>Real-time scheduling with this provider</CardDescription>\n </CardHeader>\n <CardContent>\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"Scheduling is coming soon\"\n description=\"Live availability and consultation booking will appear here once the scheduling backend ships. In the meantime, send a message to arrange a time.\"\n action={\n <Button size=\"sm\" onClick={() => navigate('../../marketplace/messaging-page')}>\n <MessageSquare className=\"h-3 w-3 mr-1\" /> Message provider\n </Button>\n }\n />\n </CardContent>\n </Card>\n </TabsContent>\n\n <TabsContent value=\"analytics\" className=\"mt-4\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Service Performance</CardTitle>\n <CardDescription>Ratings and reviews per listed service</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {providerServices.length > 0 ? (\n providerServices.map((service) => (\n <div key={service.id} className=\"flex items-center justify-between\">\n <div className=\"min-w-0\">\n <p className=\"text-sm font-medium truncate\">{service.title}</p>\n <p className=\"text-xs text-text-secondary\">{service.category}</p>\n </div>\n <div className=\"flex items-center gap-2 text-sm shrink-0\">\n <Star className=\"h-3.5 w-3.5 text-status-warning-text\" />\n <span className=\"font-semibold\">{service.rating}</span>\n <span className=\"text-xs text-text-secondary\">({service.reviews})</span>\n </div>\n </div>\n ))\n ) : (\n <p className=\"text-sm text-text-secondary\">No performance data yet.</p>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
|