@burdenoff/microfe-crewfoundry 2026.723.2 → 2026.730.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.
@@ -1,3 +1,43 @@
1
- import "./lib/palette.js";
2
- import "./lib/hooks.js";
3
- import "react/jsx-runtime";
1
+ import { ACCENT as e } from "./lib/palette.js";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { useMounted as n, usePrefersReducedMotion as r } from "./lib/hooks.js";
4
+ import { clamp as i } from "./lib/geometry.js";
5
+ import { toPercent as a } from "./lib/format.js";
6
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
7
+ //#region src/crewfoundry/components/viz/SkillBar.tsx
8
+ function c({ label: c, value: l, max: u = 100, levelLabel: d, showPercent: f = !0, color: p = e, height: m = 8, className: h }) {
9
+ let g = n(), _ = r(), v = i(a(l, u, 0), 0, 100), y = d ?? (f ? `${v}%` : null);
10
+ return /* @__PURE__ */ s("div", {
11
+ className: t("flex flex-col gap-1.5", h),
12
+ children: [/* @__PURE__ */ s("div", {
13
+ className: "flex items-baseline justify-between gap-3 text-sm",
14
+ children: [/* @__PURE__ */ o("span", {
15
+ className: "font-medium text-text-primary",
16
+ children: c
17
+ }), y === null ? null : /* @__PURE__ */ o("span", {
18
+ className: "tabular-nums text-text-secondary",
19
+ children: y
20
+ })]
21
+ }), /* @__PURE__ */ o("div", {
22
+ className: "w-full overflow-hidden rounded-full bg-bg-sunken",
23
+ style: { height: m },
24
+ role: "progressbar",
25
+ "aria-valuenow": v,
26
+ "aria-valuemin": 0,
27
+ "aria-valuemax": 100,
28
+ "aria-label": `${c} proficiency`,
29
+ children: /* @__PURE__ */ o("div", {
30
+ className: "h-full rounded-full",
31
+ style: {
32
+ width: g || _ ? `${v}%` : "0%",
33
+ backgroundColor: p,
34
+ transition: _ ? void 0 : "width 700ms cubic-bezier(0.22,1,0.36,1)"
35
+ }
36
+ })
37
+ })]
38
+ });
39
+ }
40
+ //#endregion
41
+ export { c as SkillBar };
42
+
43
+ //# sourceMappingURL=SkillBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillBar.js","names":[],"sources":["../../../../src/crewfoundry/components/viz/SkillBar.tsx"],"sourcesContent":["import { cn } from '../../utils/cn';\nimport { ACCENT } from './lib/palette';\nimport { clamp } from './lib/geometry';\nimport { toPercent } from './lib/format';\nimport { useMounted, usePrefersReducedMotion } from './lib/hooks';\n\nexport interface SkillBarProps {\n label: string;\n value: number;\n max?: number;\n /** Qualitative level shown on the right, e.g. \"Advanced\". */\n levelLabel?: string;\n /** Show the numeric percentage on the right (ignored when levelLabel is set). */\n showPercent?: boolean;\n /** Tokenized fill color; defaults to the product accent. */\n color?: string;\n /** Bar height in pixels. */\n height?: number;\n className?: string;\n}\n\n/** A labeled proficiency bar (skill name + level bar). */\nexport function SkillBar({\n label,\n value,\n max = 100,\n levelLabel,\n showPercent = true,\n color = ACCENT,\n height = 8,\n className,\n}: SkillBarProps) {\n const mounted = useMounted();\n const reduced = usePrefersReducedMotion();\n const pct = clamp(toPercent(value, max, 0), 0, 100);\n const right = levelLabel ?? (showPercent ? `${pct}%` : null);\n\n return (\n <div className={cn('flex flex-col gap-1.5', className)}>\n <div className=\"flex items-baseline justify-between gap-3 text-sm\">\n <span className=\"font-medium text-text-primary\">{label}</span>\n {right !== null ? <span className=\"tabular-nums text-text-secondary\">{right}</span> : null}\n </div>\n <div\n className=\"w-full overflow-hidden rounded-full bg-bg-sunken\"\n style={{ height }}\n role=\"progressbar\"\n aria-valuenow={pct}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={`${label} proficiency`}\n >\n <div\n className=\"h-full rounded-full\"\n style={{\n width: mounted || reduced ? `${pct}%` : '0%',\n backgroundColor: color,\n transition: reduced ? undefined : 'width 700ms cubic-bezier(0.22,1,0.36,1)',\n }}\n />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAsBA,SAAgB,EAAS,EACvB,UACA,UACA,SAAM,KACN,eACA,iBAAc,IACd,WAAQ,GACR,YAAS,GACT,gBACgB;CAChB,IAAM,IAAU,GAAY,EACtB,IAAU,GAAyB,EACnC,IAAM,EAAM,EAAU,GAAO,GAAK,EAAE,EAAE,GAAG,IAAI,EAC7C,IAAQ,MAAe,IAAc,GAAG,EAAI,KAAK;AAEvD,QACE,kBAAC,OAAD;EAAK,WAAW,EAAG,yBAAyB,EAAU;YAAtD,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,QAAD;IAAM,WAAU;cAAiC;IAAa,CAAA,EAC7D,MAAU,OAA2E,OAApE,kBAAC,QAAD;IAAM,WAAU;cAAoC;IAAa,CAAA,CAC/E;MACN,kBAAC,OAAD;GACE,WAAU;GACV,OAAO,EAAE,WAAQ;GACjB,MAAK;GACL,iBAAe;GACf,iBAAe;GACf,iBAAe;GACf,cAAY,GAAG,EAAM;aAErB,kBAAC,OAAD;IACE,WAAU;IACV,OAAO;KACL,OAAO,KAAW,IAAU,GAAG,EAAI,KAAK;KACxC,iBAAiB;KACjB,YAAY,IAAU,KAAA,IAAY;KACnC;IACD,CAAA;GACE,CAAA,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"HiringJobDetailsPagePage.d.ts","sourceRoot":"","sources":["../../../src/crewfoundry/pages/HiringJobDetailsPagePage.tsx"],"names":[],"mappings":"AAyGA,wBAAgB,wBAAwB,gCAqTvC"}
1
+ {"version":3,"file":"HiringJobDetailsPagePage.d.ts","sourceRoot":"","sources":["../../../src/crewfoundry/pages/HiringJobDetailsPagePage.tsx"],"names":[],"mappings":"AAkHA,wBAAgB,wBAAwB,gCAsbvC"}
@@ -1,20 +1,22 @@
1
1
  import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
