@burdenoff/microfe-crewfoundry 2026.703.2 → 2026.704.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crewfoundry/pages/AdminAdminPagePage.js +117 -164
- package/dist/crewfoundry/pages/AdminAdminPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +99 -82
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +160 -192
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +238 -231
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +196 -166
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +45 -147
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js +20 -11
- package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js +45 -152
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +50 -138
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js +149 -67
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +50 -201
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +205 -136
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js +25 -31
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js +118 -104
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +117 -58
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js +90 -94
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +210 -191
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +213 -180
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js +133 -264
- package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js.map +1 -1
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js +279 -212
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +131 -105
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +167 -148
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +3 -3
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +13 -5
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +151 -152
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +38 -21
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +3 -3
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js +134 -127
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +163 -132
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +202 -160
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +104 -91
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +29 -147
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +22 -106
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +74 -74
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +101 -97
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +64 -47
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js +111 -121
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPagePage.js +131 -110
- package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +65 -64
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +58 -43
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +66 -82
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +38 -88
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +59 -65
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +209 -323
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +175 -220
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +74 -59
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +96 -80
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js +28 -100
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +27 -20
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +73 -73
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +62 -56
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js +40 -138
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +126 -93
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +99 -77
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js +73 -74
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +1 -1
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +122 -122
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +130 -113
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js +68 -59
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +73 -62
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +82 -58
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +153 -153
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +63 -48
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,26 +2,76 @@ import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
|
2
2
|
import { useMemo as t } from "react";
|
|
3
3
|
import { Activity as n, BarChart3 as r, Calendar as i, PieChart as a, TrendingUp as o, Users as s } from "lucide-react";
|
|
4
4
|
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
5
|
-
import { Badge as u,
|
|
5
|
+
import { Badge as u, Card as d, CardContent as f, CardDescription as p, CardHeader as m, CardTitle as h, GlassCard as g, GradientText as _, PagePurpose as v, ResponsiveTable as y, Tabs as b, TabsContent as x, TabsList as S, TabsTrigger as C } from "@burdenoff/fe-libs/ui";
|
|
6
6
|
//#region src/crewfoundry/pages/AnalyticsAnalyticsPagePage.tsx
|
|
7
7
|
function w() {
|
|
8
8
|
let { employees: w, departments: T, jobPostings: E, candidates: D, projects: O } = e(), k = t(() => {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
if (w.length === 0) return [];
|
|
10
|
+
let e = (e) => {
|
|
11
|
+
let t = new Date(e);
|
|
12
|
+
return `${t.getFullYear()}-${String(t.getMonth()).padStart(2, "0")}`;
|
|
13
|
+
};
|
|
14
|
+
return Array.from(new Set(w.map((t) => e(t.startDate)))).sort().slice(-6).map((t) => {
|
|
15
|
+
let [n, r] = t.split("-").map(Number), i = new Date(n, r + 1, 0).getTime();
|
|
11
16
|
return {
|
|
12
|
-
month: r,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
month: new Date(n, r, 1).toLocaleString("en-US", {
|
|
18
|
+
month: "short",
|
|
19
|
+
year: "2-digit"
|
|
20
|
+
}),
|
|
21
|
+
headcount: w.filter((e) => new Date(e.startDate).getTime() <= i && e.status !== "terminated").length,
|
|
22
|
+
hires: w.filter((n) => e(n.startDate) === t).length,
|
|
23
|
+
exits: w.filter((n) => n.status === "terminated" && e(n.startDate) === t).length
|
|
17
24
|
};
|
|
18
25
|
});
|
|
19
|
-
|
|
20
|
-
}, [w, E]), A = T.map((e) => ({
|
|
26
|
+
}, [w]), A = T.map((e) => ({
|
|
21
27
|
name: e.name,
|
|
22
28
|
count: e.employeeCount,
|
|
23
29
|
budget: e.budget
|
|
24
|
-
})), j = Math.max(1, ...A.map((e) => e.count)), M = Math.max(1, ...k.map((e) => e.headcount)), N =
|
|
30
|
+
})), j = Math.max(1, ...A.map((e) => e.count)), M = Math.max(1, ...k.map((e) => e.headcount)), N = [...A].sort((e, t) => t.count - e.count), P = [
|
|
31
|
+
{
|
|
32
|
+
key: "name",
|
|
33
|
+
header: "Department",
|
|
34
|
+
priority: "primary",
|
|
35
|
+
cell: (e) => /* @__PURE__ */ c("span", {
|
|
36
|
+
className: "font-medium",
|
|
37
|
+
children: e.name
|
|
38
|
+
})
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
key: "count",
|
|
42
|
+
header: "Headcount",
|
|
43
|
+
priority: "secondary",
|
|
44
|
+
cell: (e) => /* @__PURE__ */ c("span", {
|
|
45
|
+
className: "md:block md:text-right",
|
|
46
|
+
children: e.count
|
|
47
|
+
})
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
key: "budget",
|
|
51
|
+
header: "Budget",
|
|
52
|
+
priority: "secondary",
|
|
53
|
+
cell: (e) => /* @__PURE__ */ l("span", {
|
|
54
|
+
className: "md:block md:text-right",
|
|
55
|
+
children: [
|
|
56
|
+
"$",
|
|
57
|
+
(e.budget / 1e6).toFixed(1),
|
|
58
|
+
"M"
|
|
59
|
+
]
|
|
60
|
+
})
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
key: "distribution",
|
|
64
|
+
header: "Distribution",
|
|
65
|
+
priority: "primary",
|
|
66
|
+
cell: (e) => /* @__PURE__ */ c("div", {
|
|
67
|
+
className: "h-3 w-full min-w-24 overflow-hidden rounded bg-bg-sunken",
|
|
68
|
+
children: /* @__PURE__ */ c("div", {
|
|
69
|
+
className: "h-3 rounded bg-action-primary-bg/70",
|
|
70
|
+
style: { width: `${Math.round(e.count / j * 100)}%` }
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
], F = t(() => [
|
|
25
75
|
{
|
|
26
76
|
stage: "Applications",
|
|
27
77
|
count: E.reduce((e, t) => e + t.applicants, 0),
|
|
@@ -52,7 +102,7 @@ function w() {
|
|
|
52
102
|
count: D.filter((e) => e.status === "hired").length,
|
|
53
103
|
color: "bg-status-success-text"
|
|
54
104
|
}
|
|
55
|
-
], [D, E]),
|
|
105
|
+
], [D, E]), I = Math.max(1, ...F.map((e) => e.count));
|
|
56
106
|
return /* @__PURE__ */ l("div", {
|
|
57
107
|
className: "space-y-6 p-6",
|
|
58
108
|
children: [
|
|
@@ -61,36 +111,36 @@ function w() {
|
|
|
61
111
|
children: [/* @__PURE__ */ l("div", { children: [
|
|
62
112
|
/* @__PURE__ */ c("h1", {
|
|
63
113
|
className: "text-2xl font-semibold",
|
|
64
|
-
children: /* @__PURE__ */ c(
|
|
114
|
+
children: /* @__PURE__ */ c(_, { children: "Workforce Analytics" })
|
|
65
115
|
}),
|
|
66
116
|
/* @__PURE__ */ c("p", {
|
|
67
117
|
className: "text-sm text-text-secondary",
|
|
68
118
|
children: "Comprehensive analytics across all HR domains"
|
|
69
119
|
}),
|
|
70
|
-
/* @__PURE__ */ c(
|
|
120
|
+
/* @__PURE__ */ c(v, {
|
|
71
121
|
className: "mt-1",
|
|
72
122
|
children: "Your workforce analytics hub — track headcount, performance, and engagement trends here to spot what's working and where your teams need attention."
|
|
73
123
|
})
|
|
74
|
-
] }), /* @__PURE__ */ l(
|
|
124
|
+
] }), /* @__PURE__ */ l(u, {
|
|
75
125
|
variant: "outline",
|
|
76
|
-
|
|
77
|
-
children: [/* @__PURE__ */ c(i, { className: "
|
|
126
|
+
className: "flex items-center gap-1 self-start",
|
|
127
|
+
children: [/* @__PURE__ */ c(i, { className: "h-3.5 w-3.5" }), "Rolling 6 months"]
|
|
78
128
|
})]
|
|
79
129
|
}),
|
|
80
130
|
/* @__PURE__ */ l("div", {
|
|
81
131
|
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
|
|
82
132
|
children: [
|
|
83
|
-
/* @__PURE__ */ l(
|
|
133
|
+
/* @__PURE__ */ l(g, {
|
|
84
134
|
treatment: "glass",
|
|
85
135
|
glow: !0,
|
|
86
136
|
className: "border-border-seam",
|
|
87
|
-
children: [/* @__PURE__ */ l(
|
|
137
|
+
children: [/* @__PURE__ */ l(m, {
|
|
88
138
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
89
|
-
children: [/* @__PURE__ */ c(
|
|
139
|
+
children: [/* @__PURE__ */ c(h, {
|
|
90
140
|
className: "text-sm font-medium",
|
|
91
141
|
children: "Total Workforce"
|
|
92
142
|
}), /* @__PURE__ */ c(s, { className: "h-4 w-4 text-text-secondary" })]
|
|
93
|
-
}), /* @__PURE__ */ l(
|
|
143
|
+
}), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
|
|
94
144
|
className: "text-2xl font-bold tabular-nums",
|
|
95
145
|
children: w.length
|
|
96
146
|
}), /* @__PURE__ */ l("div", {
|
|
@@ -98,16 +148,16 @@ function w() {
|
|
|
98
148
|
children: [/* @__PURE__ */ c(o, { className: "mr-1 h-3 w-3" }), "Live headcount data"]
|
|
99
149
|
})] })]
|
|
100
150
|
}),
|
|
101
|
-
/* @__PURE__ */ l(
|
|
151
|
+
/* @__PURE__ */ l(g, {
|
|
102
152
|
treatment: "metric",
|
|
103
153
|
className: "border-border-seam",
|
|
104
|
-
children: [/* @__PURE__ */ l(
|
|
154
|
+
children: [/* @__PURE__ */ l(m, {
|
|
105
155
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
106
|
-
children: [/* @__PURE__ */ c(
|
|
156
|
+
children: [/* @__PURE__ */ c(h, {
|
|
107
157
|
className: "text-sm font-medium",
|
|
108
158
|
children: "Active Departments"
|
|
109
159
|
}), /* @__PURE__ */ c(a, { className: "h-4 w-4 text-text-secondary" })]
|
|
110
|
-
}), /* @__PURE__ */ l(
|
|
160
|
+
}), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
|
|
111
161
|
className: "text-2xl font-bold tabular-nums",
|
|
112
162
|
children: T.length
|
|
113
163
|
}), /* @__PURE__ */ c("p", {
|
|
@@ -115,16 +165,16 @@ function w() {
|
|
|
115
165
|
children: "All departments tracked"
|
|
116
166
|
})] })]
|
|
117
167
|
}),
|
|
118
|
-
/* @__PURE__ */ l(
|
|
168
|
+
/* @__PURE__ */ l(g, {
|
|
119
169
|
treatment: "metric",
|
|
120
170
|
className: "border-border-seam",
|
|
121
|
-
children: [/* @__PURE__ */ l(
|
|
171
|
+
children: [/* @__PURE__ */ l(m, {
|
|
122
172
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
123
|
-
children: [/* @__PURE__ */ c(
|
|
173
|
+
children: [/* @__PURE__ */ c(h, {
|
|
124
174
|
className: "text-sm font-medium",
|
|
125
175
|
children: "Active Projects"
|
|
126
176
|
}), /* @__PURE__ */ c(n, { className: "h-4 w-4 text-text-secondary" })]
|
|
127
|
-
}), /* @__PURE__ */ l(
|
|
177
|
+
}), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
|
|
128
178
|
className: "text-2xl font-bold tabular-nums",
|
|
129
179
|
children: O.filter((e) => e.status === "active").length
|
|
130
180
|
}), /* @__PURE__ */ l("p", {
|
|
@@ -132,16 +182,16 @@ function w() {
|
|
|
132
182
|
children: [O.filter((e) => e.status === "completed").length, " completed"]
|
|
133
183
|
})] })]
|
|
134
184
|
}),
|
|
135
|
-
/* @__PURE__ */ l(
|
|
185
|
+
/* @__PURE__ */ l(g, {
|
|
136
186
|
treatment: "metric",
|
|
137
187
|
className: "border-border-seam",
|
|
138
|
-
children: [/* @__PURE__ */ l(
|
|
188
|
+
children: [/* @__PURE__ */ l(m, {
|
|
139
189
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
140
|
-
children: [/* @__PURE__ */ c(
|
|
190
|
+
children: [/* @__PURE__ */ c(h, {
|
|
141
191
|
className: "text-sm font-medium",
|
|
142
192
|
children: "Hiring Pipeline"
|
|
143
193
|
}), /* @__PURE__ */ c(r, { className: "h-4 w-4 text-text-secondary" })]
|
|
144
|
-
}), /* @__PURE__ */ l(
|
|
194
|
+
}), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
|
|
145
195
|
className: "text-2xl font-bold tabular-nums",
|
|
146
196
|
children: D.length
|
|
147
197
|
}), /* @__PURE__ */ c("p", {
|
|
@@ -171,7 +221,7 @@ function w() {
|
|
|
171
221
|
/* @__PURE__ */ c(x, {
|
|
172
222
|
value: "overview",
|
|
173
223
|
className: "space-y-4",
|
|
174
|
-
children: /* @__PURE__ */ l(
|
|
224
|
+
children: /* @__PURE__ */ l(d, { children: [/* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c(h, { children: "Workforce Growth Trend" }), /* @__PURE__ */ c(p, { children: "Monthly headcount and hiring activity" })] }), /* @__PURE__ */ c(f, {
|
|
175
225
|
className: "space-y-3",
|
|
176
226
|
children: k.map((e) => /* @__PURE__ */ l("div", {
|
|
177
227
|
className: "flex items-center gap-3",
|
|
@@ -201,10 +251,14 @@ function w() {
|
|
|
201
251
|
e.hires,
|
|
202
252
|
" hired"
|
|
203
253
|
]
|
|
204
|
-
}), /* @__PURE__ */ l(u, {
|
|
205
|
-
variant: "
|
|
254
|
+
}), e.exits > 0 && /* @__PURE__ */ l(u, {
|
|
255
|
+
variant: "destructive",
|
|
206
256
|
className: "text-[10px]",
|
|
207
|
-
children: [
|
|
257
|
+
children: [
|
|
258
|
+
"-",
|
|
259
|
+
e.exits,
|
|
260
|
+
" exits"
|
|
261
|
+
]
|
|
208
262
|
})]
|
|
209
263
|
})
|
|
210
264
|
]
|
|
@@ -214,9 +268,9 @@ function w() {
|
|
|
214
268
|
/* @__PURE__ */ c(x, {
|
|
215
269
|
value: "hiring",
|
|
216
270
|
className: "space-y-4",
|
|
217
|
-
children: /* @__PURE__ */ l(
|
|
271
|
+
children: /* @__PURE__ */ l(d, { children: [/* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c(h, { children: "Hiring Funnel" }), /* @__PURE__ */ c(p, { children: "Candidate pipeline stages" })] }), /* @__PURE__ */ c(f, {
|
|
218
272
|
className: "space-y-4",
|
|
219
|
-
children:
|
|
273
|
+
children: F.map((e) => /* @__PURE__ */ l("div", {
|
|
220
274
|
className: "flex items-center gap-3",
|
|
221
275
|
children: [
|
|
222
276
|
/* @__PURE__ */ c("span", {
|
|
@@ -227,7 +281,7 @@ function w() {
|
|
|
227
281
|
className: "h-6 flex-1 overflow-hidden rounded bg-bg-sunken",
|
|
228
282
|
children: /* @__PURE__ */ c("div", {
|
|
229
283
|
className: `h-6 rounded ${e.color}`,
|
|
230
|
-
style: { width: `${Math.max(Math.round(e.count /
|
|
284
|
+
style: { width: `${Math.max(Math.round(e.count / I * 100), 5)}%` }
|
|
231
285
|
})
|
|
232
286
|
}),
|
|
233
287
|
/* @__PURE__ */ c("span", {
|
|
@@ -241,48 +295,11 @@ function w() {
|
|
|
241
295
|
/* @__PURE__ */ c(x, {
|
|
242
296
|
value: "departments",
|
|
243
297
|
className: "space-y-4",
|
|
244
|
-
children: /* @__PURE__ */ l(
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
className: "text-right",
|
|
250
|
-
children: "Headcount"
|
|
251
|
-
}),
|
|
252
|
-
/* @__PURE__ */ c("span", {
|
|
253
|
-
className: "text-right",
|
|
254
|
-
children: "Budget"
|
|
255
|
-
}),
|
|
256
|
-
/* @__PURE__ */ c("span", { children: "Distribution" })
|
|
257
|
-
]
|
|
258
|
-
}), A.sort((e, t) => t.count - e.count).map((e) => /* @__PURE__ */ l("div", {
|
|
259
|
-
className: "grid grid-cols-4 items-center gap-2 border-b py-2 text-sm last:border-0",
|
|
260
|
-
children: [
|
|
261
|
-
/* @__PURE__ */ c("span", {
|
|
262
|
-
className: "font-medium",
|
|
263
|
-
children: e.name
|
|
264
|
-
}),
|
|
265
|
-
/* @__PURE__ */ c("span", {
|
|
266
|
-
className: "text-right",
|
|
267
|
-
children: e.count
|
|
268
|
-
}),
|
|
269
|
-
/* @__PURE__ */ l("span", {
|
|
270
|
-
className: "text-right",
|
|
271
|
-
children: [
|
|
272
|
-
"$",
|
|
273
|
-
(e.budget / 1e6).toFixed(1),
|
|
274
|
-
"M"
|
|
275
|
-
]
|
|
276
|
-
}),
|
|
277
|
-
/* @__PURE__ */ c("div", {
|
|
278
|
-
className: "h-3 overflow-hidden rounded bg-bg-sunken",
|
|
279
|
-
children: /* @__PURE__ */ c("div", {
|
|
280
|
-
className: "h-3 rounded bg-action-primary-bg/70",
|
|
281
|
-
style: { width: `${Math.round(e.count / j * 100)}%` }
|
|
282
|
-
})
|
|
283
|
-
})
|
|
284
|
-
]
|
|
285
|
-
}, e.name))] })] })
|
|
298
|
+
children: /* @__PURE__ */ l(d, { children: [/* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c(h, { children: "Department Breakdown" }), /* @__PURE__ */ c(p, { children: "Headcount and budget by department" })] }), /* @__PURE__ */ c(f, { children: /* @__PURE__ */ c(y, {
|
|
299
|
+
columns: P,
|
|
300
|
+
data: N,
|
|
301
|
+
rowKey: (e) => e.name
|
|
302
|
+
}) })] })
|
|
286
303
|
})
|
|
287
304
|
]
|
|
288
305
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnalyticsAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/AnalyticsAnalyticsPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { Activity, BarChart3, Calendar, PieChart, TrendingUp, Users } from 'lucide-react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype MonthlyMetric = {\n month: string;\n headcount: number;\n hires: number;\n exits: number;\n openRoles: number;\n};\n\ntype FunnelStage = {\n stage: string;\n count: number;\n color: string;\n};\n\nexport function AnalyticsAnalyticsPagePage() {\n const { employees, departments, jobPostings, candidates, projects } = useCrewFoundryStore();\n\n const monthlyMetrics = useMemo<MonthlyMetric[]>(() => {\n const sortedEmployees = [...employees].sort((a, b) => a.startDate.localeCompare(b.startDate));\n const months = sortedEmployees.slice(-6).map((employee, index) => {\n const month = new Date(employee.startDate).toLocaleString('en-US', { month: 'short' });\n const hires = sortedEmployees.filter(\n (item) =>\n new Date(item.startDate).toLocaleString('en-US', { month: 'short' }) === month &&\n item.status === 'active'\n ).length;\n const exits = sortedEmployees.filter(\n (item) =>\n new Date(item.startDate).toLocaleString('en-US', { month: 'short' }) === month &&\n item.status === 'terminated'\n ).length;\n return {\n month,\n headcount: Math.max(1, sortedEmployees.length - (5 - index) * 2),\n hires,\n exits,\n openRoles: Math.max(\n 0,\n jobPostings.filter((posting) => posting.status === 'active').length - index\n ),\n };\n });\n return months.length > 0 ? months : [];\n }, [employees, jobPostings]);\n\n const deptDistribution = departments.map((department) => ({\n name: department.name,\n count: department.employeeCount,\n budget: department.budget,\n }));\n\n const maxDeptCount = Math.max(1, ...deptDistribution.map((department) => department.count));\n const maxMetric = Math.max(1, ...monthlyMetrics.map((metric) => metric.headcount));\n\n const hiringFunnel = useMemo<FunnelStage[]>(\n () => [\n {\n stage: 'Applications',\n count: jobPostings.reduce((sum, posting) => sum + posting.applicants, 0),\n color: 'bg-status-info-text',\n },\n {\n stage: 'Screening',\n count: candidates.filter((candidate) => candidate.status === 'screening').length,\n color: 'bg-status-info-text',\n },\n {\n stage: 'Interview',\n count: candidates.filter((candidate) => candidate.status === 'interview').length,\n color: 'bg-action-primary-bg',\n },\n {\n stage: 'Assessment',\n count: candidates.filter((candidate) => candidate.status === 'assessment').length,\n color: 'bg-action-primary-bg',\n },\n {\n stage: 'Offer',\n count: candidates.filter((candidate) => candidate.status === 'offer').length,\n color: 'bg-status-warning-text',\n },\n {\n stage: 'Hired',\n count: candidates.filter((candidate) => candidate.status === 'hired').length,\n color: 'bg-status-success-text',\n },\n ],\n [candidates, jobPostings]\n );\n\n const maxFunnel = Math.max(1, ...hiringFunnel.map((stage) => stage.count));\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>Workforce Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Comprehensive analytics across all HR domains\n </p>\n <PagePurpose className=\"mt-1\">Your workforce analytics hub — track headcount, performance, and engagement trends here to spot what's working and where your teams need attention.</PagePurpose>\n </div>\n <Button variant=\"outline\" size=\"sm\">\n <Calendar className=\"mr-2 h-4 w-4\" />\n Rolling 6 Months\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\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 Workforce</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{employees.length}</div>\n <div className=\"flex items-center text-xs text-status-success-text\">\n <TrendingUp className=\"mr-1 h-3 w-3\" />\n Live headcount data\n </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\">Active Departments</CardTitle>\n <PieChart 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 <p className=\"text-xs text-text-secondary\">All departments tracked</p>\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\">Active Projects</CardTitle>\n <Activity className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {projects.filter((project) => project.status === 'active').length}\n </div>\n <p className=\"text-xs text-text-secondary\">\n {projects.filter((project) => project.status === 'completed').length} completed\n </p>\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\">Hiring Pipeline</CardTitle>\n <BarChart3 className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{candidates.length}</div>\n <p className=\"text-xs text-text-secondary\">candidates in pipeline</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <Tabs defaultValue=\"overview\">\n <TabsList>\n <TabsTrigger value=\"overview\">Overview</TabsTrigger>\n <TabsTrigger value=\"hiring\">Hiring Funnel</TabsTrigger>\n <TabsTrigger value=\"departments\">Departments</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"overview\" className=\"space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>Workforce Growth Trend</CardTitle>\n <CardDescription>Monthly headcount and hiring activity</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {monthlyMetrics.map((metric) => (\n <div\n key={`${metric.month}-${metric.headcount}`}\n className=\"flex items-center gap-3\"\n >\n <span className=\"w-10 text-sm text-text-secondary\">{metric.month}</span>\n <div className=\"h-5 flex-1 overflow-hidden rounded bg-bg-sunken\">\n <div\n className=\"h-5 rounded bg-action-primary-bg\"\n style={{ width: `${Math.round((metric.headcount / maxMetric) * 100)}%` }}\n />\n </div>\n <span className=\"w-10 text-right text-sm font-medium\">{metric.headcount}</span>\n <div className=\"flex w-32 justify-end gap-1\">\n <Badge variant=\"default\" className=\"text-[10px]\">\n +{metric.hires} hired\n </Badge>\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n {metric.openRoles} open\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </TabsContent>\n\n <TabsContent value=\"hiring\" className=\"space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>Hiring Funnel</CardTitle>\n <CardDescription>Candidate pipeline stages</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {hiringFunnel.map((stage) => (\n <div key={stage.stage} className=\"flex items-center gap-3\">\n <span className=\"w-28 text-sm font-medium\">{stage.stage}</span>\n <div className=\"h-6 flex-1 overflow-hidden rounded bg-bg-sunken\">\n <div\n className={`h-6 rounded ${stage.color}`}\n style={{\n width: `${Math.max(Math.round((stage.count / maxFunnel) * 100), 5)}%`,\n }}\n />\n </div>\n <span className=\"w-10 text-right text-sm font-bold\">{stage.count}</span>\n </div>\n ))}\n </CardContent>\n </Card>\n </TabsContent>\n\n <TabsContent value=\"departments\" className=\"space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>Department Breakdown</CardTitle>\n <CardDescription>Headcount and budget by department</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"mb-2 grid grid-cols-4 gap-2 border-b pb-2 text-xs font-medium text-text-secondary\">\n <span>Department</span>\n <span className=\"text-right\">Headcount</span>\n <span className=\"text-right\">Budget</span>\n <span>Distribution</span>\n </div>\n {deptDistribution\n .sort((a, b) => b.count - a.count)\n .map((department) => (\n <div\n key={department.name}\n className=\"grid grid-cols-4 items-center gap-2 border-b py-2 text-sm last:border-0\"\n >\n <span className=\"font-medium\">{department.name}</span>\n <span className=\"text-right\">{department.count}</span>\n <span className=\"text-right\">${(department.budget / 1000000).toFixed(1)}M</span>\n <div className=\"h-3 overflow-hidden rounded bg-bg-sunken\">\n <div\n className=\"h-3 rounded bg-action-primary-bg/70\"\n style={{ width: `${Math.round((department.count / maxDeptCount) * 100)}%` }}\n />\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AnalyticsAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/AnalyticsAnalyticsPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { Activity, BarChart3, Calendar, PieChart, TrendingUp, Users } from 'lucide-react';\nimport {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n ResponsiveTable,\n type ResponsiveTableColumn,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype MonthlyMetric = {\n month: string;\n headcount: number;\n hires: number;\n exits: number;\n};\n\ntype DeptRow = {\n name: string;\n count: number;\n budget: number;\n};\n\ntype FunnelStage = {\n stage: string;\n count: number;\n color: string;\n};\n\nexport function AnalyticsAnalyticsPagePage() {\n const { employees, departments, jobPostings, candidates, projects } = useCrewFoundryStore();\n\n const monthlyMetrics = useMemo<MonthlyMetric[]>(() => {\n if (employees.length === 0) {\n return [];\n }\n const monthKey = (value: string) => {\n const date = new Date(value);\n return `${date.getFullYear()}-${String(date.getMonth()).padStart(2, '0')}`;\n };\n const distinctMonths = Array.from(new Set(employees.map((item) => monthKey(item.startDate))))\n .sort()\n .slice(-6);\n return distinctMonths.map((key) => {\n const [year, month] = key.split('-').map(Number);\n const monthEnd = new Date(year, month + 1, 0).getTime();\n const label = new Date(year, month, 1).toLocaleString('en-US', {\n month: 'short',\n year: '2-digit',\n });\n // Real cumulative headcount as of month end, and real hires/exits in month.\n const headcount = employees.filter(\n (item) => new Date(item.startDate).getTime() <= monthEnd && item.status !== 'terminated'\n ).length;\n const hires = employees.filter((item) => monthKey(item.startDate) === key).length;\n const exits = employees.filter(\n (item) => item.status === 'terminated' && monthKey(item.startDate) === key\n ).length;\n return { month: label, headcount, hires, exits };\n });\n }, [employees]);\n\n const deptDistribution = departments.map((department) => ({\n name: department.name,\n count: department.employeeCount,\n budget: department.budget,\n }));\n\n const maxDeptCount = Math.max(1, ...deptDistribution.map((department) => department.count));\n const maxMetric = Math.max(1, ...monthlyMetrics.map((metric) => metric.headcount));\n\n const sortedDeptDistribution = [...deptDistribution].sort((a, b) => b.count - a.count);\n\n const deptColumns: ResponsiveTableColumn<DeptRow>[] = [\n {\n key: 'name',\n header: 'Department',\n priority: 'primary',\n cell: (department) => <span className=\"font-medium\">{department.name}</span>,\n },\n {\n key: 'count',\n header: 'Headcount',\n priority: 'secondary',\n cell: (department) => <span className=\"md:block md:text-right\">{department.count}</span>,\n },\n {\n key: 'budget',\n header: 'Budget',\n priority: 'secondary',\n cell: (department) => (\n <span className=\"md:block md:text-right\">\n ${(department.budget / 1000000).toFixed(1)}M\n </span>\n ),\n },\n {\n key: 'distribution',\n header: 'Distribution',\n priority: 'primary',\n cell: (department) => (\n <div className=\"h-3 w-full min-w-24 overflow-hidden rounded bg-bg-sunken\">\n <div\n className=\"h-3 rounded bg-action-primary-bg/70\"\n style={{ width: `${Math.round((department.count / maxDeptCount) * 100)}%` }}\n />\n </div>\n ),\n },\n ];\n\n const hiringFunnel = useMemo<FunnelStage[]>(\n () => [\n {\n stage: 'Applications',\n count: jobPostings.reduce((sum, posting) => sum + posting.applicants, 0),\n color: 'bg-status-info-text',\n },\n {\n stage: 'Screening',\n count: candidates.filter((candidate) => candidate.status === 'screening').length,\n color: 'bg-status-info-text',\n },\n {\n stage: 'Interview',\n count: candidates.filter((candidate) => candidate.status === 'interview').length,\n color: 'bg-action-primary-bg',\n },\n {\n stage: 'Assessment',\n count: candidates.filter((candidate) => candidate.status === 'assessment').length,\n color: 'bg-action-primary-bg',\n },\n {\n stage: 'Offer',\n count: candidates.filter((candidate) => candidate.status === 'offer').length,\n color: 'bg-status-warning-text',\n },\n {\n stage: 'Hired',\n count: candidates.filter((candidate) => candidate.status === 'hired').length,\n color: 'bg-status-success-text',\n },\n ],\n [candidates, jobPostings]\n );\n\n const maxFunnel = Math.max(1, ...hiringFunnel.map((stage) => stage.count));\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>Workforce Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Comprehensive analytics across all HR domains\n </p>\n <PagePurpose className=\"mt-1\">Your workforce analytics hub — track headcount, performance, and engagement trends here to spot what's working and where your teams need attention.</PagePurpose>\n </div>\n <Badge variant=\"outline\" className=\"flex items-center gap-1 self-start\">\n <Calendar className=\"h-3.5 w-3.5\" />\n Rolling 6 months\n </Badge>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\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 Workforce</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{employees.length}</div>\n <div className=\"flex items-center text-xs text-status-success-text\">\n <TrendingUp className=\"mr-1 h-3 w-3\" />\n Live headcount data\n </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\">Active Departments</CardTitle>\n <PieChart 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 <p className=\"text-xs text-text-secondary\">All departments tracked</p>\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\">Active Projects</CardTitle>\n <Activity className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {projects.filter((project) => project.status === 'active').length}\n </div>\n <p className=\"text-xs text-text-secondary\">\n {projects.filter((project) => project.status === 'completed').length} completed\n </p>\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\">Hiring Pipeline</CardTitle>\n <BarChart3 className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{candidates.length}</div>\n <p className=\"text-xs text-text-secondary\">candidates in pipeline</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <Tabs defaultValue=\"overview\">\n <TabsList>\n <TabsTrigger value=\"overview\">Overview</TabsTrigger>\n <TabsTrigger value=\"hiring\">Hiring Funnel</TabsTrigger>\n <TabsTrigger value=\"departments\">Departments</TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"overview\" className=\"space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>Workforce Growth Trend</CardTitle>\n <CardDescription>Monthly headcount and hiring activity</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {monthlyMetrics.map((metric) => (\n <div\n key={`${metric.month}-${metric.headcount}`}\n className=\"flex items-center gap-3\"\n >\n <span className=\"w-10 text-sm text-text-secondary\">{metric.month}</span>\n <div className=\"h-5 flex-1 overflow-hidden rounded bg-bg-sunken\">\n <div\n className=\"h-5 rounded bg-action-primary-bg\"\n style={{ width: `${Math.round((metric.headcount / maxMetric) * 100)}%` }}\n />\n </div>\n <span className=\"w-10 text-right text-sm font-medium\">{metric.headcount}</span>\n <div className=\"flex w-32 justify-end gap-1\">\n <Badge variant=\"default\" className=\"text-[10px]\">\n +{metric.hires} hired\n </Badge>\n {metric.exits > 0 && (\n <Badge variant=\"destructive\" className=\"text-[10px]\">\n -{metric.exits} exits\n </Badge>\n )}\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </TabsContent>\n\n <TabsContent value=\"hiring\" className=\"space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>Hiring Funnel</CardTitle>\n <CardDescription>Candidate pipeline stages</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {hiringFunnel.map((stage) => (\n <div key={stage.stage} className=\"flex items-center gap-3\">\n <span className=\"w-28 text-sm font-medium\">{stage.stage}</span>\n <div className=\"h-6 flex-1 overflow-hidden rounded bg-bg-sunken\">\n <div\n className={`h-6 rounded ${stage.color}`}\n style={{\n width: `${Math.max(Math.round((stage.count / maxFunnel) * 100), 5)}%`,\n }}\n />\n </div>\n <span className=\"w-10 text-right text-sm font-bold\">{stage.count}</span>\n </div>\n ))}\n </CardContent>\n </Card>\n </TabsContent>\n\n <TabsContent value=\"departments\" className=\"space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>Department Breakdown</CardTitle>\n <CardDescription>Headcount and budget by department</CardDescription>\n </CardHeader>\n <CardContent>\n <ResponsiveTable\n columns={deptColumns}\n data={sortedDeptDistribution}\n rowKey={(department) => department.name}\n />\n </CardContent>\n </Card>\n </TabsContent>\n </Tabs>\n </div>\n );\n}\n"],"mappings":"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"}
|