@burdenoff/microfe-crewfoundry 2026.704.5 → 2026.704.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crewfoundry/CrewFoundryRoutes.js +51 -43
- package/dist/crewfoundry/CrewFoundryRoutes.js.map +1 -1
- package/dist/crewfoundry/components/forms/formValues.js +5 -2
- package/dist/crewfoundry/components/forms/formValues.js.map +1 -1
- package/dist/crewfoundry/components/viz/AllocationBar.js +68 -0
- package/dist/crewfoundry/components/viz/AllocationBar.js.map +1 -0
- package/dist/crewfoundry/components/viz/AreaChart.js +102 -0
- package/dist/crewfoundry/components/viz/AreaChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/AvatarStack.js +36 -0
- package/dist/crewfoundry/components/viz/AvatarStack.js.map +1 -0
- package/dist/crewfoundry/components/viz/BarChart.js +83 -0
- package/dist/crewfoundry/components/viz/BarChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/CertificateCard.js +118 -0
- package/dist/crewfoundry/components/viz/CertificateCard.js.map +1 -0
- package/dist/crewfoundry/components/viz/DonutChart.js +109 -0
- package/dist/crewfoundry/components/viz/DonutChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/HBarFunnel.js +54 -0
- package/dist/crewfoundry/components/viz/HBarFunnel.js.map +1 -0
- package/dist/crewfoundry/components/viz/Heatmap.js +91 -0
- package/dist/crewfoundry/components/viz/Heatmap.js.map +1 -0
- package/dist/crewfoundry/components/viz/KanbanBoard.js +50 -0
- package/dist/crewfoundry/components/viz/KanbanBoard.js.map +1 -0
- package/dist/crewfoundry/components/viz/LineChart.js +123 -0
- package/dist/crewfoundry/components/viz/LineChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/OrgTree.js +83 -0
- package/dist/crewfoundry/components/viz/OrgTree.js.map +1 -0
- package/dist/crewfoundry/components/viz/PathSteps.js +68 -0
- package/dist/crewfoundry/components/viz/PathSteps.js.map +1 -0
- package/dist/crewfoundry/components/viz/ProgressRing.js +68 -0
- package/dist/crewfoundry/components/viz/ProgressRing.js.map +1 -0
- package/dist/crewfoundry/components/viz/RatingStars.js +51 -0
- package/dist/crewfoundry/components/viz/RatingStars.js.map +1 -0
- package/dist/crewfoundry/components/viz/SegmentedTabs.js +69 -0
- package/dist/crewfoundry/components/viz/SegmentedTabs.js.map +1 -0
- package/dist/crewfoundry/components/viz/SkillBar.js +3 -0
- package/dist/crewfoundry/components/viz/Sparkline.js +74 -0
- package/dist/crewfoundry/components/viz/Sparkline.js.map +1 -0
- package/dist/crewfoundry/components/viz/StatCard.js +60 -0
- package/dist/crewfoundry/components/viz/StatCard.js.map +1 -0
- package/dist/crewfoundry/components/viz/StepProgress.js +3 -0
- package/dist/crewfoundry/components/viz/Timeline.js +66 -0
- package/dist/crewfoundry/components/viz/Timeline.js.map +1 -0
- package/dist/crewfoundry/components/viz/index.js +23 -0
- package/dist/crewfoundry/components/viz/lib/Avatar.js +30 -0
- package/dist/crewfoundry/components/viz/lib/Avatar.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/CartesianFrame.js +119 -0
- package/dist/crewfoundry/components/viz/lib/CartesianFrame.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js +35 -0
- package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/format.js +21 -0
- package/dist/crewfoundry/components/viz/lib/format.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/geometry.js +69 -0
- package/dist/crewfoundry/components/viz/lib/geometry.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/hooks.js +39 -0
- package/dist/crewfoundry/components/viz/lib/hooks.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/palette.js +27 -0
- package/dist/crewfoundry/components/viz/lib/palette.js.map +1 -0
- package/dist/crewfoundry/lib/analytics.js +323 -0
- package/dist/crewfoundry/lib/analytics.js.map +1 -0
- package/dist/crewfoundry/lib/companyFinance.js +16 -0
- package/dist/crewfoundry/lib/companyFinance.js.map +1 -0
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +226 -283
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +107 -120
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +122 -162
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +121 -158
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +316 -211
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +75 -27
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +167 -165
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +168 -109
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +401 -290
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +84 -75
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +368 -174
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +236 -201
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +369 -196
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +252 -249
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +210 -110
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +216 -178
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js +385 -0
- package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js.map +1 -0
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js +189 -130
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +397 -241
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +262 -147
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +345 -167
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +98 -24
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +35 -31
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +289 -108
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +221 -114
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +136 -133
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +148 -97
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +264 -157
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +85 -93
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +211 -122
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +94 -54
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +28 -25
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +290 -138
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +169 -79
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +65 -61
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +296 -125
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js +187 -0
- package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js.map +1 -0
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +142 -76
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +93 -43
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +250 -98
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
- package/dist/crewfoundry/utils/cn.js +10 -0
- package/dist/crewfoundry/utils/cn.js.map +1 -0
- package/dist/crewfoundry/utils/courseProgress.js +46 -0
- package/dist/crewfoundry/utils/courseProgress.js.map +1 -0
- package/dist/node_modules/clsx/dist/clsx.js +18 -0
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
2
|
import { newClientId as t } from "../components/forms/formValues.js";
|
|
3
|
-
import {
|
|
4
|
-
import { Briefcase as
|
|
5
|
-
import { useNavigate as
|
|
6
|
-
import { jsx as
|
|
7
|
-
import { Button as
|
|
8
|
-
import { useGlobalUi as
|
|
3
|
+
import { useMemo as n, useState as r } from "react";
|
|
4
|
+
import { Briefcase as i, ChevronRight as a, Plus as o, Save as s, X as c } from "lucide-react";
|
|
5
|
+
import { useNavigate as l } from "react-router-dom";
|
|
6
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
7
|
+
import { Button as f, GlassCard as ee, GradientText as p, Input as m, PagePurpose as h, Textarea as g } from "@burdenoff/fe-libs/ui";
|
|
8
|
+
import { useGlobalUi as _ } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
9
9
|
//#region src/crewfoundry/pages/HiringCreateJobPagePage.tsx
|
|
10
|
-
var
|
|
10
|
+
var v = "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", y = "text-sm font-medium text-text-primary", b = [
|
|
11
11
|
{
|
|
12
12
|
label: "Full time",
|
|
13
13
|
value: "full_time"
|
|
@@ -24,7 +24,7 @@ var x = "flex h-10 w-full rounded-input border border-border-default bg-bg-surfa
|
|
|
24
24
|
label: "Remote",
|
|
25
25
|
value: "remote"
|
|
26
26
|
}
|
|
27
|
-
],
|
|
27
|
+
], x = [
|
|
28
28
|
{
|
|
29
29
|
label: "Entry",
|
|
30
30
|
value: "entry"
|
|
@@ -46,21 +46,22 @@ var x = "flex h-10 w-full rounded-input border border-border-default bg-bg-surfa
|
|
|
46
46
|
value: "executive"
|
|
47
47
|
}
|
|
48
48
|
];
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
function S({ htmlFor: e, children: t }) {
|
|
50
|
+
return /* @__PURE__ */ u("label", {
|
|
51
|
+
className: y,
|
|
52
|
+
htmlFor: e,
|
|
53
|
+
children: t
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function C() {
|
|
57
|
+
let C = l(), { showToast: w } = _(), T = e((e) => e.addJobPosting), E = e((e) => e.departments), [D, O] = r(""), [k, A] = r(""), [j, te] = r(""), [M, N] = r(""), [P, F] = r("full_time"), [I, L] = r("mid"), [R, z] = r(""), [B, V] = r(""), [H, U] = r(""), [W, G] = r([""]), [K, q] = r([""]), [J, Y] = r(!1), X = n(() => Array.from(new Set(E.map((e) => e.name).filter(Boolean))).sort(), [E]), Z = () => G((e) => [...e, ""]), ne = () => q((e) => [...e, ""]), re = (e, t) => G((n) => n.map((n, r) => r === e ? t : n)), ie = (e, t) => q((n) => n.map((n, r) => r === e ? t : n)), ae = (e) => G((t) => t.filter((t, n) => n !== e)), oe = (e) => q((t) => t.filter((t, n) => n !== e)), Q = async (e) => {
|
|
57
58
|
if (J) return;
|
|
58
59
|
if (!D.trim()) {
|
|
59
|
-
|
|
60
|
+
w("Job Title is required", "warning");
|
|
60
61
|
return;
|
|
61
62
|
}
|
|
62
63
|
if (!k.trim()) {
|
|
63
|
-
|
|
64
|
+
w("Department is required", "warning");
|
|
64
65
|
return;
|
|
65
66
|
}
|
|
66
67
|
let n = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), r = {
|
|
@@ -76,242 +77,276 @@ function w() {
|
|
|
76
77
|
applicants: 0,
|
|
77
78
|
postedDate: n,
|
|
78
79
|
deadline: H.trim() === "" ? n : H,
|
|
79
|
-
description:
|
|
80
|
+
description: M.trim(),
|
|
80
81
|
requirements: W.map((e) => e.trim()).filter(Boolean),
|
|
81
82
|
benefits: K.map((e) => e.trim()).filter(Boolean)
|
|
82
83
|
};
|
|
83
84
|
Y(!0);
|
|
84
85
|
try {
|
|
85
|
-
await
|
|
86
|
+
await T(r), w(e === "draft" ? "Draft saved" : "Job published", "success"), C("../hiring/jobs-page");
|
|
86
87
|
} catch (e) {
|
|
87
|
-
|
|
88
|
+
w(e instanceof Error ? e.message : "Unable to save job posting", "error");
|
|
88
89
|
} finally {
|
|
89
90
|
Y(!1);
|
|
90
91
|
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
/* @__PURE__ */
|
|
96
|
-
className: "
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
92
|
+
}, $ = (e, t, n, r, i, a) => /* @__PURE__ */ d("div", {
|
|
93
|
+
className: "space-y-2",
|
|
94
|
+
children: [e.map((e, r) => /* @__PURE__ */ d("div", {
|
|
95
|
+
className: "relative",
|
|
96
|
+
children: [/* @__PURE__ */ u(m, {
|
|
97
|
+
className: "pr-9",
|
|
98
|
+
placeholder: a,
|
|
99
|
+
value: e,
|
|
100
|
+
onChange: (e) => t(r, e.target.value)
|
|
101
|
+
}), /* @__PURE__ */ u("button", {
|
|
102
|
+
type: "button",
|
|
103
|
+
"aria-label": `Remove ${i.toLowerCase()} ${r + 1}`,
|
|
104
|
+
onClick: () => n(r),
|
|
105
|
+
className: "absolute right-2.5 top-1/2 -translate-y-1/2 rounded-sm p-0.5 text-text-secondary transition-colors hover:text-text-primary focus-visible:outline-none focus-visible:text-text-primary",
|
|
106
|
+
children: /* @__PURE__ */ u(c, { className: "h-4 w-4" })
|
|
107
|
+
})]
|
|
108
|
+
}, r)), /* @__PURE__ */ d(f, {
|
|
109
|
+
variant: "link",
|
|
110
|
+
size: "sm",
|
|
111
|
+
className: "h-auto p-0",
|
|
112
|
+
onClick: r,
|
|
113
|
+
type: "button",
|
|
114
|
+
children: [
|
|
115
|
+
/* @__PURE__ */ u(o, { className: "h-4 w-4 mr-1" }),
|
|
116
|
+
"Add ",
|
|
117
|
+
i
|
|
118
|
+
]
|
|
119
|
+
})]
|
|
120
|
+
});
|
|
121
|
+
return /* @__PURE__ */ d("div", {
|
|
122
|
+
className: "space-y-6 p-6",
|
|
123
|
+
children: [/* @__PURE__ */ d("div", {
|
|
124
|
+
className: "space-y-2",
|
|
125
|
+
children: [/* @__PURE__ */ d("nav", {
|
|
126
|
+
"aria-label": "Breadcrumb",
|
|
127
|
+
className: "flex items-center gap-1 text-sm text-text-secondary",
|
|
128
|
+
children: [
|
|
129
|
+
/* @__PURE__ */ u("button", {
|
|
130
|
+
type: "button",
|
|
131
|
+
onClick: () => C("../hiring/jobs-page"),
|
|
132
|
+
className: "rounded-sm transition-colors hover:text-text-primary focus-visible:outline-none focus-visible:text-text-primary",
|
|
133
|
+
children: "Hiring"
|
|
105
134
|
}),
|
|
106
|
-
/* @__PURE__ */
|
|
107
|
-
|
|
108
|
-
|
|
135
|
+
/* @__PURE__ */ u(a, { className: "h-3.5 w-3.5" }),
|
|
136
|
+
/* @__PURE__ */ u("span", {
|
|
137
|
+
className: "text-text-primary",
|
|
138
|
+
children: "Post New Job"
|
|
109
139
|
})
|
|
110
|
-
]
|
|
111
|
-
}),
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
140
|
+
]
|
|
141
|
+
}), /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("h1", {
|
|
142
|
+
className: "text-2xl font-semibold",
|
|
143
|
+
children: /* @__PURE__ */ u(p, { children: "Create Job Posting" })
|
|
144
|
+
}), /* @__PURE__ */ u(h, {
|
|
145
|
+
className: "mt-1",
|
|
146
|
+
children: "Create a new job posting — define the role, requirements, and compensation here to start attracting and collecting applicants."
|
|
147
|
+
})] })]
|
|
148
|
+
}), /* @__PURE__ */ d(ee, {
|
|
149
|
+
treatment: "glass",
|
|
150
|
+
className: "max-w-5xl p-6",
|
|
151
|
+
children: [/* @__PURE__ */ d("div", {
|
|
152
|
+
className: "mb-6 flex items-center gap-2 text-lg font-semibold text-text-primary",
|
|
153
|
+
children: [/* @__PURE__ */ u(i, { className: "h-5 w-5" }), "Job details"]
|
|
154
|
+
}), /* @__PURE__ */ d("div", {
|
|
155
|
+
className: "space-y-5",
|
|
117
156
|
children: [
|
|
118
|
-
/* @__PURE__ */
|
|
119
|
-
className: "
|
|
120
|
-
children: [/* @__PURE__ */
|
|
121
|
-
className: "text-sm font-medium",
|
|
122
|
-
htmlFor: "job-title",
|
|
123
|
-
children: "Job Title"
|
|
124
|
-
}), /* @__PURE__ */ s(_, {
|
|
125
|
-
id: "job-title",
|
|
126
|
-
placeholder: "e.g. Senior Frontend Developer",
|
|
127
|
-
value: D,
|
|
128
|
-
onChange: (e) => O(e.target.value)
|
|
129
|
-
})]
|
|
130
|
-
}),
|
|
131
|
-
/* @__PURE__ */ c("div", {
|
|
132
|
-
className: "grid grid-cols-1 sm:grid-cols-2 gap-4",
|
|
133
|
-
children: [/* @__PURE__ */ c("div", {
|
|
157
|
+
/* @__PURE__ */ d("div", {
|
|
158
|
+
className: "grid grid-cols-1 gap-5 md:grid-cols-2",
|
|
159
|
+
children: [/* @__PURE__ */ d("div", {
|
|
134
160
|
className: "space-y-2",
|
|
135
|
-
children: [/* @__PURE__ */
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
onChange: (e) => A(e.target.value)
|
|
161
|
+
children: [/* @__PURE__ */ u(S, {
|
|
162
|
+
htmlFor: "job-title",
|
|
163
|
+
children: "Job Title"
|
|
164
|
+
}), /* @__PURE__ */ u(m, {
|
|
165
|
+
id: "job-title",
|
|
166
|
+
placeholder: "e.g. Senior Frontend Developer",
|
|
167
|
+
value: D,
|
|
168
|
+
onChange: (e) => O(e.target.value)
|
|
144
169
|
})]
|
|
145
|
-
}), /* @__PURE__ */
|
|
146
|
-
className: "space-y-2",
|
|
147
|
-
children: [/* @__PURE__ */ s("label", {
|
|
148
|
-
className: "text-sm font-medium",
|
|
149
|
-
htmlFor: "job-location",
|
|
150
|
-
children: "Location"
|
|
151
|
-
}), /* @__PURE__ */ s(_, {
|
|
152
|
-
id: "job-location",
|
|
153
|
-
placeholder: "e.g. San Francisco, CA",
|
|
154
|
-
value: j,
|
|
155
|
-
onChange: (e) => M(e.target.value)
|
|
156
|
-
})]
|
|
157
|
-
})]
|
|
158
|
-
}),
|
|
159
|
-
/* @__PURE__ */ c("div", {
|
|
160
|
-
className: "grid grid-cols-1 sm:grid-cols-2 gap-4",
|
|
161
|
-
children: [/* @__PURE__ */ c("div", {
|
|
170
|
+
}), /* @__PURE__ */ d("div", {
|
|
162
171
|
className: "space-y-2",
|
|
163
|
-
children: [/* @__PURE__ */
|
|
164
|
-
className: "text-sm font-medium",
|
|
172
|
+
children: [/* @__PURE__ */ u(S, {
|
|
165
173
|
htmlFor: "job-type",
|
|
166
174
|
children: "Employment Type"
|
|
167
|
-
}), /* @__PURE__ */
|
|
175
|
+
}), /* @__PURE__ */ u("select", {
|
|
168
176
|
id: "job-type",
|
|
169
|
-
className:
|
|
177
|
+
className: v,
|
|
170
178
|
value: P,
|
|
171
179
|
onChange: (e) => F(e.target.value),
|
|
172
|
-
children:
|
|
180
|
+
children: b.map((e) => /* @__PURE__ */ u("option", {
|
|
173
181
|
value: e.value,
|
|
174
182
|
children: e.label
|
|
175
183
|
}, e.value))
|
|
176
184
|
})]
|
|
177
|
-
})
|
|
185
|
+
})]
|
|
186
|
+
}),
|
|
187
|
+
/* @__PURE__ */ d("div", {
|
|
188
|
+
className: "grid grid-cols-1 gap-5 md:grid-cols-2",
|
|
189
|
+
children: [/* @__PURE__ */ d("div", {
|
|
190
|
+
className: "space-y-2",
|
|
191
|
+
children: [
|
|
192
|
+
/* @__PURE__ */ u(S, {
|
|
193
|
+
htmlFor: "job-department",
|
|
194
|
+
children: "Department"
|
|
195
|
+
}),
|
|
196
|
+
/* @__PURE__ */ u(m, {
|
|
197
|
+
id: "job-department",
|
|
198
|
+
list: "crewfoundry-department-options",
|
|
199
|
+
placeholder: "e.g. Engineering",
|
|
200
|
+
value: k,
|
|
201
|
+
onChange: (e) => A(e.target.value)
|
|
202
|
+
}),
|
|
203
|
+
/* @__PURE__ */ u("datalist", {
|
|
204
|
+
id: "crewfoundry-department-options",
|
|
205
|
+
children: X.map((e) => /* @__PURE__ */ u("option", { value: e }, e))
|
|
206
|
+
})
|
|
207
|
+
]
|
|
208
|
+
}), /* @__PURE__ */ d("div", {
|
|
178
209
|
className: "space-y-2",
|
|
179
|
-
children: [/* @__PURE__ */
|
|
180
|
-
className: "text-sm font-medium",
|
|
210
|
+
children: [/* @__PURE__ */ u(S, {
|
|
181
211
|
htmlFor: "job-experience",
|
|
182
212
|
children: "Experience Level"
|
|
183
|
-
}), /* @__PURE__ */
|
|
213
|
+
}), /* @__PURE__ */ u("select", {
|
|
184
214
|
id: "job-experience",
|
|
185
|
-
className:
|
|
215
|
+
className: v,
|
|
186
216
|
value: I,
|
|
187
217
|
onChange: (e) => L(e.target.value),
|
|
188
|
-
children:
|
|
218
|
+
children: x.map((e) => /* @__PURE__ */ u("option", {
|
|
189
219
|
value: e.value,
|
|
190
220
|
children: e.label
|
|
191
221
|
}, e.value))
|
|
192
222
|
})]
|
|
193
223
|
})]
|
|
194
224
|
}),
|
|
195
|
-
/* @__PURE__ */
|
|
196
|
-
className: "grid grid-cols-1
|
|
197
|
-
children: [/* @__PURE__ */
|
|
225
|
+
/* @__PURE__ */ d("div", {
|
|
226
|
+
className: "grid grid-cols-1 gap-5 md:grid-cols-2",
|
|
227
|
+
children: [/* @__PURE__ */ d("div", {
|
|
198
228
|
className: "space-y-2",
|
|
199
|
-
children: [/* @__PURE__ */
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
value: R,
|
|
208
|
-
onChange: (e) => z(e.target.value)
|
|
229
|
+
children: [/* @__PURE__ */ u(S, {
|
|
230
|
+
htmlFor: "job-location",
|
|
231
|
+
children: "Location"
|
|
232
|
+
}), /* @__PURE__ */ u(m, {
|
|
233
|
+
id: "job-location",
|
|
234
|
+
placeholder: "e.g. San Francisco, CA",
|
|
235
|
+
value: j,
|
|
236
|
+
onChange: (e) => te(e.target.value)
|
|
209
237
|
})]
|
|
210
|
-
}), /* @__PURE__ */
|
|
211
|
-
className: "
|
|
212
|
-
children: [/* @__PURE__ */
|
|
213
|
-
className: "
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
238
|
+
}), /* @__PURE__ */ d("div", {
|
|
239
|
+
className: "grid grid-cols-2 gap-4",
|
|
240
|
+
children: [/* @__PURE__ */ d("div", {
|
|
241
|
+
className: "space-y-2",
|
|
242
|
+
children: [/* @__PURE__ */ u(S, {
|
|
243
|
+
htmlFor: "job-salary-min",
|
|
244
|
+
children: "Salary Min"
|
|
245
|
+
}), /* @__PURE__ */ d("div", {
|
|
246
|
+
className: "relative",
|
|
247
|
+
children: [/* @__PURE__ */ u("span", {
|
|
248
|
+
className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-text-secondary",
|
|
249
|
+
children: "$"
|
|
250
|
+
}), /* @__PURE__ */ u(m, {
|
|
251
|
+
id: "job-salary-min",
|
|
252
|
+
type: "number",
|
|
253
|
+
className: "pl-7",
|
|
254
|
+
placeholder: "120,000",
|
|
255
|
+
value: R,
|
|
256
|
+
onChange: (e) => z(e.target.value)
|
|
257
|
+
})]
|
|
258
|
+
})]
|
|
259
|
+
}), /* @__PURE__ */ d("div", {
|
|
260
|
+
className: "space-y-2",
|
|
261
|
+
children: [/* @__PURE__ */ u(S, {
|
|
262
|
+
htmlFor: "job-salary-max",
|
|
263
|
+
children: "Salary Max"
|
|
264
|
+
}), /* @__PURE__ */ d("div", {
|
|
265
|
+
className: "relative",
|
|
266
|
+
children: [/* @__PURE__ */ u("span", {
|
|
267
|
+
className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-text-secondary",
|
|
268
|
+
children: "$"
|
|
269
|
+
}), /* @__PURE__ */ u(m, {
|
|
270
|
+
id: "job-salary-max",
|
|
271
|
+
type: "number",
|
|
272
|
+
className: "pl-7",
|
|
273
|
+
placeholder: "180,000",
|
|
274
|
+
value: B,
|
|
275
|
+
onChange: (e) => V(e.target.value)
|
|
276
|
+
})]
|
|
277
|
+
})]
|
|
222
278
|
})]
|
|
223
279
|
})]
|
|
224
280
|
}),
|
|
225
|
-
/* @__PURE__ */
|
|
226
|
-
className: "
|
|
227
|
-
children:
|
|
228
|
-
className: "
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
281
|
+
/* @__PURE__ */ u("div", {
|
|
282
|
+
className: "grid grid-cols-1 gap-5 md:grid-cols-2",
|
|
283
|
+
children: /* @__PURE__ */ d("div", {
|
|
284
|
+
className: "space-y-2",
|
|
285
|
+
children: [/* @__PURE__ */ u(S, {
|
|
286
|
+
htmlFor: "job-deadline",
|
|
287
|
+
children: "Application Deadline"
|
|
288
|
+
}), /* @__PURE__ */ u(m, {
|
|
289
|
+
id: "job-deadline",
|
|
290
|
+
type: "date",
|
|
291
|
+
value: H,
|
|
292
|
+
onChange: (e) => U(e.target.value)
|
|
293
|
+
})]
|
|
294
|
+
})
|
|
237
295
|
}),
|
|
238
|
-
/* @__PURE__ */
|
|
296
|
+
/* @__PURE__ */ d("div", {
|
|
239
297
|
className: "space-y-2",
|
|
240
|
-
children: [/* @__PURE__ */
|
|
241
|
-
className: "text-sm font-medium",
|
|
298
|
+
children: [/* @__PURE__ */ u(S, {
|
|
242
299
|
htmlFor: "job-description",
|
|
243
300
|
children: "Description"
|
|
244
|
-
}), /* @__PURE__ */
|
|
301
|
+
}), /* @__PURE__ */ u(g, {
|
|
245
302
|
id: "job-description",
|
|
246
303
|
placeholder: "Describe the role, responsibilities, and ideal candidate...",
|
|
247
304
|
rows: 4,
|
|
248
|
-
value:
|
|
249
|
-
onChange: (e) =>
|
|
305
|
+
value: M,
|
|
306
|
+
onChange: (e) => N(e.target.value)
|
|
307
|
+
})]
|
|
308
|
+
}),
|
|
309
|
+
/* @__PURE__ */ d("div", {
|
|
310
|
+
className: "grid grid-cols-1 gap-6 border-t border-border-subtle pt-5 md:grid-cols-2",
|
|
311
|
+
children: [/* @__PURE__ */ d("div", {
|
|
312
|
+
className: "space-y-3",
|
|
313
|
+
children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("div", {
|
|
314
|
+
className: y,
|
|
315
|
+
children: "Requirements"
|
|
316
|
+
}), /* @__PURE__ */ u("p", {
|
|
317
|
+
className: "text-xs text-text-secondary",
|
|
318
|
+
children: "List the key requirements for this role"
|
|
319
|
+
})] }), $(W, re, ae, Z, "Requirement", "e.g. 5+ years with React")]
|
|
320
|
+
}), /* @__PURE__ */ d("div", {
|
|
321
|
+
className: "space-y-3",
|
|
322
|
+
children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("div", {
|
|
323
|
+
className: y,
|
|
324
|
+
children: "Benefits"
|
|
325
|
+
}), /* @__PURE__ */ u("p", {
|
|
326
|
+
className: "text-xs text-text-secondary",
|
|
327
|
+
children: "What does this position offer?"
|
|
328
|
+
})] }), $(K, ie, oe, ne, "Benefit", "e.g. Flexible remote work")]
|
|
329
|
+
})]
|
|
330
|
+
}),
|
|
331
|
+
/* @__PURE__ */ d("div", {
|
|
332
|
+
className: "flex flex-col-reverse justify-end gap-2 border-t border-border-subtle pt-5 sm:flex-row",
|
|
333
|
+
children: [/* @__PURE__ */ u(f, {
|
|
334
|
+
variant: "outline",
|
|
335
|
+
disabled: J,
|
|
336
|
+
onClick: () => Q("draft"),
|
|
337
|
+
children: "Save as Draft"
|
|
338
|
+
}), /* @__PURE__ */ d(f, {
|
|
339
|
+
disabled: J,
|
|
340
|
+
onClick: () => Q("active"),
|
|
341
|
+
children: [/* @__PURE__ */ u(s, { className: "h-4 w-4 mr-1" }), J ? "Saving…" : "Publish Job"]
|
|
250
342
|
})]
|
|
251
343
|
})
|
|
252
344
|
]
|
|
253
|
-
})]
|
|
254
|
-
|
|
255
|
-
className: "space-y-3",
|
|
256
|
-
children: [W.map((e, t) => /* @__PURE__ */ c("div", {
|
|
257
|
-
className: "flex gap-2",
|
|
258
|
-
children: [/* @__PURE__ */ s(_, {
|
|
259
|
-
placeholder: `Requirement ${t + 1}`,
|
|
260
|
-
value: e,
|
|
261
|
-
onChange: (e) => Q(t, e.target.value)
|
|
262
|
-
}), /* @__PURE__ */ s(l, {
|
|
263
|
-
variant: "outline",
|
|
264
|
-
size: "sm",
|
|
265
|
-
"aria-label": `Remove requirement ${t + 1}`,
|
|
266
|
-
onClick: () => re(t),
|
|
267
|
-
children: /* @__PURE__ */ s(o, { className: "h-4 w-4" })
|
|
268
|
-
})]
|
|
269
|
-
}, t)), /* @__PURE__ */ c(l, {
|
|
270
|
-
variant: "outline",
|
|
271
|
-
size: "sm",
|
|
272
|
-
onClick: X,
|
|
273
|
-
children: [/* @__PURE__ */ s(i, { className: "h-4 w-4 mr-1" }), "Add Requirement"]
|
|
274
|
-
})]
|
|
275
|
-
})] }),
|
|
276
|
-
/* @__PURE__ */ c(u, { children: [/* @__PURE__ */ c(p, { children: [/* @__PURE__ */ s(m, { children: "Benefits" }), /* @__PURE__ */ s(f, { children: "What does this position offer?" })] }), /* @__PURE__ */ c(d, {
|
|
277
|
-
className: "space-y-3",
|
|
278
|
-
children: [K.map((e, t) => /* @__PURE__ */ c("div", {
|
|
279
|
-
className: "flex gap-2",
|
|
280
|
-
children: [/* @__PURE__ */ s(_, {
|
|
281
|
-
placeholder: `Benefit ${t + 1}`,
|
|
282
|
-
value: e,
|
|
283
|
-
onChange: (e) => ne(t, e.target.value)
|
|
284
|
-
}), /* @__PURE__ */ s(l, {
|
|
285
|
-
variant: "outline",
|
|
286
|
-
size: "sm",
|
|
287
|
-
"aria-label": `Remove benefit ${t + 1}`,
|
|
288
|
-
onClick: () => ie(t),
|
|
289
|
-
children: /* @__PURE__ */ s(o, { className: "h-4 w-4" })
|
|
290
|
-
})]
|
|
291
|
-
}, t)), /* @__PURE__ */ c(l, {
|
|
292
|
-
variant: "outline",
|
|
293
|
-
size: "sm",
|
|
294
|
-
onClick: Z,
|
|
295
|
-
children: [/* @__PURE__ */ s(i, { className: "h-4 w-4 mr-1" }), "Add Benefit"]
|
|
296
|
-
})]
|
|
297
|
-
})] }),
|
|
298
|
-
/* @__PURE__ */ c("div", {
|
|
299
|
-
className: "flex justify-end gap-2",
|
|
300
|
-
children: [/* @__PURE__ */ s(l, {
|
|
301
|
-
variant: "outline",
|
|
302
|
-
disabled: J,
|
|
303
|
-
onClick: () => $("draft"),
|
|
304
|
-
children: "Save as Draft"
|
|
305
|
-
}), /* @__PURE__ */ c(l, {
|
|
306
|
-
disabled: J,
|
|
307
|
-
onClick: () => $("active"),
|
|
308
|
-
children: [/* @__PURE__ */ s(a, { className: "h-4 w-4 mr-1" }), J ? "Saving…" : "Publish Job"]
|
|
309
|
-
})]
|
|
310
|
-
})
|
|
311
|
-
]
|
|
345
|
+
})]
|
|
346
|
+
})]
|
|
312
347
|
});
|
|
313
348
|
}
|
|
314
349
|
//#endregion
|
|
315
|
-
export {
|
|
350
|
+
export { C as HiringCreateJobPagePage };
|
|
316
351
|
|
|
317
352
|
//# sourceMappingURL=HiringCreateJobPagePage.js.map
|
|
@@ -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('../hiring/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\">\n Create a new job posting — define the role, requirements, and compensation here to start\n attracting and collecting applicants.\n </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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"}
|
|
1
|
+
{"version":3,"file":"HiringCreateJobPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/HiringCreateJobPagePage.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from 'react';\nimport {\n Button,\n GlassCard,\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, ChevronRight, 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 FIELD_LABEL_CLASS = 'text-sm font-medium text-text-primary';\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\nfunction FieldLabel({ htmlFor, children }: { htmlFor: string; children: ReactNode }) {\n return (\n <label className={FIELD_LABEL_CLASS} htmlFor={htmlFor}>\n {children}\n </label>\n );\n}\n\nexport function HiringCreateJobPagePage() {\n const navigate = useNavigate();\n const { showToast } = useGlobalUi();\n const addJobPosting = useCrewFoundryStore((state) => state.addJobPosting);\n const departments = useCrewFoundryStore((state) => state.departments);\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 departmentNames = useMemo(\n () => Array.from(new Set(departments.map((d) => d.name).filter(Boolean))).sort(),\n [departments]\n );\n\n const addRequirement = () => setRequirements((prev) => [...prev, '']);\n const addBenefit = () => setBenefits((prev) => [...prev, '']);\n const updateRequirement = (idx: number, value: string) =>\n setRequirements((prev) => prev.map((item, i) => (i === idx ? value : item)));\n const updateBenefit = (idx: number, value: string) =>\n setBenefits((prev) => prev.map((item, i) => (i === idx ? value : item)));\n const removeRequirement = (idx: number) =>\n setRequirements((prev) => prev.filter((_, i) => i !== idx));\n const removeBenefit = (idx: number) => setBenefits((prev) => prev.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('../hiring/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 const renderChipRows = (\n items: string[],\n update: (idx: number, value: string) => void,\n remove: (idx: number) => void,\n add: () => void,\n kind: 'Requirement' | 'Benefit',\n placeholder: string\n ) => (\n <div className=\"space-y-2\">\n {items.map((value, idx) => (\n <div key={idx} className=\"relative\">\n <Input\n className=\"pr-9\"\n placeholder={placeholder}\n value={value}\n onChange={(e) => update(idx, e.target.value)}\n />\n <button\n type=\"button\"\n aria-label={`Remove ${kind.toLowerCase()} ${idx + 1}`}\n onClick={() => remove(idx)}\n className=\"absolute right-2.5 top-1/2 -translate-y-1/2 rounded-sm p-0.5 text-text-secondary transition-colors hover:text-text-primary focus-visible:outline-none focus-visible:text-text-primary\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n ))}\n <Button\n variant=\"link\"\n size=\"sm\"\n className=\"h-auto p-0\"\n onClick={add}\n type=\"button\"\n >\n <Plus className=\"h-4 w-4 mr-1\" />\n Add {kind}\n </Button>\n </div>\n );\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"space-y-2\">\n <nav\n aria-label=\"Breadcrumb\"\n className=\"flex items-center gap-1 text-sm text-text-secondary\"\n >\n <button\n type=\"button\"\n onClick={() => navigate('../hiring/jobs-page')}\n className=\"rounded-sm transition-colors hover:text-text-primary focus-visible:outline-none focus-visible:text-text-primary\"\n >\n Hiring\n </button>\n <ChevronRight className=\"h-3.5 w-3.5\" />\n <span className=\"text-text-primary\">Post New Job</span>\n </nav>\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Create Job Posting</GradientText>\n </h1>\n <PagePurpose className=\"mt-1\">\n Create a new job posting — define the role, requirements, and compensation here to start\n attracting and collecting applicants.\n </PagePurpose>\n </div>\n </div>\n\n <GlassCard treatment=\"glass\" className=\"max-w-5xl p-6\">\n <div className=\"mb-6 flex items-center gap-2 text-lg font-semibold text-text-primary\">\n <Briefcase className=\"h-5 w-5\" />\n Job details\n </div>\n\n <div className=\"space-y-5\">\n <div className=\"grid grid-cols-1 gap-5 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <FieldLabel htmlFor=\"job-title\">Job Title</FieldLabel>\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 <div className=\"space-y-2\">\n <FieldLabel htmlFor=\"job-type\">Employment Type</FieldLabel>\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>\n\n <div className=\"grid grid-cols-1 gap-5 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <FieldLabel htmlFor=\"job-department\">Department</FieldLabel>\n <Input\n id=\"job-department\"\n list=\"crewfoundry-department-options\"\n placeholder=\"e.g. Engineering\"\n value={department}\n onChange={(e) => setDepartment(e.target.value)}\n />\n <datalist id=\"crewfoundry-department-options\">\n {departmentNames.map((name) => (\n <option key={name} value={name} />\n ))}\n </datalist>\n </div>\n <div className=\"space-y-2\">\n <FieldLabel htmlFor=\"job-experience\">Experience Level</FieldLabel>\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 gap-5 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <FieldLabel htmlFor=\"job-location\">Location</FieldLabel>\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 className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <FieldLabel htmlFor=\"job-salary-min\">Salary Min</FieldLabel>\n <div className=\"relative\">\n <span className=\"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-text-secondary\">\n $\n </span>\n <Input\n id=\"job-salary-min\"\n type=\"number\"\n className=\"pl-7\"\n placeholder=\"120,000\"\n value={salaryMin}\n onChange={(e) => setSalaryMin(e.target.value)}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <FieldLabel htmlFor=\"job-salary-max\">Salary Max</FieldLabel>\n <div className=\"relative\">\n <span className=\"pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-sm text-text-secondary\">\n $\n </span>\n <Input\n id=\"job-salary-max\"\n type=\"number\"\n className=\"pl-7\"\n placeholder=\"180,000\"\n value={salaryMax}\n onChange={(e) => setSalaryMax(e.target.value)}\n />\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 gap-5 md:grid-cols-2\">\n <div className=\"space-y-2\">\n <FieldLabel htmlFor=\"job-deadline\">Application Deadline</FieldLabel>\n <Input\n id=\"job-deadline\"\n type=\"date\"\n value={deadline}\n onChange={(e) => setDeadline(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <FieldLabel htmlFor=\"job-description\">Description</FieldLabel>\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\n <div className=\"grid grid-cols-1 gap-6 border-t border-border-subtle pt-5 md:grid-cols-2\">\n <div className=\"space-y-3\">\n <div>\n <div className={FIELD_LABEL_CLASS}>Requirements</div>\n <p className=\"text-xs text-text-secondary\">List the key requirements for this role</p>\n </div>\n {renderChipRows(\n requirements,\n updateRequirement,\n removeRequirement,\n addRequirement,\n 'Requirement',\n 'e.g. 5+ years with React'\n )}\n </div>\n <div className=\"space-y-3\">\n <div>\n <div className={FIELD_LABEL_CLASS}>Benefits</div>\n <p className=\"text-xs text-text-secondary\">What does this position offer?</p>\n </div>\n {renderChipRows(\n benefits,\n updateBenefit,\n removeBenefit,\n addBenefit,\n 'Benefit',\n 'e.g. Flexible remote work'\n )}\n </div>\n </div>\n\n <div className=\"flex flex-col-reverse justify-end gap-2 border-t border-border-subtle pt-5 sm:flex-row\">\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 </GlassCard>\n </div>\n );\n}\n"],"mappings":"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"}
|