@burdenoff/microfe-crewfoundry 2026.704.6 → 2026.707.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crewfoundry/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/HelpApiDocumentationPagePage.js +0 -41
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.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 +269 -270
- 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 +1 -1
- 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 +134 -135
- 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/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/MarketplaceServiceDetailsPagePage.js +289 -140
- 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/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 +140 -78
- 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/TeamsTeamsPagePage.js +250 -98
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js +142 -184
- 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,14 +1,18 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
2
|
import { formatEnumLabel as t } from "../utils/formatEnumLabel.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
3
|
+
import { StatCard as n } from "../components/viz/StatCard.js";
|
|
4
|
+
import { OrgTree as r } from "../components/viz/OrgTree.js";
|
|
5
|
+
import { AvatarStack as i } from "../components/viz/AvatarStack.js";
|
|
6
|
+
import "../components/viz/index.js";
|
|
7
|
+
import { FormModal as a, useFormModal as o } from "../components/forms/FormModal.js";
|
|
8
|
+
import { ConfirmDialog as s } from "../components/forms/ConfirmDialog.js";
|
|
9
|
+
import { getNumber as c, getText as l, newClientId as u } from "../components/forms/formValues.js";
|
|
10
|
+
import { useCallback as d, useMemo as f, useState as p } from "react";
|
|
11
|
+
import { Building2 as m, DollarSign as h, MapPin as g, Network as _, Pencil as v, Plus as y, Trash2 as b, Users as x } from "lucide-react";
|
|
12
|
+
import { jsx as S, jsxs as C } from "react/jsx-runtime";
|
|
13
|
+
import { Badge as w, Button as T, Card as E, CardContent as D, CardHeader as O, CardTitle as k, GlassCard as A, GradientText as j, PagePurpose as M } from "@burdenoff/fe-libs/ui";
|
|
10
14
|
//#region src/crewfoundry/pages/HrDepartmentsPagePage.tsx
|
|
11
|
-
var
|
|
15
|
+
var N = (e) => `${e.firstName} ${e.lastName}`.trim(), P = [
|
|
12
16
|
{
|
|
13
17
|
name: "name",
|
|
14
18
|
label: "Department name",
|
|
@@ -47,227 +51,261 @@ var k = [
|
|
|
47
51
|
value: "restructuring"
|
|
48
52
|
}]
|
|
49
53
|
}
|
|
50
|
-
],
|
|
54
|
+
], F = (e) => ({
|
|
51
55
|
name: e.name,
|
|
52
56
|
headName: e.headName,
|
|
53
57
|
location: e.location,
|
|
54
58
|
budget: e.budget,
|
|
55
59
|
status: e.status
|
|
56
60
|
});
|
|
57
|
-
function
|
|
58
|
-
let { departments:
|
|
59
|
-
|
|
61
|
+
function I() {
|
|
62
|
+
let { departments: I, employees: L, teams: R, addDepartment: z, updateDepartment: B, removeDepartment: V } = e(), H = o(), [U, W] = p(null), G = I.reduce((e, t) => e + t.budget, 0), K = I.reduce((e, t) => e + t.employeeCount, 0), q = H.context, J = d((e) => L.find((t) => t.id === e.headId) || L.find((t) => N(t) === e.headName), [L]), Y = f(() => {
|
|
63
|
+
if (I.length === 0) return null;
|
|
64
|
+
let e = L.find((e) => !e.managerId && /chief|ceo|founder|president|head of company/i.test(e.position)), t = I.map((e) => {
|
|
65
|
+
let t = J(e), n = R.filter((t) => t.department === e.name), r;
|
|
66
|
+
return r = n.length > 0 ? n.slice(0, 4).map((e) => ({
|
|
67
|
+
id: e.id,
|
|
68
|
+
name: e.name,
|
|
69
|
+
role: `${e.memberCount} member${e.memberCount === 1 ? "" : "s"}`
|
|
70
|
+
})) : L.filter((n) => n.department === e.name && n.id !== t?.id).slice(0, 3).map((e) => ({
|
|
71
|
+
id: e.id,
|
|
72
|
+
name: N(e),
|
|
73
|
+
role: e.position,
|
|
74
|
+
avatarUrl: e.avatar
|
|
75
|
+
})), {
|
|
76
|
+
id: e.id,
|
|
77
|
+
name: e.name,
|
|
78
|
+
role: e.headName ? `${e.headName}, Head` : "Department",
|
|
79
|
+
avatarUrl: t?.avatar,
|
|
80
|
+
children: r
|
|
81
|
+
};
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
id: e?.id ?? "org-root",
|
|
85
|
+
name: e ? N(e) : "Organization",
|
|
86
|
+
role: e?.position ?? "Company",
|
|
87
|
+
avatarUrl: e?.avatar,
|
|
88
|
+
children: t
|
|
89
|
+
};
|
|
90
|
+
}, [
|
|
91
|
+
I,
|
|
92
|
+
L,
|
|
93
|
+
R,
|
|
94
|
+
J
|
|
95
|
+
]);
|
|
96
|
+
return /* @__PURE__ */ C("div", {
|
|
60
97
|
className: "space-y-6 p-6",
|
|
61
98
|
children: [
|
|
62
|
-
/* @__PURE__ */
|
|
99
|
+
/* @__PURE__ */ C("div", {
|
|
63
100
|
className: "flex items-center justify-between",
|
|
64
|
-
children: [/* @__PURE__ */
|
|
65
|
-
/* @__PURE__ */
|
|
101
|
+
children: [/* @__PURE__ */ C("div", { children: [
|
|
102
|
+
/* @__PURE__ */ S("h1", {
|
|
66
103
|
className: "text-2xl font-semibold",
|
|
67
|
-
children: /* @__PURE__ */
|
|
104
|
+
children: /* @__PURE__ */ S(j, { children: "Departments" })
|
|
68
105
|
}),
|
|
69
|
-
/* @__PURE__ */
|
|
106
|
+
/* @__PURE__ */ S("p", {
|
|
70
107
|
className: "text-sm text-text-secondary",
|
|
71
108
|
children: "Organizational structure and department management"
|
|
72
109
|
}),
|
|
73
|
-
/* @__PURE__ */
|
|
110
|
+
/* @__PURE__ */ S(M, {
|
|
74
111
|
className: "mt-1",
|
|
75
112
|
children: "Organize your company into departments — set up structure, assign heads, and see how headcount is distributed across the org."
|
|
76
113
|
})
|
|
77
|
-
] }), /* @__PURE__ */
|
|
114
|
+
] }), /* @__PURE__ */ C(T, {
|
|
78
115
|
size: "sm",
|
|
79
|
-
onClick: () =>
|
|
80
|
-
children: [/* @__PURE__ */
|
|
116
|
+
onClick: () => H.openModal(),
|
|
117
|
+
children: [/* @__PURE__ */ S(y, { className: "h-4 w-4 mr-1" }), "Add Department"]
|
|
81
118
|
})]
|
|
82
119
|
}),
|
|
83
|
-
/* @__PURE__ */
|
|
120
|
+
/* @__PURE__ */ C("div", {
|
|
84
121
|
className: "grid gap-4 md:grid-cols-3",
|
|
85
122
|
children: [
|
|
86
|
-
/* @__PURE__ */
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
className: "
|
|
90
|
-
children: [/* @__PURE__ */ _(C, {
|
|
91
|
-
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
92
|
-
children: [/* @__PURE__ */ g(w, {
|
|
93
|
-
className: "text-sm font-medium",
|
|
94
|
-
children: "Total Departments"
|
|
95
|
-
}), /* @__PURE__ */ g(l, { className: "h-4 w-4 text-text-secondary" })]
|
|
96
|
-
}), /* @__PURE__ */ g(x, { children: /* @__PURE__ */ g("div", {
|
|
97
|
-
className: "text-2xl font-bold tabular-nums",
|
|
98
|
-
children: j.length
|
|
99
|
-
}) })]
|
|
123
|
+
/* @__PURE__ */ S(n, {
|
|
124
|
+
label: "Total Departments",
|
|
125
|
+
value: I.length,
|
|
126
|
+
icon: /* @__PURE__ */ S(m, { className: "h-4 w-4" })
|
|
100
127
|
}),
|
|
101
|
-
/* @__PURE__ */
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
106
|
-
children: [/* @__PURE__ */ g(w, {
|
|
107
|
-
className: "text-sm font-medium",
|
|
108
|
-
children: "Total Headcount"
|
|
109
|
-
}), /* @__PURE__ */ g(h, { className: "h-4 w-4 text-text-secondary" })]
|
|
110
|
-
}), /* @__PURE__ */ g(x, { children: /* @__PURE__ */ g("div", {
|
|
111
|
-
className: "text-2xl font-bold tabular-nums",
|
|
112
|
-
children: B
|
|
113
|
-
}) })]
|
|
128
|
+
/* @__PURE__ */ S(n, {
|
|
129
|
+
label: "Total Headcount",
|
|
130
|
+
value: K,
|
|
131
|
+
icon: /* @__PURE__ */ S(x, { className: "h-4 w-4" })
|
|
114
132
|
}),
|
|
115
|
-
/* @__PURE__ */
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
120
|
-
children: [/* @__PURE__ */ g(w, {
|
|
121
|
-
className: "text-sm font-medium",
|
|
122
|
-
children: "Total Budget"
|
|
123
|
-
}), /* @__PURE__ */ g(u, { className: "h-4 w-4 text-text-secondary" })]
|
|
124
|
-
}), /* @__PURE__ */ g(x, { children: /* @__PURE__ */ _("div", {
|
|
125
|
-
className: "text-2xl font-bold tabular-nums",
|
|
126
|
-
children: [
|
|
127
|
-
"$",
|
|
128
|
-
(z / 1e6).toFixed(1),
|
|
129
|
-
"M"
|
|
130
|
-
]
|
|
131
|
-
}) })]
|
|
133
|
+
/* @__PURE__ */ S(n, {
|
|
134
|
+
label: "Total Budget",
|
|
135
|
+
value: `$${(G / 1e6).toFixed(1)}M`,
|
|
136
|
+
icon: /* @__PURE__ */ S(h, { className: "h-4 w-4" })
|
|
132
137
|
})
|
|
133
138
|
]
|
|
134
139
|
}),
|
|
135
|
-
/* @__PURE__ */
|
|
136
|
-
className: "grid gap-4 md:grid-cols-2",
|
|
137
|
-
children:
|
|
138
|
-
let n =
|
|
139
|
-
return /* @__PURE__ */
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
140
|
+
/* @__PURE__ */ S("div", {
|
|
141
|
+
className: "grid gap-4 md:grid-cols-2 xl:grid-cols-3",
|
|
142
|
+
children: I.map((e) => {
|
|
143
|
+
let n = L.filter((t) => t.department === e.name), r = e.employeeCount || n.length, a = n.length > 0 ? Math.round(n.reduce((e, t) => e + t.salary, 0) / n.length) : 0, o = n.length > 0 ? n.reduce((e, t) => e + t.performanceScore, 0) / n.length : 0, s = Math.round(o / 5 * 100), c = J(e), l = s >= 80 ? "bg-status-success-text" : s >= 60 ? "bg-status-warning-text" : "bg-status-error-text";
|
|
144
|
+
return /* @__PURE__ */ C(A, {
|
|
145
|
+
treatment: "glass",
|
|
146
|
+
className: "border-border-seam",
|
|
147
|
+
children: [/* @__PURE__ */ S(O, { children: /* @__PURE__ */ C("div", {
|
|
148
|
+
className: "flex items-start justify-between gap-2",
|
|
149
|
+
children: [/* @__PURE__ */ C("div", {
|
|
150
|
+
className: "min-w-0",
|
|
151
|
+
children: [/* @__PURE__ */ S(k, {
|
|
152
|
+
className: "truncate text-lg",
|
|
153
|
+
children: e.name
|
|
154
|
+
}), /* @__PURE__ */ C("div", {
|
|
155
|
+
className: "mt-2 flex items-center gap-2",
|
|
156
|
+
children: [/* @__PURE__ */ S(i, {
|
|
157
|
+
people: [{
|
|
158
|
+
name: e.headName || "Unassigned",
|
|
159
|
+
avatarUrl: c?.avatar
|
|
160
|
+
}],
|
|
161
|
+
size: 28
|
|
162
|
+
}), /* @__PURE__ */ C("span", {
|
|
163
|
+
className: "truncate text-sm text-text-secondary",
|
|
164
|
+
children: [/* @__PURE__ */ S("span", {
|
|
165
|
+
className: "font-medium text-text-primary",
|
|
166
|
+
children: e.headName
|
|
167
|
+
}), e.headName ? ", Head" : "No head assigned"]
|
|
168
|
+
})]
|
|
169
|
+
})]
|
|
170
|
+
}), /* @__PURE__ */ C("div", {
|
|
171
|
+
className: "flex items-center gap-1",
|
|
172
|
+
children: [
|
|
173
|
+
/* @__PURE__ */ S(w, {
|
|
174
|
+
variant: e.status === "active" ? "default" : "secondary",
|
|
175
|
+
children: t(e.status)
|
|
176
|
+
}),
|
|
177
|
+
/* @__PURE__ */ S(T, {
|
|
178
|
+
variant: "ghost",
|
|
179
|
+
size: "sm",
|
|
180
|
+
className: "h-8 w-8 p-0",
|
|
181
|
+
"aria-label": `Edit ${e.name}`,
|
|
182
|
+
onClick: () => H.openModal(e),
|
|
183
|
+
children: /* @__PURE__ */ S(v, { className: "h-4 w-4" })
|
|
184
|
+
}),
|
|
185
|
+
/* @__PURE__ */ S(T, {
|
|
186
|
+
variant: "ghost",
|
|
187
|
+
size: "sm",
|
|
188
|
+
className: "h-8 w-8 p-0",
|
|
189
|
+
"aria-label": `Delete ${e.name}`,
|
|
190
|
+
onClick: () => W(e),
|
|
191
|
+
children: /* @__PURE__ */ S(b, { className: "h-4 w-4 text-status-error-text" })
|
|
192
|
+
})
|
|
193
|
+
]
|
|
194
|
+
})]
|
|
195
|
+
}) }), /* @__PURE__ */ C(D, {
|
|
196
|
+
className: "space-y-4",
|
|
146
197
|
children: [
|
|
147
|
-
/* @__PURE__ */
|
|
148
|
-
|
|
149
|
-
children:
|
|
198
|
+
/* @__PURE__ */ C("div", {
|
|
199
|
+
className: "flex items-end justify-between gap-3",
|
|
200
|
+
children: [/* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("p", {
|
|
201
|
+
className: "text-3xl font-bold leading-none tabular-nums",
|
|
202
|
+
children: r
|
|
203
|
+
}), /* @__PURE__ */ S("p", {
|
|
204
|
+
className: "mt-1 text-xs text-text-secondary",
|
|
205
|
+
children: "Employees"
|
|
206
|
+
})] }), /* @__PURE__ */ C("div", {
|
|
207
|
+
className: "text-right",
|
|
208
|
+
children: [/* @__PURE__ */ C("p", {
|
|
209
|
+
className: "text-lg font-semibold tabular-nums",
|
|
210
|
+
children: [
|
|
211
|
+
"$",
|
|
212
|
+
(e.budget / 1e6).toFixed(1),
|
|
213
|
+
"M"
|
|
214
|
+
]
|
|
215
|
+
}), /* @__PURE__ */ S("p", {
|
|
216
|
+
className: "text-xs text-text-secondary",
|
|
217
|
+
children: "Annual budget"
|
|
218
|
+
})]
|
|
219
|
+
})]
|
|
220
|
+
}),
|
|
221
|
+
/* @__PURE__ */ C("div", {
|
|
222
|
+
className: "space-y-1",
|
|
223
|
+
children: [/* @__PURE__ */ C("div", {
|
|
224
|
+
className: "flex items-center justify-between text-xs text-text-secondary",
|
|
225
|
+
children: [/* @__PURE__ */ S("span", { children: "Avg performance" }), /* @__PURE__ */ C("span", {
|
|
226
|
+
className: "font-medium text-text-primary tabular-nums",
|
|
227
|
+
children: [s, "%"]
|
|
228
|
+
})]
|
|
229
|
+
}), /* @__PURE__ */ S("div", {
|
|
230
|
+
className: "h-2 overflow-hidden rounded-full bg-bg-sunken",
|
|
231
|
+
children: /* @__PURE__ */ S("div", {
|
|
232
|
+
className: `h-2 rounded-full ${l}`,
|
|
233
|
+
style: { width: `${s}%` }
|
|
234
|
+
})
|
|
235
|
+
})]
|
|
150
236
|
}),
|
|
151
|
-
/* @__PURE__ */
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
237
|
+
/* @__PURE__ */ C("div", {
|
|
238
|
+
className: "flex items-center justify-between text-xs text-text-secondary",
|
|
239
|
+
children: [/* @__PURE__ */ C("span", {
|
|
240
|
+
className: "flex items-center gap-1",
|
|
241
|
+
children: [/* @__PURE__ */ S(g, { className: "h-3 w-3" }), e.location]
|
|
242
|
+
}), /* @__PURE__ */ C("span", { children: [
|
|
243
|
+
"Cost/Head:",
|
|
244
|
+
" ",
|
|
245
|
+
r > 0 ? `$${Math.round(e.budget / r / 1e3)}K` : "—"
|
|
246
|
+
] })]
|
|
158
247
|
}),
|
|
159
|
-
/* @__PURE__ */
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
children: /* @__PURE__ */ g(m, { className: "h-4 w-4 text-status-error-text" })
|
|
248
|
+
a > 0 && /* @__PURE__ */ C("p", {
|
|
249
|
+
className: "text-xs text-text-secondary",
|
|
250
|
+
children: ["Avg salary ", /* @__PURE__ */ C("span", {
|
|
251
|
+
className: "font-medium text-text-primary",
|
|
252
|
+
children: ["$", a.toLocaleString()]
|
|
253
|
+
})]
|
|
166
254
|
})
|
|
167
255
|
]
|
|
168
256
|
})]
|
|
169
|
-
}
|
|
170
|
-
className: "flex items-center gap-1",
|
|
171
|
-
children: [/* @__PURE__ */ g(d, { className: "h-3 w-3" }), e.location]
|
|
172
|
-
})] }), /* @__PURE__ */ _(x, { children: [
|
|
173
|
-
/* @__PURE__ */ _("div", {
|
|
174
|
-
className: "grid grid-cols-2 gap-4 mb-4",
|
|
175
|
-
children: [
|
|
176
|
-
/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("p", {
|
|
177
|
-
className: "text-xs text-text-secondary",
|
|
178
|
-
children: "Department Head"
|
|
179
|
-
}), /* @__PURE__ */ g("p", {
|
|
180
|
-
className: "text-sm font-medium",
|
|
181
|
-
children: e.headName
|
|
182
|
-
})] }),
|
|
183
|
-
/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("p", {
|
|
184
|
-
className: "text-xs text-text-secondary",
|
|
185
|
-
children: "Headcount"
|
|
186
|
-
}), /* @__PURE__ */ _("p", {
|
|
187
|
-
className: "text-sm font-medium",
|
|
188
|
-
children: [e.employeeCount, " employees"]
|
|
189
|
-
})] }),
|
|
190
|
-
/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("p", {
|
|
191
|
-
className: "text-xs text-text-secondary",
|
|
192
|
-
children: "Annual Budget"
|
|
193
|
-
}), /* @__PURE__ */ _("p", {
|
|
194
|
-
className: "text-sm font-medium",
|
|
195
|
-
children: [
|
|
196
|
-
"$",
|
|
197
|
-
(e.budget / 1e6).toFixed(1),
|
|
198
|
-
"M"
|
|
199
|
-
]
|
|
200
|
-
})] }),
|
|
201
|
-
/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("p", {
|
|
202
|
-
className: "text-xs text-text-secondary",
|
|
203
|
-
children: "Avg Salary"
|
|
204
|
-
}), /* @__PURE__ */ _("p", {
|
|
205
|
-
className: "text-sm font-medium",
|
|
206
|
-
children: ["$", r.toLocaleString()]
|
|
207
|
-
})] })
|
|
208
|
-
]
|
|
209
|
-
}),
|
|
210
|
-
/* @__PURE__ */ g(O, { className: "mb-3" }),
|
|
211
|
-
/* @__PURE__ */ _("div", {
|
|
212
|
-
className: "flex items-center justify-between text-xs",
|
|
213
|
-
children: [/* @__PURE__ */ _("span", {
|
|
214
|
-
className: "text-text-secondary",
|
|
215
|
-
children: [
|
|
216
|
-
"Avg Performance: ",
|
|
217
|
-
i,
|
|
218
|
-
"/5"
|
|
219
|
-
]
|
|
220
|
-
}), /* @__PURE__ */ _("span", {
|
|
221
|
-
className: "text-text-secondary",
|
|
222
|
-
children: [
|
|
223
|
-
"Cost/Head:",
|
|
224
|
-
" ",
|
|
225
|
-
e.employeeCount > 0 ? `$${Math.round(e.budget / e.employeeCount / 1e3)}K` : "—"
|
|
226
|
-
]
|
|
227
|
-
})]
|
|
228
|
-
})
|
|
229
|
-
] })] }, e.id);
|
|
257
|
+
}, e.id);
|
|
230
258
|
})
|
|
231
259
|
}),
|
|
232
|
-
/* @__PURE__ */
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
260
|
+
Y && /* @__PURE__ */ C(E, { children: [/* @__PURE__ */ S(O, { children: /* @__PURE__ */ C(k, {
|
|
261
|
+
className: "flex items-center gap-2 text-lg",
|
|
262
|
+
children: [/* @__PURE__ */ S(_, { className: "h-4 w-4 text-text-secondary" }), "Org structure"]
|
|
263
|
+
}) }), /* @__PURE__ */ S(D, { children: /* @__PURE__ */ S("div", {
|
|
264
|
+
className: "overflow-x-auto pb-2",
|
|
265
|
+
children: /* @__PURE__ */ S("div", {
|
|
266
|
+
className: "min-w-fit",
|
|
267
|
+
children: /* @__PURE__ */ S(r, { root: Y })
|
|
268
|
+
})
|
|
269
|
+
}) })] }),
|
|
270
|
+
/* @__PURE__ */ S(a, {
|
|
271
|
+
open: H.open,
|
|
272
|
+
onOpenChange: H.onOpenChange,
|
|
273
|
+
title: q ? "Edit department" : "Add department",
|
|
274
|
+
description: q ? "Update this department’s details." : "Create a new department in your organization.",
|
|
275
|
+
fields: P,
|
|
276
|
+
initialValues: q ? F(q) : void 0,
|
|
277
|
+
submitLabel: q ? "Save changes" : "Add department",
|
|
240
278
|
onSubmit: async (e) => {
|
|
241
279
|
let t = {
|
|
242
|
-
id:
|
|
243
|
-
name:
|
|
244
|
-
headId:
|
|
245
|
-
headName:
|
|
246
|
-
employeeCount:
|
|
247
|
-
budget:
|
|
248
|
-
location:
|
|
249
|
-
status:
|
|
280
|
+
id: q?.id ?? u(),
|
|
281
|
+
name: l(e, "name"),
|
|
282
|
+
headId: q?.headId ?? "",
|
|
283
|
+
headName: l(e, "headName"),
|
|
284
|
+
employeeCount: q?.employeeCount ?? 0,
|
|
285
|
+
budget: c(e, "budget"),
|
|
286
|
+
location: l(e, "location"),
|
|
287
|
+
status: l(e, "status")
|
|
250
288
|
};
|
|
251
|
-
|
|
289
|
+
q ? await B(q.id, t) : await z(t);
|
|
252
290
|
}
|
|
253
291
|
}),
|
|
254
|
-
/* @__PURE__ */
|
|
255
|
-
open:
|
|
292
|
+
/* @__PURE__ */ S(s, {
|
|
293
|
+
open: U !== null,
|
|
256
294
|
onOpenChange: (e) => {
|
|
257
|
-
e ||
|
|
295
|
+
e || W(null);
|
|
258
296
|
},
|
|
259
297
|
title: "Delete department?",
|
|
260
|
-
description:
|
|
298
|
+
description: U ? `${U.name} will be removed. This cannot be undone.` : void 0,
|
|
261
299
|
confirmLabel: "Delete",
|
|
262
300
|
destructive: !0,
|
|
263
301
|
onConfirm: async () => {
|
|
264
|
-
|
|
302
|
+
U && (await V(U.id), W(null));
|
|
265
303
|
}
|
|
266
304
|
})
|
|
267
305
|
]
|
|
268
306
|
});
|
|
269
307
|
}
|
|
270
308
|
//#endregion
|
|
271
|
-
export {
|
|
309
|
+
export { I as HrDepartmentsPagePage };
|
|
272
310
|
|
|
273
311
|
//# sourceMappingURL=HrDepartmentsPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HrDepartmentsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/HrDepartmentsPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n Separator,\n} from '@burdenoff/fe-libs/ui';\nimport { Building2, DollarSign, MapPin, Pencil, Plus, Trash2, Users } from 'lucide-react';\nimport { useCrewFoundryStore, type Department } from '../store/crewfoundryStore';\nimport {\n FormModal,\n useFormModal,\n type FieldConfig,\n type FormValues,\n} from '../components/forms/FormModal';\nimport { ConfirmDialog } from '../components/forms/ConfirmDialog';\nimport { getNumber, getText, newClientId } from '../components/forms/formValues';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\n\nconst DEPARTMENT_FIELDS: FieldConfig[] = [\n { name: 'name', label: 'Department name', type: 'text', required: true, colSpan: 2 },\n { name: 'headName', label: 'Department head', type: 'text', required: true },\n { name: 'location', label: 'Location', type: 'text', required: true },\n { name: 'budget', label: 'Annual budget', type: 'number', required: true },\n {\n name: 'status',\n label: 'Status',\n type: 'select',\n required: true,\n options: [\n { label: 'Active', value: 'active' },\n { label: 'Restructuring', value: 'restructuring' },\n ],\n },\n];\n\nconst toFormValues = (department: Department): FormValues => ({\n name: department.name,\n headName: department.headName,\n location: department.location,\n budget: department.budget,\n status: department.status,\n});\n\nexport function HrDepartmentsPagePage() {\n const { departments, employees, addDepartment, updateDepartment, removeDepartment } =\n useCrewFoundryStore();\n const form = useFormModal<Department>();\n const [deleting, setDeleting] = useState<Department | null>(null);\n\n const totalBudget = departments.reduce((s, d) => s + d.budget, 0);\n const totalHeadcount = departments.reduce((s, d) => s + d.employeeCount, 0);\n\n const editing = form.context;\n\n const handleSubmit = async (values: FormValues) => {\n const payload: Department = {\n id: editing?.id ?? newClientId(),\n name: getText(values, 'name'),\n headId: editing?.headId ?? '',\n headName: getText(values, 'headName'),\n employeeCount: editing?.employeeCount ?? 0,\n budget: getNumber(values, 'budget'),\n location: getText(values, 'location'),\n status: getText(values, 'status') as Department['status'],\n };\n if (editing) {\n await updateDepartment(editing.id, payload);\n } else {\n await addDepartment(payload);\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Departments</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Organizational structure and department management\n </p>\n <PagePurpose className=\"mt-1\">\n Organize your company into departments — set up structure, assign heads, and see how\n headcount is distributed across the org.\n </PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => form.openModal()}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Department\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Departments</CardTitle>\n <Building2 className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{departments.length}</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Headcount</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{totalHeadcount}</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Budget</CardTitle>\n <DollarSign className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(totalBudget / 1000000).toFixed(1)}M\n </div>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n {departments.map((dept) => {\n const deptEmps = employees.filter((e) => e.department === dept.name);\n const avgSalary =\n deptEmps.length > 0\n ? Math.round(deptEmps.reduce((s, e) => s + e.salary, 0) / deptEmps.length)\n : 0;\n const avgPerf =\n deptEmps.length > 0\n ? (deptEmps.reduce((s, e) => s + e.performanceScore, 0) / deptEmps.length).toFixed(1)\n : '0';\n\n return (\n <Card key={dept.id}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-lg\">{dept.name}</CardTitle>\n <div className=\"flex items-center gap-1\">\n <Badge variant={dept.status === 'active' ? 'default' : 'secondary'}>\n {formatEnumLabel(dept.status)}\n </Badge>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n aria-label={`Edit ${dept.name}`}\n onClick={() => form.openModal(dept)}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n aria-label={`Delete ${dept.name}`}\n onClick={() => setDeleting(dept)}\n >\n <Trash2 className=\"h-4 w-4 text-status-error-text\" />\n </Button>\n </div>\n </div>\n <CardDescription className=\"flex items-center gap-1\">\n <MapPin className=\"h-3 w-3\" />\n {dept.location}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-2 gap-4 mb-4\">\n <div>\n <p className=\"text-xs text-text-secondary\">Department Head</p>\n <p className=\"text-sm font-medium\">{dept.headName}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Headcount</p>\n <p className=\"text-sm font-medium\">{dept.employeeCount} employees</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Annual Budget</p>\n <p className=\"text-sm font-medium\">${(dept.budget / 1000000).toFixed(1)}M</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Avg Salary</p>\n <p className=\"text-sm font-medium\">${avgSalary.toLocaleString()}</p>\n </div>\n </div>\n <Separator className=\"mb-3\" />\n <div className=\"flex items-center justify-between text-xs\">\n <span className=\"text-text-secondary\">Avg Performance: {avgPerf}/5</span>\n <span className=\"text-text-secondary\">\n Cost/Head:{' '}\n {dept.employeeCount > 0\n ? `$${Math.round(dept.budget / dept.employeeCount / 1000)}K`\n : '—'}\n </span>\n </div>\n </CardContent>\n </Card>\n );\n })}\n </div>\n\n <FormModal\n open={form.open}\n onOpenChange={form.onOpenChange}\n title={editing ? 'Edit department' : 'Add department'}\n description={\n editing\n ? 'Update this department’s details.'\n : 'Create a new department in your organization.'\n }\n fields={DEPARTMENT_FIELDS}\n initialValues={editing ? toFormValues(editing) : undefined}\n submitLabel={editing ? 'Save changes' : 'Add department'}\n onSubmit={handleSubmit}\n />\n\n <ConfirmDialog\n open={deleting !== null}\n onOpenChange={(open) => {\n if (!open) {\n setDeleting(null);\n }\n }}\n title=\"Delete department?\"\n description={\n deleting ? `${deleting.name} will be removed. This cannot be undone.` : undefined\n }\n confirmLabel=\"Delete\"\n destructive\n onConfirm={async () => {\n if (deleting) {\n await removeDepartment(deleting.id);\n setDeleting(null);\n }\n }}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HrDepartmentsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/HrDepartmentsPagePage.tsx"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Building2, DollarSign, MapPin, Network, Pencil, Plus, Trash2, Users } from 'lucide-react';\nimport {\n useCrewFoundryStore,\n type Department,\n type Employee,\n} from '../store/crewfoundryStore';\nimport { AvatarStack, OrgTree, StatCard, type OrgNode } from '../components/viz';\nimport {\n FormModal,\n useFormModal,\n type FieldConfig,\n type FormValues,\n} from '../components/forms/FormModal';\nimport { ConfirmDialog } from '../components/forms/ConfirmDialog';\nimport { getNumber, getText, newClientId } from '../components/forms/formValues';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\n\nconst fullName = (employee: Employee): string => `${employee.firstName} ${employee.lastName}`.trim();\n\nconst DEPARTMENT_FIELDS: FieldConfig[] = [\n { name: 'name', label: 'Department name', type: 'text', required: true, colSpan: 2 },\n { name: 'headName', label: 'Department head', type: 'text', required: true },\n { name: 'location', label: 'Location', type: 'text', required: true },\n { name: 'budget', label: 'Annual budget', type: 'number', required: true },\n {\n name: 'status',\n label: 'Status',\n type: 'select',\n required: true,\n options: [\n { label: 'Active', value: 'active' },\n { label: 'Restructuring', value: 'restructuring' },\n ],\n },\n];\n\nconst toFormValues = (department: Department): FormValues => ({\n name: department.name,\n headName: department.headName,\n location: department.location,\n budget: department.budget,\n status: department.status,\n});\n\nexport function HrDepartmentsPagePage() {\n const { departments, employees, teams, addDepartment, updateDepartment, removeDepartment } =\n useCrewFoundryStore();\n const form = useFormModal<Department>();\n const [deleting, setDeleting] = useState<Department | null>(null);\n\n const totalBudget = departments.reduce((s, d) => s + d.budget, 0);\n const totalHeadcount = departments.reduce((s, d) => s + d.employeeCount, 0);\n\n const editing = form.context;\n\n // Resolve a department's head to a real employee (by id first, then by name) so\n // we can show a real avatar rather than a text-only name.\n const headOf = useCallback(\n (department: Department): Employee | undefined =>\n employees.find((e) => e.id === department.headId) ||\n employees.find((e) => fullName(e) === department.headName),\n [employees]\n );\n\n // Org structure: a real hierarchy derived from the roster + departments + teams.\n // Root = a top-of-org employee (CEO / founder / chief with no manager) when one\n // exists, else a generic company node. Each department hangs off the root with\n // its head; each department's children are its real teams (or a sample of its\n // real employees when the department has no teams).\n const orgRoot = useMemo<OrgNode | null>(() => {\n if (departments.length === 0) {\n return null;\n }\n const topLeader = employees.find(\n (e) => !e.managerId && /chief|ceo|founder|president|head of company/i.test(e.position)\n );\n\n const deptNodes: OrgNode[] = departments.map((department) => {\n const head = headOf(department);\n const deptTeams = teams.filter((team) => team.department === department.name);\n let children: OrgNode[];\n if (deptTeams.length > 0) {\n children = deptTeams.slice(0, 4).map((team) => ({\n id: team.id,\n name: team.name,\n role: `${team.memberCount} member${team.memberCount === 1 ? '' : 's'}`,\n }));\n } else {\n children = employees\n .filter((e) => e.department === department.name && e.id !== head?.id)\n .slice(0, 3)\n .map((e) => ({ id: e.id, name: fullName(e), role: e.position, avatarUrl: e.avatar }));\n }\n return {\n id: department.id,\n name: department.name,\n role: department.headName ? `${department.headName}, Head` : 'Department',\n avatarUrl: head?.avatar,\n children,\n };\n });\n\n return {\n id: topLeader?.id ?? 'org-root',\n name: topLeader ? fullName(topLeader) : 'Organization',\n role: topLeader?.position ?? 'Company',\n avatarUrl: topLeader?.avatar,\n children: deptNodes,\n };\n }, [departments, employees, teams, headOf]);\n\n const handleSubmit = async (values: FormValues) => {\n const payload: Department = {\n id: editing?.id ?? newClientId(),\n name: getText(values, 'name'),\n headId: editing?.headId ?? '',\n headName: getText(values, 'headName'),\n employeeCount: editing?.employeeCount ?? 0,\n budget: getNumber(values, 'budget'),\n location: getText(values, 'location'),\n status: getText(values, 'status') as Department['status'],\n };\n if (editing) {\n await updateDepartment(editing.id, payload);\n } else {\n await addDepartment(payload);\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Departments</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Organizational structure and department management\n </p>\n <PagePurpose className=\"mt-1\">\n Organize your company into departments — set up structure, assign heads, and see how\n headcount is distributed across the org.\n </PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => form.openModal()}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Department\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n <StatCard\n label=\"Total Departments\"\n value={departments.length}\n icon={<Building2 className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Total Headcount\"\n value={totalHeadcount}\n icon={<Users className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Total Budget\"\n value={`$${(totalBudget / 1000000).toFixed(1)}M`}\n icon={<DollarSign className=\"h-4 w-4\" />}\n />\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 xl:grid-cols-3\">\n {departments.map((dept) => {\n const deptEmps = employees.filter((e) => e.department === dept.name);\n const headcount = dept.employeeCount || deptEmps.length;\n const avgSalary =\n deptEmps.length > 0\n ? Math.round(deptEmps.reduce((s, e) => s + e.salary, 0) / deptEmps.length)\n : 0;\n const avgPerfValue =\n deptEmps.length > 0\n ? deptEmps.reduce((s, e) => s + e.performanceScore, 0) / deptEmps.length\n : 0;\n // Progress bar = real average performance for the department, on a 0–100\n // scale (score out of 5). A clearly-labeled, computed metric — no fabrication.\n const perfPct = Math.round((avgPerfValue / 5) * 100);\n const head = headOf(dept);\n const perfTone =\n perfPct >= 80\n ? 'bg-status-success-text'\n : perfPct >= 60\n ? 'bg-status-warning-text'\n : 'bg-status-error-text';\n\n return (\n <GlassCard key={dept.id} treatment=\"glass\" className=\"border-border-seam\">\n <CardHeader>\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <CardTitle className=\"truncate text-lg\">{dept.name}</CardTitle>\n <div className=\"mt-2 flex items-center gap-2\">\n <AvatarStack\n people={[{ name: dept.headName || 'Unassigned', avatarUrl: head?.avatar }]}\n size={28}\n />\n <span className=\"truncate text-sm text-text-secondary\">\n <span className=\"font-medium text-text-primary\">{dept.headName}</span>\n {dept.headName ? ', Head' : 'No head assigned'}\n </span>\n </div>\n </div>\n <div className=\"flex items-center gap-1\">\n <Badge variant={dept.status === 'active' ? 'default' : 'secondary'}>\n {formatEnumLabel(dept.status)}\n </Badge>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n aria-label={`Edit ${dept.name}`}\n onClick={() => form.openModal(dept)}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-8 w-8 p-0\"\n aria-label={`Delete ${dept.name}`}\n onClick={() => setDeleting(dept)}\n >\n <Trash2 className=\"h-4 w-4 text-status-error-text\" />\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"flex items-end justify-between gap-3\">\n <div>\n <p className=\"text-3xl font-bold leading-none tabular-nums\">{headcount}</p>\n <p className=\"mt-1 text-xs text-text-secondary\">Employees</p>\n </div>\n <div className=\"text-right\">\n <p className=\"text-lg font-semibold tabular-nums\">\n ${(dept.budget / 1000000).toFixed(1)}M\n </p>\n <p className=\"text-xs text-text-secondary\">Annual budget</p>\n </div>\n </div>\n\n <div className=\"space-y-1\">\n <div className=\"flex items-center justify-between text-xs text-text-secondary\">\n <span>Avg performance</span>\n <span className=\"font-medium text-text-primary tabular-nums\">{perfPct}%</span>\n </div>\n <div className=\"h-2 overflow-hidden rounded-full bg-bg-sunken\">\n <div className={`h-2 rounded-full ${perfTone}`} style={{ width: `${perfPct}%` }} />\n </div>\n </div>\n\n <div className=\"flex items-center justify-between text-xs text-text-secondary\">\n <span className=\"flex items-center gap-1\">\n <MapPin className=\"h-3 w-3\" />\n {dept.location}\n </span>\n <span>\n Cost/Head:{' '}\n {headcount > 0\n ? `$${Math.round(dept.budget / headcount / 1000)}K`\n : '—'}\n </span>\n </div>\n {avgSalary > 0 && (\n <p className=\"text-xs text-text-secondary\">\n Avg salary <span className=\"font-medium text-text-primary\">${avgSalary.toLocaleString()}</span>\n </p>\n )}\n </CardContent>\n </GlassCard>\n );\n })}\n </div>\n\n {orgRoot && (\n <Card>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-lg\">\n <Network className=\"h-4 w-4 text-text-secondary\" />\n Org structure\n </CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"overflow-x-auto pb-2\">\n <div className=\"min-w-fit\">\n <OrgTree root={orgRoot} />\n </div>\n </div>\n </CardContent>\n </Card>\n )}\n\n <FormModal\n open={form.open}\n onOpenChange={form.onOpenChange}\n title={editing ? 'Edit department' : 'Add department'}\n description={\n editing\n ? 'Update this department’s details.'\n : 'Create a new department in your organization.'\n }\n fields={DEPARTMENT_FIELDS}\n initialValues={editing ? toFormValues(editing) : undefined}\n submitLabel={editing ? 'Save changes' : 'Add department'}\n onSubmit={handleSubmit}\n />\n\n <ConfirmDialog\n open={deleting !== null}\n onOpenChange={(open) => {\n if (!open) {\n setDeleting(null);\n }\n }}\n title=\"Delete department?\"\n description={\n deleting ? `${deleting.name} will be removed. This cannot be undone.` : undefined\n }\n confirmLabel=\"Delete\"\n destructive\n onConfirm={async () => {\n if (deleting) {\n await removeDepartment(deleting.id);\n setDeleting(null);\n }\n }}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|