2
  import { formatEnumLabel as t } from "../utils/formatEnumLabel.js";
3
- import { getInitials as n } from "../components/viz/lib/format.js";
4
- import { HBarFunnel as r } from "../components/viz/HBarFunnel.js";
5
- import { RatingStars as i } from "../components/viz/RatingStars.js";
3
+ import { STATUS as n } from "../components/viz/lib/palette.js";
4
+ import { getInitials as r } from "../components/viz/lib/format.js";
5
+ import { HBarFunnel as i } from "../components/viz/HBarFunnel.js";
6
+ import { RatingStars as a } from "../components/viz/RatingStars.js";
7
+ import { SkillBar as ee } from "../components/viz/SkillBar.js";
6
8
  import "../components/viz/index.js";
7
- import { FormModal as a } from "../components/forms/FormModal.js";
8
- import { ConfirmDialog as o } from "../components/forms/ConfirmDialog.js";
9
- import { getNumber as s, getTags as c, getText as l } from "../components/forms/formValues.js";
10
- import { useState as u } from "react";
11
- import { Briefcase as d, Calendar as f, CheckCircle as p, MapPin as m, Pencil as h, Share2 as g, Trash2 as ee, Users as _ } from "lucide-react";
12
- import { useNavigate as v, useSearchParams as y } from "react-router-dom";
13
- import { jsx as b, jsxs as x } from "react/jsx-runtime";
14
- import { Badge as S, Button as C, Card as w, CardContent as T, CardHeader as E, CardTitle as D, GlassCard as O, GradientText as k, IllustratedEmptyState as A, PagePurpose as j, Spinner as M } from "@burdenoff/fe-libs/ui";
15
- import { useGlobalUi as N } from "@burdenoff/fe-libs/shared/providers/shell";
9
+ import { FormModal as te } from "../components/forms/FormModal.js";
10
+ import { ConfirmDialog as ne } from "../components/forms/ConfirmDialog.js";
11
+ import { getNumber as o, getTags as s, getText as c } from "../components/forms/formValues.js";
12
+ import { useState as l } from "react";
13
+ import { Briefcase as re, Calendar as ie, CheckCircle as u, MapPin as ae, Pencil as d, Share2 as f, Sparkles as p, Trash2 as m, Users as h, XCircle as g } from "lucide-react";
14
+ import { useNavigate as _, useSearchParams as oe } from "react-router-dom";
15
+ import { jsx as v, jsxs as y } from "react/jsx-runtime";
16
+ import { Badge as b, Button as x, Card as S, CardContent as C, CardHeader as w, CardTitle as T, GlassCard as se, GradientText as E, IllustratedEmptyState as D, PagePurpose as O, Spinner as k } from "@burdenoff/fe-libs/ui";
17
+ import { useGlobalUi as A } from "@burdenoff/fe-libs/shared/providers/shell";
16
18
  //#region src/crewfoundry/pages/HiringJobDetailsPagePage.tsx
