@burdenoff/microfe-crewfoundry 2026.703.2 → 2026.704.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.
- package/dist/crewfoundry/pages/AdminAdminPagePage.js +117 -164
- package/dist/crewfoundry/pages/AdminAdminPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +99 -82
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +160 -192
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +238 -231
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +196 -166
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +45 -147
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js +20 -11
- package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js +45 -152
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +50 -138
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js +149 -67
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +50 -201
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +205 -136
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js +25 -31
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js +118 -104
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +117 -58
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js +90 -94
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +210 -191
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +213 -180
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js +133 -264
- package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js.map +1 -1
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js +279 -212
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +131 -105
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +167 -148
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +3 -3
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +13 -5
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +151 -152
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +38 -21
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +3 -3
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js +134 -127
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +163 -132
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +202 -160
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +104 -91
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +29 -147
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +22 -106
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +74 -74
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +101 -97
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +64 -47
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js +111 -121
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPagePage.js +131 -110
- package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +65 -64
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +58 -43
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +66 -82
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +38 -88
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +59 -65
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +209 -323
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +175 -220
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +74 -59
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +96 -80
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js +28 -100
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +27 -20
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +73 -73
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +62 -56
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js +40 -138
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +126 -93
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +99 -77
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js +73 -74
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +1 -1
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +122 -122
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +130 -113
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js +68 -59
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +73 -62
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +82 -58
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +153 -153
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +63 -48
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,11 +4,12 @@ import { ConfirmDialog as n } from "../components/forms/ConfirmDialog.js";
|
|
|
4
4
|
import { getNumber as r, getTags as i, getText as a, newClientId as o } from "../components/forms/formValues.js";
|
|
5
5
|
import { useState as s } from "react";
|
|
6
6
|
import { Pencil as c, Plus as l, Search as u, Star as d, Trash2 as f } from "lucide-react";
|
|
7
|
-
import {
|
|
8
|
-
import { Badge as
|
|
9
|
-
import {
|
|
7
|
+
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
8
|
+
import { Badge as h, Button as g, CardContent as _, GlassCard as v, GradientText as y, IllustratedEmptyState as b, Input as x, PagePurpose as S, Pagination as C, ResponsiveTable as w } from "@burdenoff/fe-libs/ui";
|
|
9
|
+
import { usePagination as T } from "@burdenoff/fe-libs/shared/hooks";
|
|
10
|
+
import { useGlobalUi as E } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
10
11
|
//#region src/crewfoundry/pages/HiringCandidatesPagePage.tsx
|
|
11
|
-
var
|
|
12
|
+
var D = [
|
|
12
13
|
{
|
|
13
14
|
name: "firstName",
|
|
14
15
|
label: "First Name",
|
|
@@ -120,7 +121,7 @@ var T = [
|
|
|
120
121
|
type: "textarea",
|
|
121
122
|
colSpan: 2
|
|
122
123
|
}
|
|
123
|
-
],
|
|
124
|
+
], O = (e) => ({
|
|
124
125
|
firstName: e.firstName,
|
|
125
126
|
lastName: e.lastName,
|
|
126
127
|
email: e.email,
|
|
@@ -135,7 +136,7 @@ var T = [
|
|
|
135
136
|
resumeUrl: e.resumeUrl ?? "",
|
|
136
137
|
skills: e.skills,
|
|
137
138
|
notes: e.notes
|
|
138
|
-
}),
|
|
139
|
+
}), k = (e) => {
|
|
139
140
|
let t = a(e, "appliedDate");
|
|
140
141
|
return {
|
|
141
142
|
firstName: a(e, "firstName"),
|
|
@@ -153,206 +154,224 @@ var T = [
|
|
|
153
154
|
skills: i(e, "skills"),
|
|
154
155
|
notes: a(e, "notes")
|
|
155
156
|
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
}, A = [
|
|
158
|
+
{
|
|
159
|
+
key: "name",
|
|
160
|
+
header: "Name",
|
|
161
|
+
priority: "primary",
|
|
162
|
+
cell: (e) => /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ m("p", {
|
|
163
|
+
className: "font-medium",
|
|
164
|
+
children: [
|
|
165
|
+
e.firstName,
|
|
166
|
+
" ",
|
|
167
|
+
e.lastName
|
|
168
|
+
]
|
|
169
|
+
}), /* @__PURE__ */ p("p", {
|
|
170
|
+
className: "text-xs text-text-secondary",
|
|
171
|
+
children: e.email
|
|
172
|
+
})] })
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
key: "position",
|
|
176
|
+
header: "Position",
|
|
177
|
+
priority: "secondary",
|
|
178
|
+
cell: (e) => /* @__PURE__ */ p("span", {
|
|
179
|
+
className: "text-text-secondary",
|
|
180
|
+
children: e.position
|
|
181
|
+
})
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
key: "source",
|
|
185
|
+
header: "Source",
|
|
186
|
+
priority: "secondary",
|
|
187
|
+
cell: (e) => /* @__PURE__ */ p(h, {
|
|
188
|
+
variant: "outline",
|
|
189
|
+
className: "w-fit h-fit text-[10px]",
|
|
190
|
+
children: e.source
|
|
191
|
+
})
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
key: "experience",
|
|
195
|
+
header: "Experience",
|
|
196
|
+
priority: "secondary",
|
|
197
|
+
cell: (e) => /* @__PURE__ */ m("span", { children: [e.experience, " yrs"] })
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
key: "rating",
|
|
201
|
+
header: "Rating",
|
|
202
|
+
priority: "secondary",
|
|
203
|
+
cell: (e) => /* @__PURE__ */ m("span", {
|
|
204
|
+
className: "flex items-center gap-1",
|
|
205
|
+
children: [/* @__PURE__ */ p(d, { className: "h-3 w-3 text-status-warning-text" }), e.rating]
|
|
206
|
+
})
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
key: "applied",
|
|
210
|
+
header: "Applied",
|
|
211
|
+
priority: "hidden-on-mobile",
|
|
212
|
+
cell: (e) => /* @__PURE__ */ p("span", {
|
|
213
|
+
className: "text-text-secondary text-xs",
|
|
214
|
+
children: e.appliedDate
|
|
215
|
+
})
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
key: "status",
|
|
219
|
+
header: "Status",
|
|
220
|
+
priority: "secondary",
|
|
221
|
+
cell: (e) => /* @__PURE__ */ p(h, {
|
|
222
|
+
variant: e.status === "hired" || e.status === "offer" ? "default" : e.status === "rejected" ? "destructive" : "secondary",
|
|
223
|
+
className: "text-[10px]",
|
|
224
|
+
children: e.status
|
|
225
|
+
})
|
|
226
|
+
}
|
|
227
|
+
];
|
|
228
|
+
function j() {
|
|
229
|
+
let { showToast: r } = E(), { candidates: i, addCandidate: a, updateCandidate: d, removeCandidate: h } = e(), [j, M] = s(""), [N, P] = s("all"), { page: F, pageSize: I, offset: L, setPage: R } = T({ initialPageSize: 25 }), [z, B] = s(!1), [V, H] = s(null), [U, W] = s(null), G = async (e) => {
|
|
159
230
|
await a({
|
|
160
231
|
id: o(),
|
|
161
|
-
...
|
|
232
|
+
...k(e)
|
|
162
233
|
}), r("Candidate added", "success");
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
},
|
|
168
|
-
let t = `${e.firstName} ${e.lastName} ${e.position} ${e.email}`.toLowerCase().includes(
|
|
234
|
+
}, K = async (e) => {
|
|
235
|
+
V && (await d(V.id, k(e)), r("Candidate updated", "success"));
|
|
236
|
+
}, q = async () => {
|
|
237
|
+
U && (await h(U.id), r("Candidate removed", "success"));
|
|
238
|
+
}, J = [...new Set(i.map((e) => e.status))], Y = i.filter((e) => {
|
|
239
|
+
let t = `${e.firstName} ${e.lastName} ${e.position} ${e.email}`.toLowerCase().includes(j.toLowerCase()), n = N === "all" || e.status === N;
|
|
169
240
|
return t && n;
|
|
170
|
-
});
|
|
171
|
-
return /* @__PURE__ */
|
|
241
|
+
}), X = Y.slice(L, L + I);
|
|
242
|
+
return /* @__PURE__ */ m("div", {
|
|
172
243
|
className: "space-y-6 p-6",
|
|
173
244
|
children: [
|
|
174
|
-
/* @__PURE__ */
|
|
245
|
+
/* @__PURE__ */ m("div", {
|
|
175
246
|
className: "flex items-center justify-between",
|
|
176
|
-
children: [/* @__PURE__ */
|
|
177
|
-
/* @__PURE__ */
|
|
247
|
+
children: [/* @__PURE__ */ m("div", { children: [
|
|
248
|
+
/* @__PURE__ */ p("h1", {
|
|
178
249
|
className: "text-2xl font-semibold",
|
|
179
|
-
children: /* @__PURE__ */
|
|
250
|
+
children: /* @__PURE__ */ p(y, { children: "Candidates" })
|
|
180
251
|
}),
|
|
181
|
-
/* @__PURE__ */
|
|
252
|
+
/* @__PURE__ */ m("p", {
|
|
182
253
|
className: "text-sm text-text-secondary",
|
|
183
254
|
children: [i.length, " candidates in pipeline"]
|
|
184
255
|
}),
|
|
185
|
-
/* @__PURE__ */
|
|
256
|
+
/* @__PURE__ */ p(S, {
|
|
186
257
|
className: "mt-1",
|
|
187
258
|
children: "Your candidate pool — search, filter, and evaluate the people you're considering so you can fill open roles with the right talent."
|
|
188
259
|
})
|
|
189
|
-
] }), /* @__PURE__ */
|
|
260
|
+
] }), /* @__PURE__ */ m(g, {
|
|
190
261
|
size: "sm",
|
|
191
|
-
onClick: () =>
|
|
192
|
-
children: [/* @__PURE__ */
|
|
262
|
+
onClick: () => B(!0),
|
|
263
|
+
children: [/* @__PURE__ */ p(l, { className: "h-4 w-4 mr-1" }), "Add Candidate"]
|
|
193
264
|
})]
|
|
194
265
|
}),
|
|
195
|
-
/* @__PURE__ */
|
|
266
|
+
/* @__PURE__ */ m("div", {
|
|
196
267
|
className: "flex gap-3 flex-wrap",
|
|
197
|
-
children: [/* @__PURE__ */
|
|
268
|
+
children: [/* @__PURE__ */ m("div", {
|
|
198
269
|
className: "relative flex-1 max-w-sm",
|
|
199
|
-
children: [/* @__PURE__ */
|
|
270
|
+
children: [/* @__PURE__ */ p(u, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary" }), /* @__PURE__ */ p(x, {
|
|
200
271
|
placeholder: "Search candidates...",
|
|
201
272
|
className: "pl-9",
|
|
202
|
-
value:
|
|
203
|
-
onChange: (e) =>
|
|
273
|
+
value: j,
|
|
274
|
+
onChange: (e) => {
|
|
275
|
+
M(e.target.value), R(1);
|
|
276
|
+
}
|
|
204
277
|
})]
|
|
205
|
-
}), /* @__PURE__ */
|
|
278
|
+
}), /* @__PURE__ */ m("div", {
|
|
206
279
|
className: "flex gap-1",
|
|
207
|
-
children: [/* @__PURE__ */
|
|
208
|
-
variant:
|
|
280
|
+
children: [/* @__PURE__ */ p(g, {
|
|
281
|
+
variant: N === "all" ? "default" : "outline",
|
|
209
282
|
size: "sm",
|
|
210
|
-
onClick: () =>
|
|
283
|
+
onClick: () => {
|
|
284
|
+
P("all"), R(1);
|
|
285
|
+
},
|
|
211
286
|
children: "All"
|
|
212
|
-
}),
|
|
213
|
-
variant:
|
|
287
|
+
}), J.map((e) => /* @__PURE__ */ p(g, {
|
|
288
|
+
variant: N === e ? "default" : "outline",
|
|
214
289
|
size: "sm",
|
|
215
|
-
onClick: () =>
|
|
290
|
+
onClick: () => {
|
|
291
|
+
P(e), R(1);
|
|
292
|
+
},
|
|
216
293
|
children: e
|
|
217
294
|
}, e))]
|
|
218
295
|
})]
|
|
219
296
|
}),
|
|
220
|
-
/* @__PURE__ */
|
|
297
|
+
/* @__PURE__ */ p(v, {
|
|
221
298
|
treatment: "glass",
|
|
222
299
|
glow: !0,
|
|
223
300
|
className: "border-border-seam",
|
|
224
|
-
children: /* @__PURE__ */ m(
|
|
225
|
-
className: "p-
|
|
226
|
-
children:
|
|
227
|
-
|
|
228
|
-
|
|
301
|
+
children: /* @__PURE__ */ m(_, {
|
|
302
|
+
className: "p-4",
|
|
303
|
+
children: [/* @__PURE__ */ p(w, {
|
|
304
|
+
data: X,
|
|
305
|
+
rowKey: (e) => e.id,
|
|
306
|
+
columns: A,
|
|
307
|
+
emptyState: /* @__PURE__ */ p(b, {
|
|
229
308
|
illustration: "empty-search",
|
|
230
309
|
title: "No candidates match",
|
|
231
310
|
description: "Try a different search term or status filter."
|
|
311
|
+
}),
|
|
312
|
+
rowActions: (e) => /* @__PURE__ */ m("div", {
|
|
313
|
+
className: "flex items-center justify-end gap-1",
|
|
314
|
+
children: [/* @__PURE__ */ p(g, {
|
|
315
|
+
variant: "ghost",
|
|
316
|
+
size: "sm",
|
|
317
|
+
"aria-label": `Edit ${e.firstName} ${e.lastName}`,
|
|
318
|
+
onClick: () => H(e),
|
|
319
|
+
children: /* @__PURE__ */ p(c, { className: "h-3.5 w-3.5" })
|
|
320
|
+
}), /* @__PURE__ */ p(g, {
|
|
321
|
+
variant: "ghost",
|
|
322
|
+
size: "sm",
|
|
323
|
+
"aria-label": `Delete ${e.firstName} ${e.lastName}`,
|
|
324
|
+
onClick: () => W(e),
|
|
325
|
+
children: /* @__PURE__ */ p(f, { className: "h-3.5 w-3.5 text-status-error-fg" })
|
|
326
|
+
})]
|
|
232
327
|
})
|
|
233
|
-
})
|
|
234
|
-
className: "
|
|
235
|
-
children:
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}),
|
|
243
|
-
/* @__PURE__ */ m("span", {
|
|
244
|
-
className: "text-center",
|
|
245
|
-
children: "Rating"
|
|
246
|
-
}),
|
|
247
|
-
/* @__PURE__ */ m("span", { children: "Applied" }),
|
|
248
|
-
/* @__PURE__ */ m("span", {
|
|
249
|
-
className: "text-center",
|
|
250
|
-
children: "Status"
|
|
251
|
-
}),
|
|
252
|
-
/* @__PURE__ */ m("span", {
|
|
253
|
-
className: "text-right",
|
|
254
|
-
children: "Actions"
|
|
255
|
-
})
|
|
256
|
-
]
|
|
257
|
-
}), W.map((e) => /* @__PURE__ */ h("div", {
|
|
258
|
-
className: "grid grid-cols-8 gap-2 py-3 px-4 border-b last:border-0 text-sm hover:bg-bg-sunken/50",
|
|
259
|
-
children: [
|
|
260
|
-
/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ h("p", {
|
|
261
|
-
className: "font-medium",
|
|
262
|
-
children: [
|
|
263
|
-
e.firstName,
|
|
264
|
-
" ",
|
|
265
|
-
e.lastName
|
|
266
|
-
]
|
|
267
|
-
}), /* @__PURE__ */ m("p", {
|
|
268
|
-
className: "text-xs text-text-secondary",
|
|
269
|
-
children: e.email
|
|
270
|
-
})] }),
|
|
271
|
-
/* @__PURE__ */ m("span", {
|
|
272
|
-
className: "text-text-secondary",
|
|
273
|
-
children: e.position
|
|
274
|
-
}),
|
|
275
|
-
/* @__PURE__ */ m(g, {
|
|
276
|
-
variant: "outline",
|
|
277
|
-
className: "w-fit h-fit text-[10px]",
|
|
278
|
-
children: e.source
|
|
279
|
-
}),
|
|
280
|
-
/* @__PURE__ */ h("span", {
|
|
281
|
-
className: "text-right",
|
|
282
|
-
children: [e.experience, " yrs"]
|
|
283
|
-
}),
|
|
284
|
-
/* @__PURE__ */ h("div", {
|
|
285
|
-
className: "flex items-center justify-center gap-1",
|
|
286
|
-
children: [/* @__PURE__ */ m(d, { className: "h-3 w-3 text-status-warning-text" }), /* @__PURE__ */ m("span", { children: e.rating })]
|
|
287
|
-
}),
|
|
288
|
-
/* @__PURE__ */ m("span", {
|
|
289
|
-
className: "text-text-secondary text-xs",
|
|
290
|
-
children: e.appliedDate
|
|
291
|
-
}),
|
|
292
|
-
/* @__PURE__ */ m("div", {
|
|
293
|
-
className: "text-center",
|
|
294
|
-
children: /* @__PURE__ */ m(g, {
|
|
295
|
-
variant: e.status === "hired" || e.status === "offer" ? "default" : e.status === "rejected" ? "destructive" : "secondary",
|
|
296
|
-
className: "text-[10px]",
|
|
297
|
-
children: e.status
|
|
298
|
-
})
|
|
299
|
-
}),
|
|
300
|
-
/* @__PURE__ */ h("div", {
|
|
301
|
-
className: "flex items-center justify-end gap-1",
|
|
302
|
-
children: [/* @__PURE__ */ m(_, {
|
|
303
|
-
variant: "ghost",
|
|
304
|
-
size: "sm",
|
|
305
|
-
"aria-label": `Edit ${e.firstName} ${e.lastName}`,
|
|
306
|
-
onClick: () => L(e),
|
|
307
|
-
children: /* @__PURE__ */ m(c, { className: "h-3.5 w-3.5" })
|
|
308
|
-
}), /* @__PURE__ */ m(_, {
|
|
309
|
-
variant: "ghost",
|
|
310
|
-
size: "sm",
|
|
311
|
-
"aria-label": `Delete ${e.firstName} ${e.lastName}`,
|
|
312
|
-
onClick: () => z(e),
|
|
313
|
-
children: /* @__PURE__ */ m(f, { className: "h-3.5 w-3.5 text-status-error-fg" })
|
|
314
|
-
})]
|
|
315
|
-
})
|
|
316
|
-
]
|
|
317
|
-
}, e.id))] })
|
|
328
|
+
}), Y.length > I && /* @__PURE__ */ p("div", {
|
|
329
|
+
className: "mt-4",
|
|
330
|
+
children: /* @__PURE__ */ p(C, {
|
|
331
|
+
page: F,
|
|
332
|
+
pageSize: I,
|
|
333
|
+
totalItems: Y.length,
|
|
334
|
+
onPageChange: R
|
|
335
|
+
})
|
|
336
|
+
})]
|
|
318
337
|
})
|
|
319
338
|
}),
|
|
320
|
-
/* @__PURE__ */
|
|
321
|
-
open:
|
|
322
|
-
onOpenChange:
|
|
339
|
+
/* @__PURE__ */ p(t, {
|
|
340
|
+
open: z,
|
|
341
|
+
onOpenChange: B,
|
|
323
342
|
title: "Add Candidate",
|
|
324
343
|
description: "Add someone to your hiring pipeline.",
|
|
325
|
-
fields:
|
|
344
|
+
fields: D,
|
|
326
345
|
submitLabel: "Add candidate",
|
|
327
|
-
onSubmit:
|
|
346
|
+
onSubmit: G
|
|
328
347
|
}),
|
|
329
|
-
/* @__PURE__ */
|
|
330
|
-
open:
|
|
348
|
+
/* @__PURE__ */ p(t, {
|
|
349
|
+
open: V !== null,
|
|
331
350
|
onOpenChange: (e) => {
|
|
332
|
-
e ||
|
|
351
|
+
e || H(null);
|
|
333
352
|
},
|
|
334
353
|
title: "Edit Candidate",
|
|
335
|
-
description:
|
|
336
|
-
fields:
|
|
337
|
-
initialValues:
|
|
354
|
+
description: V ? `${V.firstName} ${V.lastName}` : void 0,
|
|
355
|
+
fields: D,
|
|
356
|
+
initialValues: V ? O(V) : void 0,
|
|
338
357
|
submitLabel: "Save changes",
|
|
339
|
-
onSubmit:
|
|
358
|
+
onSubmit: K
|
|
340
359
|
}),
|
|
341
|
-
/* @__PURE__ */
|
|
342
|
-
open:
|
|
360
|
+
/* @__PURE__ */ p(n, {
|
|
361
|
+
open: U !== null,
|
|
343
362
|
onOpenChange: (e) => {
|
|
344
|
-
e ||
|
|
363
|
+
e || W(null);
|
|
345
364
|
},
|
|
346
365
|
title: "Remove candidate",
|
|
347
|
-
description:
|
|
366
|
+
description: U ? `Remove ${U.firstName} ${U.lastName} from the pipeline?` : void 0,
|
|
348
367
|
confirmLabel: "Remove",
|
|
349
368
|
destructive: !0,
|
|
350
|
-
onConfirm:
|
|
369
|
+
onConfirm: q
|
|
351
370
|
})
|
|
352
371
|
]
|
|
353
372
|
});
|
|
354
373
|
}
|
|
355
374
|
//#endregion
|
|
356
|
-
export {
|
|
375
|
+
export { j as HiringCandidatesPagePage };
|
|
357
376
|
|
|
358
377
|
//# sourceMappingURL=HiringCandidatesPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HiringCandidatesPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/HiringCandidatesPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n Button,\n CardContent,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { Pencil, Plus, Search, Star, Trash2 } from 'lucide-react';\nimport { useCrewFoundryStore, type Candidate } from '../store/crewfoundryStore';\nimport { FormModal, type FieldConfig, type FormValues } from '../components/forms/FormModal';\nimport { ConfirmDialog } from '../components/forms/ConfirmDialog';\nimport { getNumber, getTags, getText, newClientId } from '../components/forms/formValues';\n\nconst CANDIDATE_STATUS_OPTIONS: FieldConfig['options'] = [\n { label: 'New', value: 'new' },\n { label: 'Screening', value: 'screening' },\n { label: 'Interview', value: 'interview' },\n { label: 'Assessment', value: 'assessment' },\n { label: 'Offer', value: 'offer' },\n { label: 'Hired', value: 'hired' },\n { label: 'Rejected', value: 'rejected' },\n];\n\nconst CANDIDATE_FIELDS: FieldConfig[] = [\n { name: 'firstName', label: 'First Name', type: 'text', required: true },\n { name: 'lastName', label: 'Last Name', type: 'text', required: true },\n { name: 'email', label: 'Email', type: 'email', required: true },\n { name: 'phone', label: 'Phone', type: 'text', required: true },\n { name: 'position', label: 'Position', type: 'text', required: true },\n {\n name: 'status',\n label: 'Status',\n type: 'select',\n required: true,\n options: CANDIDATE_STATUS_OPTIONS,\n },\n { name: 'source', label: 'Source', type: 'text', required: true, placeholder: 'e.g. LinkedIn' },\n { name: 'experience', label: 'Experience (years)', type: 'number', required: true },\n { name: 'currentCompany', label: 'Current Company', type: 'text' },\n { name: 'rating', label: 'Rating (out of 5)', type: 'number' },\n { name: 'appliedDate', label: 'Applied Date', type: 'date' },\n { name: 'resumeUrl', label: 'Resume URL', type: 'text' },\n { name: 'skills', label: 'Skills', type: 'tags', colSpan: 2 },\n { name: 'notes', label: 'Notes', type: 'textarea', colSpan: 2 },\n];\n\nconst candidateToValues = (candidate: Candidate): FormValues => ({\n firstName: candidate.firstName,\n lastName: candidate.lastName,\n email: candidate.email,\n phone: candidate.phone,\n position: candidate.position,\n status: candidate.status,\n source: candidate.source,\n experience: candidate.experience,\n currentCompany: candidate.currentCompany,\n rating: candidate.rating,\n appliedDate: candidate.appliedDate,\n resumeUrl: candidate.resumeUrl ?? '',\n skills: candidate.skills,\n notes: candidate.notes,\n});\n\nconst valuesToCandidateFields = (values: FormValues): Omit<Candidate, 'id'> => {\n const appliedDate = getText(values, 'appliedDate');\n return {\n firstName: getText(values, 'firstName'),\n lastName: getText(values, 'lastName'),\n email: getText(values, 'email'),\n phone: getText(values, 'phone'),\n position: getText(values, 'position'),\n status: values.status as Candidate['status'],\n source: getText(values, 'source'),\n experience: getNumber(values, 'experience'),\n currentCompany: getText(values, 'currentCompany'),\n rating: getNumber(values, 'rating'),\n appliedDate: appliedDate.trim() !== '' ? appliedDate : new Date().toISOString().slice(0, 10),\n resumeUrl: getText(values, 'resumeUrl'),\n skills: getTags(values, 'skills'),\n notes: getText(values, 'notes'),\n };\n};\n\nexport function HiringCandidatesPagePage() {\n const { showToast } = useGlobalUi();\n const { candidates, addCandidate, updateCandidate, removeCandidate } = useCrewFoundryStore();\n const [search, setSearch] = useState('');\n const [filterStatus, setFilterStatus] = useState<string>('all');\n const [createOpen, setCreateOpen] = useState(false);\n const [editTarget, setEditTarget] = useState<Candidate | null>(null);\n const [deleteTarget, setDeleteTarget] = useState<Candidate | null>(null);\n\n const handleCreate = async (values: FormValues) => {\n await addCandidate({ id: newClientId(), ...valuesToCandidateFields(values) });\n showToast('Candidate added', 'success');\n };\n\n const handleEdit = async (values: FormValues) => {\n if (!editTarget) {\n return;\n }\n await updateCandidate(editTarget.id, valuesToCandidateFields(values));\n showToast('Candidate updated', 'success');\n };\n\n const handleDelete = async () => {\n if (!deleteTarget) {\n return;\n }\n await removeCandidate(deleteTarget.id);\n showToast('Candidate removed', 'success');\n };\n\n const statuses = [...new Set(candidates.map((c) => c.status))];\n const filtered = candidates.filter((c) => {\n const matchSearch = `${c.firstName} ${c.lastName} ${c.position} ${c.email}`\n .toLowerCase()\n .includes(search.toLowerCase());\n const matchStatus = filterStatus === 'all' || c.status === filterStatus;\n return matchSearch && matchStatus;\n });\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Candidates</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">{candidates.length} candidates in pipeline</p>\n <PagePurpose className=\"mt-1\">Your candidate pool — search, filter, and evaluate the people you're considering so you can fill open roles with the right talent.</PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => setCreateOpen(true)}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Candidate\n </Button>\n </div>\n\n <div className=\"flex gap-3 flex-wrap\">\n <div className=\"relative flex-1 max-w-sm\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input\n placeholder=\"Search candidates...\"\n className=\"pl-9\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n <div className=\"flex gap-1\">\n <Button\n variant={filterStatus === 'all' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setFilterStatus('all')}\n >\n All\n </Button>\n {statuses.map((status) => (\n <Button\n key={status}\n variant={filterStatus === status ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setFilterStatus(status)}\n >\n {status}\n </Button>\n ))}\n </div>\n </div>\n\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardContent className=\"p-0\">\n {filtered.length === 0 ? (\n <div className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No candidates match\"\n description=\"Try a different search term or status filter.\"\n />\n </div>\n ) : (\n <>\n <div className=\"grid grid-cols-8 gap-2 text-xs font-medium text-text-secondary p-4 border-b\">\n <span>Name</span>\n <span>Position</span>\n <span>Source</span>\n <span className=\"text-right\">Experience</span>\n <span className=\"text-center\">Rating</span>\n <span>Applied</span>\n <span className=\"text-center\">Status</span>\n <span className=\"text-right\">Actions</span>\n </div>\n {filtered.map((candidate) => (\n <div\n key={candidate.id}\n className=\"grid grid-cols-8 gap-2 py-3 px-4 border-b last:border-0 text-sm hover:bg-bg-sunken/50\"\n >\n <div>\n <p className=\"font-medium\">\n {candidate.firstName} {candidate.lastName}\n </p>\n <p className=\"text-xs text-text-secondary\">{candidate.email}</p>\n </div>\n <span className=\"text-text-secondary\">{candidate.position}</span>\n <Badge variant=\"outline\" className=\"w-fit h-fit text-[10px]\">\n {candidate.source}\n </Badge>\n <span className=\"text-right\">{candidate.experience} yrs</span>\n <div className=\"flex items-center justify-center gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" />\n <span>{candidate.rating}</span>\n </div>\n <span className=\"text-text-secondary text-xs\">{candidate.appliedDate}</span>\n <div className=\"text-center\">\n <Badge\n variant={\n candidate.status === 'hired'\n ? 'default'\n : candidate.status === 'offer'\n ? 'default'\n : candidate.status === 'rejected'\n ? 'destructive'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {candidate.status}\n </Badge>\n </div>\n <div className=\"flex items-center justify-end gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label={`Edit ${candidate.firstName} ${candidate.lastName}`}\n onClick={() => setEditTarget(candidate)}\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label={`Delete ${candidate.firstName} ${candidate.lastName}`}\n onClick={() => setDeleteTarget(candidate)}\n >\n <Trash2 className=\"h-3.5 w-3.5 text-status-error-fg\" />\n </Button>\n </div>\n </div>\n ))}\n </>\n )}\n </CardContent>\n </GlassCard>\n\n <FormModal\n open={createOpen}\n onOpenChange={setCreateOpen}\n title=\"Add Candidate\"\n description=\"Add someone to your hiring pipeline.\"\n fields={CANDIDATE_FIELDS}\n submitLabel=\"Add candidate\"\n onSubmit={handleCreate}\n />\n <FormModal\n open={editTarget !== null}\n onOpenChange={(open) => {\n if (!open) {\n setEditTarget(null);\n }\n }}\n title=\"Edit Candidate\"\n description={editTarget ? `${editTarget.firstName} ${editTarget.lastName}` : undefined}\n fields={CANDIDATE_FIELDS}\n initialValues={editTarget ? candidateToValues(editTarget) : undefined}\n submitLabel=\"Save changes\"\n onSubmit={handleEdit}\n />\n <ConfirmDialog\n open={deleteTarget !== null}\n onOpenChange={(open) => {\n if (!open) {\n setDeleteTarget(null);\n }\n }}\n title=\"Remove candidate\"\n description={\n deleteTarget\n ? `Remove ${deleteTarget.firstName} ${deleteTarget.lastName} from the pipeline?`\n : undefined\n }\n confirmLabel=\"Remove\"\n destructive\n onConfirm={handleDelete}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HiringCandidatesPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/HiringCandidatesPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n Button,\n CardContent,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n Pagination,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { Pencil, Plus, Search, Star, Trash2 } from 'lucide-react';\nimport { useCrewFoundryStore, type Candidate } from '../store/crewfoundryStore';\nimport { FormModal, type FieldConfig, type FormValues } from '../components/forms/FormModal';\nimport { ConfirmDialog } from '../components/forms/ConfirmDialog';\nimport { getNumber, getTags, getText, newClientId } from '../components/forms/formValues';\n\nconst CANDIDATE_STATUS_OPTIONS: FieldConfig['options'] = [\n { label: 'New', value: 'new' },\n { label: 'Screening', value: 'screening' },\n { label: 'Interview', value: 'interview' },\n { label: 'Assessment', value: 'assessment' },\n { label: 'Offer', value: 'offer' },\n { label: 'Hired', value: 'hired' },\n { label: 'Rejected', value: 'rejected' },\n];\n\nconst CANDIDATE_FIELDS: FieldConfig[] = [\n { name: 'firstName', label: 'First Name', type: 'text', required: true },\n { name: 'lastName', label: 'Last Name', type: 'text', required: true },\n { name: 'email', label: 'Email', type: 'email', required: true },\n { name: 'phone', label: 'Phone', type: 'text', required: true },\n { name: 'position', label: 'Position', type: 'text', required: true },\n {\n name: 'status',\n label: 'Status',\n type: 'select',\n required: true,\n options: CANDIDATE_STATUS_OPTIONS,\n },\n { name: 'source', label: 'Source', type: 'text', required: true, placeholder: 'e.g. LinkedIn' },\n { name: 'experience', label: 'Experience (years)', type: 'number', required: true },\n { name: 'currentCompany', label: 'Current Company', type: 'text' },\n { name: 'rating', label: 'Rating (out of 5)', type: 'number' },\n { name: 'appliedDate', label: 'Applied Date', type: 'date' },\n { name: 'resumeUrl', label: 'Resume URL', type: 'text' },\n { name: 'skills', label: 'Skills', type: 'tags', colSpan: 2 },\n { name: 'notes', label: 'Notes', type: 'textarea', colSpan: 2 },\n];\n\nconst candidateToValues = (candidate: Candidate): FormValues => ({\n firstName: candidate.firstName,\n lastName: candidate.lastName,\n email: candidate.email,\n phone: candidate.phone,\n position: candidate.position,\n status: candidate.status,\n source: candidate.source,\n experience: candidate.experience,\n currentCompany: candidate.currentCompany,\n rating: candidate.rating,\n appliedDate: candidate.appliedDate,\n resumeUrl: candidate.resumeUrl ?? '',\n skills: candidate.skills,\n notes: candidate.notes,\n});\n\nconst valuesToCandidateFields = (values: FormValues): Omit<Candidate, 'id'> => {\n const appliedDate = getText(values, 'appliedDate');\n return {\n firstName: getText(values, 'firstName'),\n lastName: getText(values, 'lastName'),\n email: getText(values, 'email'),\n phone: getText(values, 'phone'),\n position: getText(values, 'position'),\n status: values.status as Candidate['status'],\n source: getText(values, 'source'),\n experience: getNumber(values, 'experience'),\n currentCompany: getText(values, 'currentCompany'),\n rating: getNumber(values, 'rating'),\n appliedDate: appliedDate.trim() !== '' ? appliedDate : new Date().toISOString().slice(0, 10),\n resumeUrl: getText(values, 'resumeUrl'),\n skills: getTags(values, 'skills'),\n notes: getText(values, 'notes'),\n };\n};\n\nconst CANDIDATE_COLUMNS: ResponsiveTableColumn<Candidate>[] = [\n {\n key: 'name',\n header: 'Name',\n priority: 'primary',\n cell: (candidate) => (\n <div>\n <p className=\"font-medium\">\n {candidate.firstName} {candidate.lastName}\n </p>\n <p className=\"text-xs text-text-secondary\">{candidate.email}</p>\n </div>\n ),\n },\n {\n key: 'position',\n header: 'Position',\n priority: 'secondary',\n cell: (candidate) => <span className=\"text-text-secondary\">{candidate.position}</span>,\n },\n {\n key: 'source',\n header: 'Source',\n priority: 'secondary',\n cell: (candidate) => (\n <Badge variant=\"outline\" className=\"w-fit h-fit text-[10px]\">\n {candidate.source}\n </Badge>\n ),\n },\n {\n key: 'experience',\n header: 'Experience',\n priority: 'secondary',\n cell: (candidate) => <span>{candidate.experience} yrs</span>,\n },\n {\n key: 'rating',\n header: 'Rating',\n priority: 'secondary',\n cell: (candidate) => (\n <span className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" />\n {candidate.rating}\n </span>\n ),\n },\n {\n key: 'applied',\n header: 'Applied',\n priority: 'hidden-on-mobile',\n cell: (candidate) => (\n <span className=\"text-text-secondary text-xs\">{candidate.appliedDate}</span>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n priority: 'secondary',\n cell: (candidate) => (\n <Badge\n variant={\n candidate.status === 'hired'\n ? 'default'\n : candidate.status === 'offer'\n ? 'default'\n : candidate.status === 'rejected'\n ? 'destructive'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {candidate.status}\n </Badge>\n ),\n },\n];\n\nexport function HiringCandidatesPagePage() {\n const { showToast } = useGlobalUi();\n const { candidates, addCandidate, updateCandidate, removeCandidate } = useCrewFoundryStore();\n const [search, setSearch] = useState('');\n const [filterStatus, setFilterStatus] = useState<string>('all');\n const { page, pageSize, offset, setPage } = usePagination({ initialPageSize: 25 });\n const [createOpen, setCreateOpen] = useState(false);\n const [editTarget, setEditTarget] = useState<Candidate | null>(null);\n const [deleteTarget, setDeleteTarget] = useState<Candidate | null>(null);\n\n const handleCreate = async (values: FormValues) => {\n await addCandidate({ id: newClientId(), ...valuesToCandidateFields(values) });\n showToast('Candidate added', 'success');\n };\n\n const handleEdit = async (values: FormValues) => {\n if (!editTarget) {\n return;\n }\n await updateCandidate(editTarget.id, valuesToCandidateFields(values));\n showToast('Candidate updated', 'success');\n };\n\n const handleDelete = async () => {\n if (!deleteTarget) {\n return;\n }\n await removeCandidate(deleteTarget.id);\n showToast('Candidate removed', 'success');\n };\n\n const statuses = [...new Set(candidates.map((c) => c.status))];\n const filtered = candidates.filter((c) => {\n const matchSearch = `${c.firstName} ${c.lastName} ${c.position} ${c.email}`\n .toLowerCase()\n .includes(search.toLowerCase());\n const matchStatus = filterStatus === 'all' || c.status === filterStatus;\n return matchSearch && matchStatus;\n });\n const paged = filtered.slice(offset, offset + pageSize);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Candidates</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">{candidates.length} candidates in pipeline</p>\n <PagePurpose className=\"mt-1\">Your candidate pool — search, filter, and evaluate the people you're considering so you can fill open roles with the right talent.</PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => setCreateOpen(true)}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Candidate\n </Button>\n </div>\n\n <div className=\"flex gap-3 flex-wrap\">\n <div className=\"relative flex-1 max-w-sm\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary\" />\n <Input\n placeholder=\"Search candidates...\"\n className=\"pl-9\"\n value={search}\n onChange={(e) => {\n setSearch(e.target.value);\n setPage(1);\n }}\n />\n </div>\n <div className=\"flex gap-1\">\n <Button\n variant={filterStatus === 'all' ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => {\n setFilterStatus('all');\n setPage(1);\n }}\n >\n All\n </Button>\n {statuses.map((status) => (\n <Button\n key={status}\n variant={filterStatus === status ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => {\n setFilterStatus(status);\n setPage(1);\n }}\n >\n {status}\n </Button>\n ))}\n </div>\n </div>\n\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardContent className=\"p-4\">\n <ResponsiveTable\n data={paged}\n rowKey={(candidate) => candidate.id}\n columns={CANDIDATE_COLUMNS}\n emptyState={\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No candidates match\"\n description=\"Try a different search term or status filter.\"\n />\n }\n rowActions={(candidate) => (\n <div className=\"flex items-center justify-end gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label={`Edit ${candidate.firstName} ${candidate.lastName}`}\n onClick={() => setEditTarget(candidate)}\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label={`Delete ${candidate.firstName} ${candidate.lastName}`}\n onClick={() => setDeleteTarget(candidate)}\n >\n <Trash2 className=\"h-3.5 w-3.5 text-status-error-fg\" />\n </Button>\n </div>\n )}\n />\n {filtered.length > pageSize && (\n <div className=\"mt-4\">\n <Pagination\n page={page}\n pageSize={pageSize}\n totalItems={filtered.length}\n onPageChange={setPage}\n />\n </div>\n )}\n </CardContent>\n </GlassCard>\n\n <FormModal\n open={createOpen}\n onOpenChange={setCreateOpen}\n title=\"Add Candidate\"\n description=\"Add someone to your hiring pipeline.\"\n fields={CANDIDATE_FIELDS}\n submitLabel=\"Add candidate\"\n onSubmit={handleCreate}\n />\n <FormModal\n open={editTarget !== null}\n onOpenChange={(open) => {\n if (!open) {\n setEditTarget(null);\n }\n }}\n title=\"Edit Candidate\"\n description={editTarget ? `${editTarget.firstName} ${editTarget.lastName}` : undefined}\n fields={CANDIDATE_FIELDS}\n initialValues={editTarget ? candidateToValues(editTarget) : undefined}\n submitLabel=\"Save changes\"\n onSubmit={handleEdit}\n />\n <ConfirmDialog\n open={deleteTarget !== null}\n onOpenChange={(open) => {\n if (!open) {\n setDeleteTarget(null);\n }\n }}\n title=\"Remove candidate\"\n description={\n deleteTarget\n ? `Remove ${deleteTarget.firstName} ${deleteTarget.lastName} from the pipeline?`\n : undefined\n }\n confirmLabel=\"Remove\"\n destructive\n onConfirm={handleDelete}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -129,7 +129,7 @@ function w() {
|
|
|
129
129
|
})]
|
|
130
130
|
}),
|
|
131
131
|
/* @__PURE__ */ c("div", {
|
|
132
|
-
className: "grid grid-cols-2 gap-4",
|
|
132
|
+
className: "grid grid-cols-1 sm:grid-cols-2 gap-4",
|
|
133
133
|
children: [/* @__PURE__ */ c("div", {
|
|
134
134
|
className: "space-y-2",
|
|
135
135
|
children: [/* @__PURE__ */ s("label", {
|
|
@@ -157,7 +157,7 @@ function w() {
|
|
|
157
157
|
})]
|
|
158
158
|
}),
|
|
159
159
|
/* @__PURE__ */ c("div", {
|
|
160
|
-
className: "grid grid-cols-2 gap-4",
|
|
160
|
+
className: "grid grid-cols-1 sm:grid-cols-2 gap-4",
|
|
161
161
|
children: [/* @__PURE__ */ c("div", {
|
|
162
162
|
className: "space-y-2",
|
|
163
163
|
children: [/* @__PURE__ */ s("label", {
|
|
@@ -193,7 +193,7 @@ function w() {
|
|
|
193
193
|
})]
|
|
194
194
|
}),
|
|
195
195
|
/* @__PURE__ */ c("div", {
|
|
196
|
-
className: "grid grid-cols-2 gap-4",
|
|
196
|
+
className: "grid grid-cols-1 sm:grid-cols-2 gap-4",
|
|
197
197
|
children: [/* @__PURE__ */ c("div", {
|
|
198
198
|
className: "space-y-2",
|
|
199
199
|
children: [/* @__PURE__ */ s("label", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HiringCreateJobPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/HiringCreateJobPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n EmphasisPanel,\n GradientText,\n Input,\n PagePurpose,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { Briefcase, Plus, Save, X } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore, type JobPosting } from '../store/crewfoundryStore';\nimport { newClientId } from '../components/forms/formValues';\n\n// Native <select> styled with the same semantic tokens as fe-libs Input.\nconst SELECT_CLASS =\n 'flex h-10 w-full rounded-input border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary transition-colors duration-200 focus-visible:border-border-focus focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50';\n\nconst JOB_TYPE_OPTIONS: { label: string; value: JobPosting['type'] }[] = [\n { label: 'Full time', value: 'full_time' },\n { label: 'Part time', value: 'part_time' },\n { label: 'Contract', value: 'contract' },\n { label: 'Remote', value: 'remote' },\n];\n\nconst EXPERIENCE_OPTIONS: { label: string; value: JobPosting['experienceLevel'] }[] = [\n { label: 'Entry', value: 'entry' },\n { label: 'Mid', value: 'mid' },\n { label: 'Senior', value: 'senior' },\n { label: 'Lead', value: 'lead' },\n { label: 'Executive', value: 'executive' },\n];\n\nexport function HiringCreateJobPagePage() {\n const navigate = useNavigate();\n const { showToast } = useGlobalUi();\n const addJobPosting = useCrewFoundryStore((state) => state.addJobPosting);\n\n const [title, setTitle] = useState('');\n const [department, setDepartment] = useState('');\n const [location, setLocation] = useState('');\n const [description, setDescription] = useState('');\n const [type, setType] = useState<JobPosting['type']>('full_time');\n const [experienceLevel, setExperienceLevel] = useState<JobPosting['experienceLevel']>('mid');\n const [salaryMin, setSalaryMin] = useState('');\n const [salaryMax, setSalaryMax] = useState('');\n const [deadline, setDeadline] = useState('');\n const [requirements, setRequirements] = useState<string[]>(['']);\n const [benefits, setBenefits] = useState<string[]>(['']);\n const [submitting, setSubmitting] = useState(false);\n\n const addRequirement = () => setRequirements([...requirements, '']);\n const addBenefit = () => setBenefits([...benefits, '']);\n const updateRequirement = (idx: number, value: string) => {\n const updated = [...requirements];\n updated[idx] = value;\n setRequirements(updated);\n };\n const updateBenefit = (idx: number, value: string) => {\n const updated = [...benefits];\n updated[idx] = value;\n setBenefits(updated);\n };\n const removeRequirement = (idx: number) =>\n setRequirements(requirements.filter((_, i) => i !== idx));\n const removeBenefit = (idx: number) => setBenefits(benefits.filter((_, i) => i !== idx));\n\n const submit = async (status: JobPosting['status']) => {\n if (submitting) {\n return;\n }\n if (!title.trim()) {\n showToast('Job Title is required', 'warning');\n return;\n }\n if (!department.trim()) {\n showToast('Department is required', 'warning');\n return;\n }\n const today = new Date().toISOString().slice(0, 10);\n const job: JobPosting = {\n id: newClientId(),\n title: title.trim(),\n department: department.trim(),\n location: location.trim(),\n type,\n experienceLevel,\n salaryMin: salaryMin.trim() === '' ? 0 : Number(salaryMin),\n salaryMax: salaryMax.trim() === '' ? 0 : Number(salaryMax),\n status,\n applicants: 0,\n postedDate: today,\n deadline: deadline.trim() === '' ? today : deadline,\n description: description.trim(),\n requirements: requirements.map((item) => item.trim()).filter(Boolean),\n benefits: benefits.map((item) => item.trim()).filter(Boolean),\n };\n\n setSubmitting(true);\n try {\n await addJobPosting(job);\n showToast(status === 'draft' ? 'Draft saved' : 'Job published', 'success');\n navigate('../jobs-page');\n } catch (error) {\n showToast(error instanceof Error ? error.message : 'Unable to save job posting', 'error');\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Create Job Posting</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Fill in the details for a new position</p>\n <PagePurpose className=\"mt-1\">Create a new job posting — define the role, requirements, and compensation here to start attracting and collecting applicants.</PagePurpose>\n </div>\n </div>\n\n <EmphasisPanel>\n <div className=\"mb-4 flex items-center gap-2 text-lg font-semibold\">\n <Briefcase className=\"h-5 w-5\" />\n Job Details\n </div>\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-title\">\n Job Title\n </label>\n <Input\n id=\"job-title\"\n placeholder=\"e.g. Senior Frontend Developer\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-department\">\n Department\n </label>\n <Input\n id=\"job-department\"\n placeholder=\"e.g. Engineering\"\n value={department}\n onChange={(e) => setDepartment(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-location\">\n Location\n </label>\n <Input\n id=\"job-location\"\n placeholder=\"e.g. San Francisco, CA\"\n value={location}\n onChange={(e) => setLocation(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-type\">\n Employment Type\n </label>\n <select\n id=\"job-type\"\n className={SELECT_CLASS}\n value={type}\n onChange={(e) => setType(e.target.value as JobPosting['type'])}\n >\n {JOB_TYPE_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-experience\">\n Experience Level\n </label>\n <select\n id=\"job-experience\"\n className={SELECT_CLASS}\n value={experienceLevel}\n onChange={(e) =>\n setExperienceLevel(e.target.value as JobPosting['experienceLevel'])\n }\n >\n {EXPERIENCE_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-salary-min\">\n Salary Min ($)\n </label>\n <Input\n id=\"job-salary-min\"\n type=\"number\"\n placeholder=\"e.g. 120000\"\n value={salaryMin}\n onChange={(e) => setSalaryMin(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-salary-max\">\n Salary Max ($)\n </label>\n <Input\n id=\"job-salary-max\"\n type=\"number\"\n placeholder=\"e.g. 180000\"\n value={salaryMax}\n onChange={(e) => setSalaryMax(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-deadline\">\n Application Deadline\n </label>\n <Input\n id=\"job-deadline\"\n type=\"date\"\n value={deadline}\n onChange={(e) => setDeadline(e.target.value)}\n />\n </div>\n\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-description\">\n Description\n </label>\n <Textarea\n id=\"job-description\"\n placeholder=\"Describe the role, responsibilities, and ideal candidate...\"\n rows={4}\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n />\n </div>\n </div>\n </EmphasisPanel>\n\n <Card>\n <CardHeader>\n <CardTitle>Requirements</CardTitle>\n <CardDescription>List the key requirements for this role</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {requirements.map((req, idx) => (\n <div key={idx} className=\"flex gap-2\">\n <Input\n placeholder={`Requirement ${idx + 1}`}\n value={req}\n onChange={(e) => updateRequirement(idx, e.target.value)}\n />\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`Remove requirement ${idx + 1}`}\n onClick={() => removeRequirement(idx)}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n <Button variant=\"outline\" size=\"sm\" onClick={addRequirement}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Requirement\n </Button>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Benefits</CardTitle>\n <CardDescription>What does this position offer?</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {benefits.map((ben, idx) => (\n <div key={idx} className=\"flex gap-2\">\n <Input\n placeholder={`Benefit ${idx + 1}`}\n value={ben}\n onChange={(e) => updateBenefit(idx, e.target.value)}\n />\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`Remove benefit ${idx + 1}`}\n onClick={() => removeBenefit(idx)}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n <Button variant=\"outline\" size=\"sm\" onClick={addBenefit}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Benefit\n </Button>\n </CardContent>\n </Card>\n\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" disabled={submitting} onClick={() => submit('draft')}>\n Save as Draft\n </Button>\n <Button disabled={submitting} onClick={() => submit('active')}>\n <Save className=\"h-4 w-4 mr-1\" />\n {submitting ? 'Saving…' : 'Publish Job'}\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HiringCreateJobPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/HiringCreateJobPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n EmphasisPanel,\n GradientText,\n Input,\n PagePurpose,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { Briefcase, Plus, Save, X } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore, type JobPosting } from '../store/crewfoundryStore';\nimport { newClientId } from '../components/forms/formValues';\n\n// Native <select> styled with the same semantic tokens as fe-libs Input.\nconst SELECT_CLASS =\n 'flex h-10 w-full rounded-input border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary transition-colors duration-200 focus-visible:border-border-focus focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50';\n\nconst JOB_TYPE_OPTIONS: { label: string; value: JobPosting['type'] }[] = [\n { label: 'Full time', value: 'full_time' },\n { label: 'Part time', value: 'part_time' },\n { label: 'Contract', value: 'contract' },\n { label: 'Remote', value: 'remote' },\n];\n\nconst EXPERIENCE_OPTIONS: { label: string; value: JobPosting['experienceLevel'] }[] = [\n { label: 'Entry', value: 'entry' },\n { label: 'Mid', value: 'mid' },\n { label: 'Senior', value: 'senior' },\n { label: 'Lead', value: 'lead' },\n { label: 'Executive', value: 'executive' },\n];\n\nexport function HiringCreateJobPagePage() {\n const navigate = useNavigate();\n const { showToast } = useGlobalUi();\n const addJobPosting = useCrewFoundryStore((state) => state.addJobPosting);\n\n const [title, setTitle] = useState('');\n const [department, setDepartment] = useState('');\n const [location, setLocation] = useState('');\n const [description, setDescription] = useState('');\n const [type, setType] = useState<JobPosting['type']>('full_time');\n const [experienceLevel, setExperienceLevel] = useState<JobPosting['experienceLevel']>('mid');\n const [salaryMin, setSalaryMin] = useState('');\n const [salaryMax, setSalaryMax] = useState('');\n const [deadline, setDeadline] = useState('');\n const [requirements, setRequirements] = useState<string[]>(['']);\n const [benefits, setBenefits] = useState<string[]>(['']);\n const [submitting, setSubmitting] = useState(false);\n\n const addRequirement = () => setRequirements([...requirements, '']);\n const addBenefit = () => setBenefits([...benefits, '']);\n const updateRequirement = (idx: number, value: string) => {\n const updated = [...requirements];\n updated[idx] = value;\n setRequirements(updated);\n };\n const updateBenefit = (idx: number, value: string) => {\n const updated = [...benefits];\n updated[idx] = value;\n setBenefits(updated);\n };\n const removeRequirement = (idx: number) =>\n setRequirements(requirements.filter((_, i) => i !== idx));\n const removeBenefit = (idx: number) => setBenefits(benefits.filter((_, i) => i !== idx));\n\n const submit = async (status: JobPosting['status']) => {\n if (submitting) {\n return;\n }\n if (!title.trim()) {\n showToast('Job Title is required', 'warning');\n return;\n }\n if (!department.trim()) {\n showToast('Department is required', 'warning');\n return;\n }\n const today = new Date().toISOString().slice(0, 10);\n const job: JobPosting = {\n id: newClientId(),\n title: title.trim(),\n department: department.trim(),\n location: location.trim(),\n type,\n experienceLevel,\n salaryMin: salaryMin.trim() === '' ? 0 : Number(salaryMin),\n salaryMax: salaryMax.trim() === '' ? 0 : Number(salaryMax),\n status,\n applicants: 0,\n postedDate: today,\n deadline: deadline.trim() === '' ? today : deadline,\n description: description.trim(),\n requirements: requirements.map((item) => item.trim()).filter(Boolean),\n benefits: benefits.map((item) => item.trim()).filter(Boolean),\n };\n\n setSubmitting(true);\n try {\n await addJobPosting(job);\n showToast(status === 'draft' ? 'Draft saved' : 'Job published', 'success');\n navigate('../jobs-page');\n } catch (error) {\n showToast(error instanceof Error ? error.message : 'Unable to save job posting', 'error');\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Create Job Posting</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Fill in the details for a new position</p>\n <PagePurpose className=\"mt-1\">Create a new job posting — define the role, requirements, and compensation here to start attracting and collecting applicants.</PagePurpose>\n </div>\n </div>\n\n <EmphasisPanel>\n <div className=\"mb-4 flex items-center gap-2 text-lg font-semibold\">\n <Briefcase className=\"h-5 w-5\" />\n Job Details\n </div>\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-title\">\n Job Title\n </label>\n <Input\n id=\"job-title\"\n placeholder=\"e.g. Senior Frontend Developer\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n />\n </div>\n\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-department\">\n Department\n </label>\n <Input\n id=\"job-department\"\n placeholder=\"e.g. Engineering\"\n value={department}\n onChange={(e) => setDepartment(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-location\">\n Location\n </label>\n <Input\n id=\"job-location\"\n placeholder=\"e.g. San Francisco, CA\"\n value={location}\n onChange={(e) => setLocation(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-type\">\n Employment Type\n </label>\n <select\n id=\"job-type\"\n className={SELECT_CLASS}\n value={type}\n onChange={(e) => setType(e.target.value as JobPosting['type'])}\n >\n {JOB_TYPE_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-experience\">\n Experience Level\n </label>\n <select\n id=\"job-experience\"\n className={SELECT_CLASS}\n value={experienceLevel}\n onChange={(e) =>\n setExperienceLevel(e.target.value as JobPosting['experienceLevel'])\n }\n >\n {EXPERIENCE_OPTIONS.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-salary-min\">\n Salary Min ($)\n </label>\n <Input\n id=\"job-salary-min\"\n type=\"number\"\n placeholder=\"e.g. 120000\"\n value={salaryMin}\n onChange={(e) => setSalaryMin(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-salary-max\">\n Salary Max ($)\n </label>\n <Input\n id=\"job-salary-max\"\n type=\"number\"\n placeholder=\"e.g. 180000\"\n value={salaryMax}\n onChange={(e) => setSalaryMax(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-deadline\">\n Application Deadline\n </label>\n <Input\n id=\"job-deadline\"\n type=\"date\"\n value={deadline}\n onChange={(e) => setDeadline(e.target.value)}\n />\n </div>\n\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\" htmlFor=\"job-description\">\n Description\n </label>\n <Textarea\n id=\"job-description\"\n placeholder=\"Describe the role, responsibilities, and ideal candidate...\"\n rows={4}\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n />\n </div>\n </div>\n </EmphasisPanel>\n\n <Card>\n <CardHeader>\n <CardTitle>Requirements</CardTitle>\n <CardDescription>List the key requirements for this role</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {requirements.map((req, idx) => (\n <div key={idx} className=\"flex gap-2\">\n <Input\n placeholder={`Requirement ${idx + 1}`}\n value={req}\n onChange={(e) => updateRequirement(idx, e.target.value)}\n />\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`Remove requirement ${idx + 1}`}\n onClick={() => removeRequirement(idx)}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n <Button variant=\"outline\" size=\"sm\" onClick={addRequirement}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Requirement\n </Button>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Benefits</CardTitle>\n <CardDescription>What does this position offer?</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {benefits.map((ben, idx) => (\n <div key={idx} className=\"flex gap-2\">\n <Input\n placeholder={`Benefit ${idx + 1}`}\n value={ben}\n onChange={(e) => updateBenefit(idx, e.target.value)}\n />\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`Remove benefit ${idx + 1}`}\n onClick={() => removeBenefit(idx)}\n >\n <X className=\"h-4 w-4\" />\n </Button>\n </div>\n ))}\n <Button variant=\"outline\" size=\"sm\" onClick={addBenefit}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Benefit\n </Button>\n </CardContent>\n </Card>\n\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" disabled={submitting} onClick={() => submit('draft')}>\n Save as Draft\n </Button>\n <Button disabled={submitting} onClick={() => submit('active')}>\n <Save className=\"h-4 w-4 mr-1\" />\n {submitting ? 'Saving…' : 'Publish Job'}\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|