@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,15 +1,16 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
2
|
+
import { formatEnumLabel as t } from "../utils/formatEnumLabel.js";
|
|
3
|
+
import { FormModal as n } from "../components/forms/FormModal.js";
|
|
4
|
+
import { ConfirmDialog as r } from "../components/forms/ConfirmDialog.js";
|
|
5
|
+
import { getNumber as i, getTags as a, getText as o, newClientId as s } from "../components/forms/formValues.js";
|
|
6
|
+
import { useState as c } from "react";
|
|
7
|
+
import { Pencil as l, Plus as u, Search as d, Star as f, Trash2 as p } from "lucide-react";
|
|
8
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
9
|
+
import { Badge as g, Button as _, CardContent as v, GlassCard as y, GradientText as b, IllustratedEmptyState as x, Input as S, PagePurpose as C, Pagination as w, ResponsiveTable as T } from "@burdenoff/fe-libs/ui";
|
|
10
|
+
import { usePagination as E } from "@burdenoff/fe-libs/shared/hooks";
|
|
11
|
+
import { useGlobalUi as D } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
11
12
|
//#region src/crewfoundry/pages/HiringCandidatesPagePage.tsx
|
|
12
|
-
var
|
|
13
|
+
var O = [
|
|
13
14
|
{
|
|
14
15
|
name: "firstName",
|
|
15
16
|
label: "First Name",
|
|
@@ -121,7 +122,7 @@ var D = [
|
|
|
121
122
|
type: "textarea",
|
|
122
123
|
colSpan: 2
|
|
123
124
|
}
|
|
124
|
-
],
|
|
125
|
+
], k = (e) => ({
|
|
125
126
|
firstName: e.firstName,
|
|
126
127
|
lastName: e.lastName,
|
|
127
128
|
email: e.email,
|
|
@@ -136,37 +137,37 @@ var D = [
|
|
|
136
137
|
resumeUrl: e.resumeUrl ?? "",
|
|
137
138
|
skills: e.skills,
|
|
138
139
|
notes: e.notes
|
|
139
|
-
}),
|
|
140
|
-
let t =
|
|
140
|
+
}), A = (e) => {
|
|
141
|
+
let t = o(e, "appliedDate");
|
|
141
142
|
return {
|
|
142
|
-
firstName:
|
|
143
|
-
lastName:
|
|
144
|
-
email:
|
|
145
|
-
phone:
|
|
146
|
-
position:
|
|
143
|
+
firstName: o(e, "firstName"),
|
|
144
|
+
lastName: o(e, "lastName"),
|
|
145
|
+
email: o(e, "email"),
|
|
146
|
+
phone: o(e, "phone"),
|
|
147
|
+
position: o(e, "position"),
|
|
147
148
|
status: e.status,
|
|
148
|
-
source:
|
|
149
|
-
experience:
|
|
150
|
-
currentCompany:
|
|
151
|
-
rating:
|
|
149
|
+
source: o(e, "source"),
|
|
150
|
+
experience: i(e, "experience"),
|
|
151
|
+
currentCompany: o(e, "currentCompany"),
|
|
152
|
+
rating: i(e, "rating"),
|
|
152
153
|
appliedDate: t.trim() === "" ? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10) : t,
|
|
153
|
-
resumeUrl:
|
|
154
|
-
skills:
|
|
155
|
-
notes:
|
|
154
|
+
resumeUrl: o(e, "resumeUrl"),
|
|
155
|
+
skills: a(e, "skills"),
|
|
156
|
+
notes: o(e, "notes")
|
|
156
157
|
};
|
|
157
|
-
},
|
|
158
|
+
}, j = [
|
|
158
159
|
{
|
|
159
160
|
key: "name",
|
|
160
161
|
header: "Name",
|
|
161
162
|
priority: "primary",
|
|
162
|
-
cell: (e) => /* @__PURE__ */
|
|
163
|
+
cell: (e) => /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ h("p", {
|
|
163
164
|
className: "font-medium",
|
|
164
165
|
children: [
|
|
165
166
|
e.firstName,
|
|
166
167
|
" ",
|
|
167
168
|
e.lastName
|
|
168
169
|
]
|
|
169
|
-
}), /* @__PURE__ */
|
|
170
|
+
}), /* @__PURE__ */ m("p", {
|
|
170
171
|
className: "text-xs text-text-secondary",
|
|
171
172
|
children: e.email
|
|
172
173
|
})] })
|
|
@@ -175,7 +176,7 @@ var D = [
|
|
|
175
176
|
key: "position",
|
|
176
177
|
header: "Position",
|
|
177
178
|
priority: "secondary",
|
|
178
|
-
cell: (e) => /* @__PURE__ */
|
|
179
|
+
cell: (e) => /* @__PURE__ */ m("span", {
|
|
179
180
|
className: "text-text-secondary",
|
|
180
181
|
children: e.position
|
|
181
182
|
})
|
|
@@ -184,7 +185,7 @@ var D = [
|
|
|
184
185
|
key: "source",
|
|
185
186
|
header: "Source",
|
|
186
187
|
priority: "secondary",
|
|
187
|
-
cell: (e) => /* @__PURE__ */
|
|
188
|
+
cell: (e) => /* @__PURE__ */ m(g, {
|
|
188
189
|
variant: "outline",
|
|
189
190
|
className: "w-fit h-fit text-[10px]",
|
|
190
191
|
children: e.source
|
|
@@ -194,22 +195,22 @@ var D = [
|
|
|
194
195
|
key: "experience",
|
|
195
196
|
header: "Experience",
|
|
196
197
|
priority: "secondary",
|
|
197
|
-
cell: (e) => /* @__PURE__ */
|
|
198
|
+
cell: (e) => /* @__PURE__ */ h("span", { children: [e.experience, " yrs"] })
|
|
198
199
|
},
|
|
199
200
|
{
|
|
200
201
|
key: "rating",
|
|
201
202
|
header: "Rating",
|
|
202
203
|
priority: "secondary",
|
|
203
|
-
cell: (e) => /* @__PURE__ */
|
|
204
|
+
cell: (e) => /* @__PURE__ */ h("span", {
|
|
204
205
|
className: "flex items-center gap-1",
|
|
205
|
-
children: [/* @__PURE__ */
|
|
206
|
+
children: [/* @__PURE__ */ m(f, { className: "h-3 w-3 text-status-warning-text" }), e.rating]
|
|
206
207
|
})
|
|
207
208
|
},
|
|
208
209
|
{
|
|
209
210
|
key: "applied",
|
|
210
211
|
header: "Applied",
|
|
211
212
|
priority: "hidden-on-mobile",
|
|
212
|
-
cell: (e) => /* @__PURE__ */
|
|
213
|
+
cell: (e) => /* @__PURE__ */ m("span", {
|
|
213
214
|
className: "text-text-secondary text-xs",
|
|
214
215
|
children: e.appliedDate
|
|
215
216
|
})
|
|
@@ -218,73 +219,73 @@ var D = [
|
|
|
218
219
|
key: "status",
|
|
219
220
|
header: "Status",
|
|
220
221
|
priority: "secondary",
|
|
221
|
-
cell: (e) => /* @__PURE__ */
|
|
222
|
+
cell: (e) => /* @__PURE__ */ m(g, {
|
|
222
223
|
variant: e.status === "hired" || e.status === "offer" ? "default" : e.status === "rejected" ? "destructive" : "secondary",
|
|
223
224
|
className: "text-[10px]",
|
|
224
|
-
children: e.status
|
|
225
|
+
children: t(e.status)
|
|
225
226
|
})
|
|
226
227
|
}
|
|
227
228
|
];
|
|
228
|
-
function
|
|
229
|
-
let { showToast:
|
|
229
|
+
function M() {
|
|
230
|
+
let { showToast: t } = D(), { candidates: i, addCandidate: a, updateCandidate: o, removeCandidate: f } = e(), [g, M] = c(""), [N, P] = c("all"), { page: F, pageSize: I, offset: L, setPage: R } = E({ initialPageSize: 25 }), [z, B] = c(!1), [V, H] = c(null), [U, W] = c(null), G = async (e) => {
|
|
230
231
|
await a({
|
|
231
|
-
id:
|
|
232
|
-
...
|
|
233
|
-
}),
|
|
232
|
+
id: s(),
|
|
233
|
+
...A(e)
|
|
234
|
+
}), t("Candidate added", "success");
|
|
234
235
|
}, K = async (e) => {
|
|
235
|
-
V && (await
|
|
236
|
+
V && (await o(V.id, A(e)), t("Candidate updated", "success"));
|
|
236
237
|
}, q = async () => {
|
|
237
|
-
U && (await
|
|
238
|
+
U && (await f(U.id), t("Candidate removed", "success"));
|
|
238
239
|
}, 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(
|
|
240
|
+
let t = `${e.firstName} ${e.lastName} ${e.position} ${e.email}`.toLowerCase().includes(g.toLowerCase()), n = N === "all" || e.status === N;
|
|
240
241
|
return t && n;
|
|
241
242
|
}), X = Y.slice(L, L + I);
|
|
242
|
-
return /* @__PURE__ */
|
|
243
|
+
return /* @__PURE__ */ h("div", {
|
|
243
244
|
className: "space-y-6 p-6",
|
|
244
245
|
children: [
|
|
245
|
-
/* @__PURE__ */
|
|
246
|
+
/* @__PURE__ */ h("div", {
|
|
246
247
|
className: "flex items-center justify-between",
|
|
247
|
-
children: [/* @__PURE__ */
|
|
248
|
-
/* @__PURE__ */
|
|
248
|
+
children: [/* @__PURE__ */ h("div", { children: [
|
|
249
|
+
/* @__PURE__ */ m("h1", {
|
|
249
250
|
className: "text-2xl font-semibold",
|
|
250
|
-
children: /* @__PURE__ */
|
|
251
|
+
children: /* @__PURE__ */ m(b, { children: "Candidates" })
|
|
251
252
|
}),
|
|
252
|
-
/* @__PURE__ */
|
|
253
|
+
/* @__PURE__ */ h("p", {
|
|
253
254
|
className: "text-sm text-text-secondary",
|
|
254
255
|
children: [i.length, " candidates in pipeline"]
|
|
255
256
|
}),
|
|
256
|
-
/* @__PURE__ */
|
|
257
|
+
/* @__PURE__ */ m(C, {
|
|
257
258
|
className: "mt-1",
|
|
258
259
|
children: "Your candidate pool — search, filter, and evaluate the people you're considering so you can fill open roles with the right talent."
|
|
259
260
|
})
|
|
260
|
-
] }), /* @__PURE__ */
|
|
261
|
+
] }), /* @__PURE__ */ h(_, {
|
|
261
262
|
size: "sm",
|
|
262
263
|
onClick: () => B(!0),
|
|
263
|
-
children: [/* @__PURE__ */
|
|
264
|
+
children: [/* @__PURE__ */ m(u, { className: "h-4 w-4 mr-1" }), "Add Candidate"]
|
|
264
265
|
})]
|
|
265
266
|
}),
|
|
266
|
-
/* @__PURE__ */
|
|
267
|
+
/* @__PURE__ */ h("div", {
|
|
267
268
|
className: "flex gap-3 flex-wrap",
|
|
268
|
-
children: [/* @__PURE__ */
|
|
269
|
+
children: [/* @__PURE__ */ h("div", {
|
|
269
270
|
className: "relative flex-1 max-w-sm",
|
|
270
|
-
children: [/* @__PURE__ */
|
|
271
|
+
children: [/* @__PURE__ */ m(d, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-text-secondary" }), /* @__PURE__ */ m(S, {
|
|
271
272
|
placeholder: "Search candidates...",
|
|
272
273
|
className: "pl-9",
|
|
273
|
-
value:
|
|
274
|
+
value: g,
|
|
274
275
|
onChange: (e) => {
|
|
275
276
|
M(e.target.value), R(1);
|
|
276
277
|
}
|
|
277
278
|
})]
|
|
278
|
-
}), /* @__PURE__ */
|
|
279
|
+
}), /* @__PURE__ */ h("div", {
|
|
279
280
|
className: "flex gap-1",
|
|
280
|
-
children: [/* @__PURE__ */
|
|
281
|
+
children: [/* @__PURE__ */ m(_, {
|
|
281
282
|
variant: N === "all" ? "default" : "outline",
|
|
282
283
|
size: "sm",
|
|
283
284
|
onClick: () => {
|
|
284
285
|
P("all"), R(1);
|
|
285
286
|
},
|
|
286
287
|
children: "All"
|
|
287
|
-
}), J.map((e) => /* @__PURE__ */
|
|
288
|
+
}), J.map((e) => /* @__PURE__ */ m(_, {
|
|
288
289
|
variant: N === e ? "default" : "outline",
|
|
289
290
|
size: "sm",
|
|
290
291
|
onClick: () => {
|
|
@@ -294,40 +295,40 @@ function j() {
|
|
|
294
295
|
}, e))]
|
|
295
296
|
})]
|
|
296
297
|
}),
|
|
297
|
-
/* @__PURE__ */
|
|
298
|
+
/* @__PURE__ */ m(y, {
|
|
298
299
|
treatment: "glass",
|
|
299
300
|
glow: !0,
|
|
300
301
|
className: "border-border-seam",
|
|
301
|
-
children: /* @__PURE__ */
|
|
302
|
+
children: /* @__PURE__ */ h(v, {
|
|
302
303
|
className: "p-4",
|
|
303
|
-
children: [/* @__PURE__ */
|
|
304
|
+
children: [/* @__PURE__ */ m(T, {
|
|
304
305
|
data: X,
|
|
305
306
|
rowKey: (e) => e.id,
|
|
306
|
-
columns:
|
|
307
|
-
emptyState: /* @__PURE__ */
|
|
307
|
+
columns: j,
|
|
308
|
+
emptyState: /* @__PURE__ */ m(x, {
|
|
308
309
|
illustration: "empty-search",
|
|
309
310
|
title: "No candidates match",
|
|
310
311
|
description: "Try a different search term or status filter."
|
|
311
312
|
}),
|
|
312
|
-
rowActions: (e) => /* @__PURE__ */
|
|
313
|
+
rowActions: (e) => /* @__PURE__ */ h("div", {
|
|
313
314
|
className: "flex items-center justify-end gap-1",
|
|
314
|
-
children: [/* @__PURE__ */
|
|
315
|
+
children: [/* @__PURE__ */ m(_, {
|
|
315
316
|
variant: "ghost",
|
|
316
317
|
size: "sm",
|
|
317
318
|
"aria-label": `Edit ${e.firstName} ${e.lastName}`,
|
|
318
319
|
onClick: () => H(e),
|
|
319
|
-
children: /* @__PURE__ */
|
|
320
|
-
}), /* @__PURE__ */
|
|
320
|
+
children: /* @__PURE__ */ m(l, { className: "h-3.5 w-3.5" })
|
|
321
|
+
}), /* @__PURE__ */ m(_, {
|
|
321
322
|
variant: "ghost",
|
|
322
323
|
size: "sm",
|
|
323
324
|
"aria-label": `Delete ${e.firstName} ${e.lastName}`,
|
|
324
325
|
onClick: () => W(e),
|
|
325
|
-
children: /* @__PURE__ */ p
|
|
326
|
+
children: /* @__PURE__ */ m(p, { className: "h-3.5 w-3.5 text-status-error-fg" })
|
|
326
327
|
})]
|
|
327
328
|
})
|
|
328
|
-
}), Y.length > I && /* @__PURE__ */
|
|
329
|
+
}), Y.length > I && /* @__PURE__ */ m("div", {
|
|
329
330
|
className: "mt-4",
|
|
330
|
-
children: /* @__PURE__ */
|
|
331
|
+
children: /* @__PURE__ */ m(w, {
|
|
331
332
|
page: F,
|
|
332
333
|
pageSize: I,
|
|
333
334
|
totalItems: Y.length,
|
|
@@ -336,28 +337,28 @@ function j() {
|
|
|
336
337
|
})]
|
|
337
338
|
})
|
|
338
339
|
}),
|
|
339
|
-
/* @__PURE__ */
|
|
340
|
+
/* @__PURE__ */ m(n, {
|
|
340
341
|
open: z,
|
|
341
342
|
onOpenChange: B,
|
|
342
343
|
title: "Add Candidate",
|
|
343
344
|
description: "Add someone to your hiring pipeline.",
|
|
344
|
-
fields:
|
|
345
|
+
fields: O,
|
|
345
346
|
submitLabel: "Add candidate",
|
|
346
347
|
onSubmit: G
|
|
347
348
|
}),
|
|
348
|
-
/* @__PURE__ */
|
|
349
|
+
/* @__PURE__ */ m(n, {
|
|
349
350
|
open: V !== null,
|
|
350
351
|
onOpenChange: (e) => {
|
|
351
352
|
e || H(null);
|
|
352
353
|
},
|
|
353
354
|
title: "Edit Candidate",
|
|
354
355
|
description: V ? `${V.firstName} ${V.lastName}` : void 0,
|
|
355
|
-
fields:
|
|
356
|
-
initialValues: V ?
|
|
356
|
+
fields: O,
|
|
357
|
+
initialValues: V ? k(V) : void 0,
|
|
357
358
|
submitLabel: "Save changes",
|
|
358
359
|
onSubmit: K
|
|
359
360
|
}),
|
|
360
|
-
/* @__PURE__ */
|
|
361
|
+
/* @__PURE__ */ m(r, {
|
|
361
362
|
open: U !== null,
|
|
362
363
|
onOpenChange: (e) => {
|
|
363
364
|
e || W(null);
|
|
@@ -372,6 +373,6 @@ function j() {
|
|
|
372
373
|
});
|
|
373
374
|
}
|
|
374
375
|
//#endregion
|
|
375
|
-
export {
|
|
376
|
+
export { M as HiringCandidatesPagePage };
|
|
376
377
|
|
|
377
378
|
//# 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 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\">\n Your candidate pool — search, filter, and evaluate the people you're considering so\n you can fill open roles with the right talent.\n </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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"}
|
|
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';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\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 {formatEnumLabel(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\">\n Your candidate pool — search, filter, and evaluate the people you're considering so\n you can fill open roles with the right talent.\n </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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"}
|