17
- var P = [
19
+ var j = [
18
20
  {
19
21
  name: "title",
20
22
  label: "Job Title",
@@ -142,7 +144,7 @@ var P = [
142
144
  label: "Benefits",
143
145
  type: "tags"
144
146
  }
145
- ], F = {
147
+ ], M = {
146
148
  new: "outline",
147
149
  screening: "secondary",
148
150
  interview: "secondary",
@@ -151,8 +153,8 @@ var P = [
151
153
  hired: "default",
152
154
  rejected: "destructive"
153
155
  };
154
- function I({ name: e, size: t = 32 }) {
155
- return /* @__PURE__ */ b("span", {
156
+ function N({ name: e, size: t = 32 }) {
157
+ return /* @__PURE__ */ v("span", {
156
158
  className: "inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full border border-border-subtle bg-bg-sunken font-medium text-text-secondary",
157
159
  style: {
158
160
  width: t,
@@ -160,45 +162,45 @@ function I({ name: e, size: t = 32 }) {
160
162
  fontSize: Math.round(t * .36)
161
163
  },
162
164
  "aria-hidden": "true",
163
- children: n(e)
165
+ children: r(e)
164
166
  });
165
167
  }
166
- function L() {
167
- let n = v(), [L] = y(), { showToast: R } = N(), { jobPostings: z, candidates: B, updateJobPosting: V, removeJobPosting: H, initialized: U } = e(), W = L.get("id"), G = W ? z.find((e) => e.id === W) : z[0], [K, q] = u(!1), [J, Y] = u(!1);
168
- if (!U && !G) return /* @__PURE__ */ b("div", {
168
+ function P() {
169
+ let r = _(), [P] = oe(), { showToast: F } = A(), { jobPostings: I, candidates: L, updateJobPosting: R, removeJobPosting: z, initialized: B, jobPostingMatches: V, jobPostingMatchesLoading: H, fetchJobPostingMatches: U } = e(), W = P.get("id"), G = W ? I.find((e) => e.id === W) : I[0], [K, q] = l(!1), [ce, J] = l(!1);
170
+ if (!B && !G) return /* @__PURE__ */ v("div", {
169
171
  className: "flex min-h-[60vh] items-center justify-center p-6",
170
- children: /* @__PURE__ */ b(M, { size: "lg" })
172
+ children: /* @__PURE__ */ v(k, { size: "lg" })
171
173
  });
172
- if (!G) return /* @__PURE__ */ b("div", {
174
+ if (!G) return /* @__PURE__ */ v("div", {
173
175
  className: "p-6",
174
- children: /* @__PURE__ */ b(A, {
176
+ children: /* @__PURE__ */ v(D, {
175
177
  illustration: "empty-search",
176
178
  title: "No job posting found",
177
179
  description: "This job posting is no longer available."
178
180
  })
179
181
  });
180
- let X = G.title.trim().toLowerCase(), Z = B.filter((e) => e.position.trim().toLowerCase() === X), Q = (e) => Z.filter((t) => t.status === e).length, $ = Q("interview"), te = [
182
+ let le = G.title.trim().toLowerCase(), Y = L.filter((e) => e.position.trim().toLowerCase() === le), X = (e) => Y.filter((t) => t.status === e).length, Z = X("interview"), ue = [
181
183
  {
182
184
  label: "Applied",
183
- value: Z.length
185
+ value: Y.length
184
186
  },
185
187
  {
186
188
  label: "Screening",
187
- value: Q("screening")
189
+ value: X("screening")
188
190
  },
189
191
  {
190
192
  label: "Interview",
191
- value: $
193
+ value: Z
192
194
  },
193
195
  {
194
196
  label: "Assessment",
195
- value: Q("assessment")
197
+ value: X("assessment")
196
198
  },
197
199
  {
198
200
  label: "Offer",
199
- value: Q("offer") + Q("hired")
201
+ value: X("offer") + X("hired")
200
202
  }
201
- ], ne = {
203
+ ], de = {
202
204
  title: G.title,
203
205
  department: G.department,
204
206
  location: G.location,
@@ -211,74 +213,98 @@ function L() {
211
213
  description: G.description,
212
214
  requirements: G.requirements,
213
215
  benefits: G.benefits
214
- };
215
- return /* @__PURE__ */ x("div", {
216
+ }, fe = async (e) => {
217
+ let t = {
218
+ title: c(e, "title"),
219
+ department: c(e, "department"),
220
+ location: c(e, "location"),
221
+ type: e.type,
222
+ experienceLevel: e.experienceLevel,
223
+ status: e.status,
224
+ salaryMin: o(e, "salaryMin"),
225
+ salaryMax: o(e, "salaryMax"),
226
+ deadline: c(e, "deadline"),
227
+ description: c(e, "description"),
228
+ requirements: s(e, "requirements"),
229
+ benefits: s(e, "benefits")
230
+ };
231
+ await R(G.id, t), F("Job posting updated", "success");
232
+ }, pe = async () => {
233
+ await z(G.id), F("Job posting deleted", "success"), r("../hiring/jobs-page");
234
+ }, me = async () => {
235
+ try {
236
+ await navigator.clipboard.writeText(window.location.href), F("Job link copied to clipboard", "success");
237
+ } catch {
238
+ F("Could not copy the job link", "error");
239
+ }
240
+ }, he = () => r(`../hiring/applications-page?position=${encodeURIComponent(G.title)}`), Q = V[G.id], $ = Q !== void 0, ge = (e) => e >= 75 ? n.success : e >= 45 ? n.warning : n.danger;
241
+ return /* @__PURE__ */ y("div", {
216
242
  className: "space-y-6 p-6",
217
243
  children: [
218
- /* @__PURE__ */ b(O, {
244
+ /* @__PURE__ */ v(se, {
219
245
  treatment: "glass",
220
246
  glow: !0,
221
247
  className: "border-border-seam",
222
- children: /* @__PURE__ */ x(T, {
248
+ children: /* @__PURE__ */ y(C, {
223
249
  className: "flex flex-col gap-4 p-6 lg:flex-row lg:items-start lg:justify-between",
224
- children: [/* @__PURE__ */ x("div", {
250
+ children: [/* @__PURE__ */ y("div", {
225
251
  className: "min-w-0",
226
252
  children: [
227
- /* @__PURE__ */ x("div", {
253
+ /* @__PURE__ */ y("div", {
228
254
  className: "mb-1 flex flex-wrap items-center gap-2",
229
- children: [/* @__PURE__ */ b("h1", {
255
+ children: [/* @__PURE__ */ v("h1", {
230
256
  className: "text-2xl font-semibold",
231
- children: /* @__PURE__ */ b(k, { children: G.title })
232
- }), /* @__PURE__ */ b(S, {
257
+ children: /* @__PURE__ */ v(E, { children: G.title })
258
+ }), /* @__PURE__ */ v(b, {
233
259
  variant: G.status === "active" ? "default" : "secondary",
234
260
  children: t(G.status)
235
261
  })]
236
262
  }),
237
- /* @__PURE__ */ x("div", {
263
+ /* @__PURE__ */ y("div", {
238
264
  className: "flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-text-secondary",
239
265
  children: [
240
- /* @__PURE__ */ x("span", {
266
+ /* @__PURE__ */ y("span", {
241
267
  className: "flex items-center gap-1",
242
- children: [/* @__PURE__ */ b(d, { className: "h-3.5 w-3.5" }), G.department]
268
+ children: [/* @__PURE__ */ v(re, { className: "h-3.5 w-3.5" }), G.department]
243
269
  }),
244
- /* @__PURE__ */ x("span", {
270
+ /* @__PURE__ */ y("span", {
245
271
  className: "flex items-center gap-1",
246
- children: [/* @__PURE__ */ b(m, { className: "h-3.5 w-3.5" }), G.location]
272
+ children: [/* @__PURE__ */ v(ae, { className: "h-3.5 w-3.5" }), G.location]
247
273
  }),
248
- /* @__PURE__ */ b("span", { children: t(G.type) })
274
+ /* @__PURE__ */ v("span", { children: t(G.type) })
249
275
  ]
250
276
  }),
251
- /* @__PURE__ */ x("div", {
277
+ /* @__PURE__ */ y("div", {
252
278
  className: "mt-2 flex flex-wrap items-center gap-2 text-xs text-text-secondary",
253
279
  children: [
254
- /* @__PURE__ */ x(S, {
280
+ /* @__PURE__ */ y(b, {
255
281
  variant: "secondary",
256
282
  className: "text-[10px]",
257
- children: [Z.length, " applicants"]
283
+ children: [Y.length, " applicants"]
258
284
  }),
259
- $ > 0 && /* @__PURE__ */ x(S, {
285
+ Z > 0 && /* @__PURE__ */ y(b, {
260
286
  variant: "secondary",
261
287
  className: "text-[10px]",
262
- children: [$, " in interview"]
288
+ children: [Z, " in interview"]
263
289
  }),
264
- /* @__PURE__ */ x("span", {
290
+ /* @__PURE__ */ y("span", {
265
291
  className: "flex items-center gap-1",
266
292
  children: [
267
- /* @__PURE__ */ b(f, { className: "h-3 w-3" }),
293
+ /* @__PURE__ */ v(ie, { className: "h-3 w-3" }),
268
294
  "Posted ",
269
295
  G.postedDate
270
296
  ]
271
297
  })
272
298
  ]
273
299
  }),
274
- /* @__PURE__ */ b(j, {
300
+ /* @__PURE__ */ v(O, {
275
301
  className: "mt-3",
276
302
  children: "Everything about this role in one place — review applicants, requirements, and compensation to decide who to interview and keep the posting current."
277
303
  })
278
304
  ]
279
- }), /* @__PURE__ */ x("div", {
305
+ }), /* @__PURE__ */ y("div", {
280
306
  className: "flex shrink-0 flex-col items-start gap-3 lg:items-end",
281
- children: [/* @__PURE__ */ x("div", {
307
+ children: [/* @__PURE__ */ y("div", {
282
308
  className: "text-2xl font-bold tabular-nums text-text-primary",
283
309
  children: [
284
310
  "$",
@@ -287,90 +313,179 @@ function L() {
287
313
  (G.salaryMax / 1e3).toFixed(0),
288
314
  "k"
289
315
  ]
290
- }), /* @__PURE__ */ x("div", {
316
+ }), /* @__PURE__ */ y("div", {
291
317
  className: "flex flex-wrap gap-2",
292
318
  children: [
293
- /* @__PURE__ */ x(C, {
319
+ /* @__PURE__ */ y(x, {
294
320
  variant: "outline",
295
321
  size: "sm",
296
- onClick: async () => {
297
- try {
298
- await navigator.clipboard.writeText(window.location.href), R("Job link copied to clipboard", "success");
299
- } catch {
300
- R("Could not copy the job link", "error");
301
- }
302
- },
303
- children: [/* @__PURE__ */ b(g, { className: "mr-1 h-4 w-4" }), "Share"]
322
+ onClick: me,
323
+ children: [/* @__PURE__ */ v(f, { className: "mr-1 h-4 w-4" }), "Share"]
304
324
  }),
305
- /* @__PURE__ */ x(C, {
325
+ /* @__PURE__ */ y(x, {
306
326
  variant: "outline",
307
327
  size: "sm",
308
328
  onClick: () => q(!0),
309
- children: [/* @__PURE__ */ b(h, { className: "mr-1 h-4 w-4" }), "Edit"]
329
+ children: [/* @__PURE__ */ v(d, { className: "mr-1 h-4 w-4" }), "Edit"]
310
330
  }),
311
- /* @__PURE__ */ b(C, {
331
+ /* @__PURE__ */ v(x, {
312
332
  variant: "destructive",
313
333
  size: "sm",
314
334
  "aria-label": "Delete job posting",
315
- onClick: () => Y(!0),
316
- children: /* @__PURE__ */ b(ee, { className: "h-4 w-4" })
335
+ onClick: () => J(!0),
336
+ children: /* @__PURE__ */ v(m, { className: "h-4 w-4" })
317
337
  }),
318
- /* @__PURE__ */ x(C, {
338
+ /* @__PURE__ */ y(x, {
319
339
  size: "sm",
320
- onClick: () => n(`../hiring/applications-page?position=${encodeURIComponent(G.title)}`),
321
- children: [/* @__PURE__ */ b(_, { className: "mr-1 h-4 w-4" }), "View Applications"]
340
+ onClick: he,
341
+ children: [/* @__PURE__ */ v(h, { className: "mr-1 h-4 w-4" }), "View Applications"]
322
342
  })
323
343
  ]
324
344
  })]
325
345
  })]
326
346
  })
327
347
  }),
328
- /* @__PURE__ */ x("div", {
348
+ /* @__PURE__ */ y("div", {
329
349
  className: "grid gap-6 lg:grid-cols-3",
330
- children: [/* @__PURE__ */ x("div", {
350
+ children: [/* @__PURE__ */ y("div", {
331
351
  className: "space-y-6 lg:col-span-2",
332
352
  children: [
333
- /* @__PURE__ */ x(w, { children: [/* @__PURE__ */ b(E, { children: /* @__PURE__ */ b(D, { children: "Description" }) }), /* @__PURE__ */ b(T, { children: /* @__PURE__ */ b("p", {
353
+ /* @__PURE__ */ y(S, { children: [/* @__PURE__ */ v(w, { children: /* @__PURE__ */ v(T, { children: "Description" }) }), /* @__PURE__ */ v(C, { children: /* @__PURE__ */ v("p", {
334
354
  className: "text-sm leading-relaxed text-text-secondary",
335
355
  children: G.description
336
356
  }) })] }),
337
- /* @__PURE__ */ x(w, { children: [/* @__PURE__ */ b(E, { children: /* @__PURE__ */ b(D, { children: "Requirements" }) }), /* @__PURE__ */ b(T, { children: G.requirements.length === 0 ? /* @__PURE__ */ b("p", {
357
+ /* @__PURE__ */ y(S, { children: [/* @__PURE__ */ v(w, { children: /* @__PURE__ */ v(T, { children: "Requirements" }) }), /* @__PURE__ */ v(C, { children: G.requirements.length === 0 ? /* @__PURE__ */ v("p", {
338
358
  className: "text-sm text-text-muted",
339
359
  children: "No requirements listed."
340
- }) : /* @__PURE__ */ b("ul", {
360
+ }) : /* @__PURE__ */ v("ul", {
341
361
  className: "space-y-2",
342
- children: G.requirements.map((e, t) => /* @__PURE__ */ x("li", {
362
+ children: G.requirements.map((e, t) => /* @__PURE__ */ y("li", {
343
363
  className: "flex items-start gap-2 text-sm",
344
- children: [/* @__PURE__ */ b(p, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-status-success-text" }), e]
364
+ children: [/* @__PURE__ */ v(u, { className: "mt-0.5 h-4 w-4 flex-shrink-0 text-status-success-text" }), e]
345
365
  }, t))
346
366
  }) })] }),
347
- /* @__PURE__ */ x(w, { children: [/* @__PURE__ */ b(E, { children: /* @__PURE__ */ b(D, { children: "Benefits" }) }), /* @__PURE__ */ b(T, { children: G.benefits.length === 0 ? /* @__PURE__ */ b("p", {
367
+ /* @__PURE__ */ y(S, { children: [/* @__PURE__ */ v(w, { children: /* @__PURE__ */ v(T, { children: "Benefits" }) }), /* @__PURE__ */ v(C, { children: G.benefits.length === 0 ? /* @__PURE__ */ v("p", {
348
368
  className: "text-sm text-text-muted",
349
369
  children: "No benefits listed."
350
- }) : /* @__PURE__ */ b("div", {
370
+ }) : /* @__PURE__ */ v("div", {
351
371
  className: "flex flex-wrap gap-2",
352
- children: G.benefits.map((e, t) => /* @__PURE__ */ b(S, {
372
+ children: G.benefits.map((e, t) => /* @__PURE__ */ v(b, {
353
373
  variant: "outline",
354
374
  className: "rounded-full px-3 py-1 text-xs",
355
375
  children: e
356
376
  }, t))
377
+ }) })] }),
378
+ /* @__PURE__ */ y(S, { children: [/* @__PURE__ */ y(w, {
379
+ className: "flex flex-row items-center justify-between gap-3",
380
+ children: [/* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v(T, { children: "Suggested Matches" }), /* @__PURE__ */ v("p", {
381
+ className: "mt-1 text-xs text-text-muted",
382
+ children: "Rule-based scoring — skill overlap (70%) + experience fit (30%) against this role's requirements. Not an AI-generated summary."
383
+ })] }), /* @__PURE__ */ y(x, {
384
+ size: "sm",
385
+ variant: "outline",
386
+ onClick: async () => {
387
+ try {
388
+ await U(G.id);
389
+ } catch {
390
+ F("Unable to generate candidate matches", "error");
391
+ }
392
+ },
393
+ disabled: H,
394
+ children: [/* @__PURE__ */ v(p, { className: "mr-1 h-4 w-4" }), $ ? "Refresh matches" : "Generate matches"]
395
+ })]
396
+ }), /* @__PURE__ */ v(C, { children: H ? /* @__PURE__ */ v("div", {
397
+ className: "flex items-center justify-center py-6",
398
+ children: /* @__PURE__ */ v(k, { size: "md" })
399
+ }) : $ ? Q.length === 0 ? /* @__PURE__ */ v("p", {
400
+ className: "text-sm text-text-muted",
401
+ children: "No candidates in the pool right now (excluding already-hired/rejected)."
402
+ }) : /* @__PURE__ */ v("ul", {
403
+ className: "space-y-4",
404
+ children: Q.map((e) => /* @__PURE__ */ y("li", {
405
+ className: "rounded-[var(--radius-card)] border border-border-subtle bg-bg-surface p-3",
406
+ children: [
407
+ /* @__PURE__ */ y("div", {
408
+ className: "flex items-center gap-2",
409
+ children: [
410
+ /* @__PURE__ */ v(N, {
411
+ name: `${e.candidate.firstName} ${e.candidate.lastName}`,
412
+ size: 28
413
+ }),
414
+ /* @__PURE__ */ y("span", {
415
+ className: "min-w-0 flex-1 truncate text-sm font-medium text-text-primary",
416
+ children: [
417
+ e.candidate.firstName,
418
+ " ",
419
+ e.candidate.lastName
420
+ ]
421
+ }),
422
+ /* @__PURE__ */ v(b, {
423
+ variant: M[e.candidate.status],
424
+ className: "shrink-0 text-[9px]",
425
+ children: t(e.candidate.status)
426
+ })
427
+ ]
428
+ }),
429
+ /* @__PURE__ */ v("div", {
430
+ className: "mt-2",
431
+ children: /* @__PURE__ */ v(ee, {
432
+ label: "Overall match",
433
+ value: e.score,
434
+ levelLabel: `${e.score}%`,
435
+ color: ge(e.score),
436
+ height: 6
437
+ })
438
+ }),
439
+ /* @__PURE__ */ y("div", {
440
+ className: "mt-2 grid grid-cols-2 gap-2 text-xs text-text-secondary",
441
+ children: [/* @__PURE__ */ y("span", { children: [
442
+ "Skills: ",
443
+ e.skillScore,
444
+ "%"
445
+ ] }), /* @__PURE__ */ y("span", { children: [
446
+ "Experience: ",
447
+ e.experienceScore,
448
+ "%"
449
+ ] })]
450
+ }),
451
+ (e.matchedSkills.length > 0 || e.missingSkills.length > 0) && /* @__PURE__ */ y("div", {
452
+ className: "mt-2 flex flex-wrap gap-1",
453
+ children: [e.matchedSkills.map((e) => /* @__PURE__ */ y(b, {
454
+ variant: "secondary",
455
+ className: "gap-1 text-[10px]",
456
+ children: [/* @__PURE__ */ v(u, { className: "h-3 w-3 text-status-success-text" }), e]
457
+ }, `m-${e}`)), e.missingSkills.map((e) => /* @__PURE__ */ y(b, {
458
+ variant: "outline",
459
+ className: "gap-1 text-[10px] text-text-muted",
460
+ children: [/* @__PURE__ */ v(g, { className: "h-3 w-3 text-status-error-text" }), e]
461
+ }, `x-${e}`))]
462
+ }),
463
+ /* @__PURE__ */ v("p", {
464
+ className: "mt-2 text-xs leading-relaxed text-text-muted",
465
+ children: e.rationale
466
+ })
467
+ ]
468
+ }, e.candidateId))
469
+ }) : /* @__PURE__ */ v("p", {
470
+ className: "text-sm text-text-muted",
471
+ children: "Click \"Generate matches\" to rank the candidate pool against this posting's requirements and experience level."
357
472
  }) })] })
358
473
  ]
359
- }), /* @__PURE__ */ x("div", {
474
+ }), /* @__PURE__ */ y("div", {
360
475
  className: "space-y-6",
361
- children: [/* @__PURE__ */ x(w, { children: [/* @__PURE__ */ b(E, { children: /* @__PURE__ */ b(D, { children: "Candidates" }) }), /* @__PURE__ */ b(T, { children: Z.length === 0 ? /* @__PURE__ */ b("p", {
476
+ children: [/* @__PURE__ */ y(S, { children: [/* @__PURE__ */ v(w, { children: /* @__PURE__ */ v(T, { children: "Candidates" }) }), /* @__PURE__ */ v(C, { children: Y.length === 0 ? /* @__PURE__ */ v("p", {
362
477
  className: "text-sm text-text-muted",
363
478
  children: "No applicants matched to this role yet."
364
- }) : /* @__PURE__ */ b("ul", {
479
+ }) : /* @__PURE__ */ v("ul", {
365
480
  className: "max-h-96 space-y-1 overflow-y-auto pr-1",
366
- children: Z.map((e) => /* @__PURE__ */ x("li", {
481
+ children: Y.map((e) => /* @__PURE__ */ y("li", {
367
482
  className: "flex items-center gap-2 rounded-[var(--radius-input)] px-2 py-2 hover:bg-bg-sunken",
368
483
  children: [
369
- /* @__PURE__ */ b(I, {
484
+ /* @__PURE__ */ v(N, {
370
485
  name: `${e.firstName} ${e.lastName}`,
371
486
  size: 30
372
487
  }),
373
- /* @__PURE__ */ x("span", {
488
+ /* @__PURE__ */ y("span", {
374
489
  className: "min-w-0 flex-1 truncate text-sm font-medium text-text-primary",
375
490
  children: [
376
491
  e.firstName,
@@ -378,69 +493,51 @@ function L() {
378
493
  e.lastName
379
494
  ]
380
495
  }),
381
- /* @__PURE__ */ b(S, {
382
- variant: F[e.status],
496
+ /* @__PURE__ */ v(b, {
497
+ variant: M[e.status],
383
498
  className: "shrink-0 text-[9px]",
384
499
  children: t(e.status)
385
500
  }),
386
- /* @__PURE__ */ b(i, {
501
+ /* @__PURE__ */ v(a, {
387
502
  value: e.rating,
388
503
  size: 12,
389
504
  className: "shrink-0"
390
505
  })
391
506
  ]
392
507
  }, e.id))
393
- }) })] }), /* @__PURE__ */ x(w, { children: [/* @__PURE__ */ b(E, { children: /* @__PURE__ */ b(D, { children: "Hiring funnel" }) }), /* @__PURE__ */ b(T, { children: Z.length === 0 ? /* @__PURE__ */ b("p", {
508
+ }) })] }), /* @__PURE__ */ y(S, { children: [/* @__PURE__ */ v(w, { children: /* @__PURE__ */ v(T, { children: "Hiring funnel" }) }), /* @__PURE__ */ v(C, { children: Y.length === 0 ? /* @__PURE__ */ v("p", {
394
509
  className: "text-sm text-text-muted",
395
510
  children: "The funnel appears once candidates apply to this role."
396
- }) : /* @__PURE__ */ b(r, {
397
- stages: te,
511
+ }) : /* @__PURE__ */ v(i, {
512
+ stages: ue,
398
513
  valueFormatter: (e) => String(e),
399
514
  showConversion: !0
400
515
  }) })] })]
401
516
  })]
402
517
  }),
403
- /* @__PURE__ */ b(a, {
518
+ /* @__PURE__ */ v(te, {
404
519
  open: K,
405
520
  onOpenChange: q,
406
521
  title: "Edit Job Posting",
407
522
  description: "Update the role details, compensation, and status.",
408
- fields: P,
409
- initialValues: ne,
523
+ fields: j,
524
+ initialValues: de,
410
525
  submitLabel: "Save changes",
411
- onSubmit: async (e) => {
412
- let t = {
413
- title: l(e, "title"),
414
- department: l(e, "department"),
415
- location: l(e, "location"),
416
- type: e.type,
417
- experienceLevel: e.experienceLevel,
418
- status: e.status,
419
- salaryMin: s(e, "salaryMin"),
420
- salaryMax: s(e, "salaryMax"),
421
- deadline: l(e, "deadline"),
422
- description: l(e, "description"),
423
- requirements: c(e, "requirements"),
424
- benefits: c(e, "benefits")
425
- };
426
- await V(G.id, t), R("Job posting updated", "success");
427
- }
526
+ onSubmit: fe
428
527
  }),
429
- /* @__PURE__ */ b(o, {
430
- open: J,
431
- onOpenChange: Y,
528
+ /* @__PURE__ */ v(ne, {
529
+ open: ce,
530
+ onOpenChange: J,
432
531
  title: "Delete job posting",
433
532
  description: `Permanently remove “${G.title}”? This cannot be undone.`,
434
533
  confirmLabel: "Delete",
435
534
  destructive: !0,
436
- onConfirm: async () => {
437
- await H(G.id), R("Job posting deleted", "success"), n("../hiring/jobs-page");
438
- }
535
+ onConfirm: pe
439
536
  })
440
537
  ]
441
538
  });
442
539
  }
443
540
  //#endregion
444
- export { L as HiringJobDetailsPagePage };
541
+ export { P as HiringJobDetailsPagePage };
445
542
 
446
543
  //# sourceMappingURL=HiringJobDetailsPagePage.js.map