@burdenoff/microfe-crewfoundry 2026.704.6 → 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.
Files changed (148) hide show
  1. package/dist/crewfoundry/CrewFoundryRoutes.js +51 -43
  2. package/dist/crewfoundry/CrewFoundryRoutes.js.map +1 -1
  3. package/dist/crewfoundry/components/forms/formValues.js +5 -2
  4. package/dist/crewfoundry/components/forms/formValues.js.map +1 -1
  5. package/dist/crewfoundry/components/viz/AllocationBar.js +68 -0
  6. package/dist/crewfoundry/components/viz/AllocationBar.js.map +1 -0
  7. package/dist/crewfoundry/components/viz/AreaChart.js +102 -0
  8. package/dist/crewfoundry/components/viz/AreaChart.js.map +1 -0
  9. package/dist/crewfoundry/components/viz/AvatarStack.js +36 -0
  10. package/dist/crewfoundry/components/viz/AvatarStack.js.map +1 -0
  11. package/dist/crewfoundry/components/viz/BarChart.js +83 -0
  12. package/dist/crewfoundry/components/viz/BarChart.js.map +1 -0
  13. package/dist/crewfoundry/components/viz/CertificateCard.js +118 -0
  14. package/dist/crewfoundry/components/viz/CertificateCard.js.map +1 -0
  15. package/dist/crewfoundry/components/viz/DonutChart.js +109 -0
  16. package/dist/crewfoundry/components/viz/DonutChart.js.map +1 -0
  17. package/dist/crewfoundry/components/viz/HBarFunnel.js +54 -0
  18. package/dist/crewfoundry/components/viz/HBarFunnel.js.map +1 -0
  19. package/dist/crewfoundry/components/viz/Heatmap.js +91 -0
  20. package/dist/crewfoundry/components/viz/Heatmap.js.map +1 -0
  21. package/dist/crewfoundry/components/viz/KanbanBoard.js +50 -0
  22. package/dist/crewfoundry/components/viz/KanbanBoard.js.map +1 -0
  23. package/dist/crewfoundry/components/viz/LineChart.js +123 -0
  24. package/dist/crewfoundry/components/viz/LineChart.js.map +1 -0
  25. package/dist/crewfoundry/components/viz/OrgTree.js +83 -0
  26. package/dist/crewfoundry/components/viz/OrgTree.js.map +1 -0
  27. package/dist/crewfoundry/components/viz/PathSteps.js +68 -0
  28. package/dist/crewfoundry/components/viz/PathSteps.js.map +1 -0
  29. package/dist/crewfoundry/components/viz/ProgressRing.js +68 -0
  30. package/dist/crewfoundry/components/viz/ProgressRing.js.map +1 -0
  31. package/dist/crewfoundry/components/viz/RatingStars.js +51 -0
  32. package/dist/crewfoundry/components/viz/RatingStars.js.map +1 -0
  33. package/dist/crewfoundry/components/viz/SegmentedTabs.js +69 -0
  34. package/dist/crewfoundry/components/viz/SegmentedTabs.js.map +1 -0
  35. package/dist/crewfoundry/components/viz/SkillBar.js +3 -0
  36. package/dist/crewfoundry/components/viz/Sparkline.js +74 -0
  37. package/dist/crewfoundry/components/viz/Sparkline.js.map +1 -0
  38. package/dist/crewfoundry/components/viz/StatCard.js +60 -0
  39. package/dist/crewfoundry/components/viz/StatCard.js.map +1 -0
  40. package/dist/crewfoundry/components/viz/StepProgress.js +3 -0
  41. package/dist/crewfoundry/components/viz/Timeline.js +66 -0
  42. package/dist/crewfoundry/components/viz/Timeline.js.map +1 -0
  43. package/dist/crewfoundry/components/viz/index.js +23 -0
  44. package/dist/crewfoundry/components/viz/lib/Avatar.js +30 -0
  45. package/dist/crewfoundry/components/viz/lib/Avatar.js.map +1 -0
  46. package/dist/crewfoundry/components/viz/lib/CartesianFrame.js +119 -0
  47. package/dist/crewfoundry/components/viz/lib/CartesianFrame.js.map +1 -0
  48. package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js +35 -0
  49. package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js.map +1 -0
  50. package/dist/crewfoundry/components/viz/lib/format.js +21 -0
  51. package/dist/crewfoundry/components/viz/lib/format.js.map +1 -0
  52. package/dist/crewfoundry/components/viz/lib/geometry.js +69 -0
  53. package/dist/crewfoundry/components/viz/lib/geometry.js.map +1 -0
  54. package/dist/crewfoundry/components/viz/lib/hooks.js +39 -0
  55. package/dist/crewfoundry/components/viz/lib/hooks.js.map +1 -0
  56. package/dist/crewfoundry/components/viz/lib/palette.js +27 -0
  57. package/dist/crewfoundry/components/viz/lib/palette.js.map +1 -0
  58. package/dist/crewfoundry/lib/analytics.js +323 -0
  59. package/dist/crewfoundry/lib/analytics.js.map +1 -0
  60. package/dist/crewfoundry/lib/companyFinance.js +16 -0
  61. package/dist/crewfoundry/lib/companyFinance.js.map +1 -0
  62. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +226 -283
  63. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  64. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +107 -120
  65. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
  66. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +122 -162
  67. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
  68. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +121 -158
  69. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
  70. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +316 -211
  71. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
  72. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +75 -27
  73. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
  74. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +167 -165
  75. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
  76. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +168 -109
  77. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
  78. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +401 -290
  79. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
  80. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +84 -75
  81. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
  82. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +368 -174
  83. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
  84. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +236 -201
  85. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
  86. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +369 -196
  87. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
  88. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +269 -270
  89. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
  90. package/dist/crewfoundry/pages/HiringJobsPagePage.js +210 -110
  91. package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
  92. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +216 -178
  93. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
  94. package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js +385 -0
  95. package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js.map +1 -0
  96. package/dist/crewfoundry/pages/HrEmployeesPagePage.js +189 -130
  97. package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
  98. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +397 -241
  99. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
  100. package/dist/crewfoundry/pages/HrPayrollPagePage.js +262 -147
  101. package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
  102. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +345 -167
  103. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
  104. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +98 -24
  105. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
  106. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +1 -1
  107. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
  108. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +289 -108
  109. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
  110. package/dist/crewfoundry/pages/LearningCoursesPagePage.js +221 -114
  111. package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
  112. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +134 -135
  113. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
  114. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +148 -97
  115. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
  116. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +264 -157
  117. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
  118. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +85 -93
  119. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
  120. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +211 -122
  121. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
  122. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +94 -54
  123. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
  124. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +289 -140
  125. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
  126. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +169 -79
  127. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
  128. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +296 -125
  129. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
  130. package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js +187 -0
  131. package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js.map +1 -0
  132. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +140 -78
  133. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
  134. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +93 -43
  135. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
  136. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +250 -98
  137. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
  138. package/dist/crewfoundry/store/crewfoundryStore.js +1 -1
  139. package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
  140. package/dist/crewfoundry/utils/cn.js +10 -0
  141. package/dist/crewfoundry/utils/cn.js.map +1 -0
  142. package/dist/crewfoundry/utils/courseProgress.js +46 -0
  143. package/dist/crewfoundry/utils/courseProgress.js.map +1 -0
  144. package/dist/node_modules/clsx/dist/clsx.js +18 -0
  145. package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
  146. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
  147. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  148. package/package.json +1 -1
@@ -1,312 +1,255 @@
1
1
  import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
- import { useMemo as t } from "react";
3
- import { Activity as n, BarChart3 as r, Calendar as i, PieChart as a, TrendingUp as o, Users as s } from "lucide-react";
4
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
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";
2
+ import { AreaChart as t } from "../components/viz/AreaChart.js";
3
+ import { LineChart as n } from "../components/viz/LineChart.js";
4
+ import { BarChart as r } from "../components/viz/BarChart.js";
5
+ import { HBarFunnel as i } from "../components/viz/HBarFunnel.js";
6
+ import { DonutChart as a } from "../components/viz/DonutChart.js";
7
+ import { StatCard as o } from "../components/viz/StatCard.js";
8
+ import { SegmentedTabs as s } from "../components/viz/SegmentedTabs.js";
9
+ import "../components/viz/index.js";
10
+ import { attritionTrend as c, benchAndOverallocated as l, deptHeadcount as u, headcountByMonth as d, momDelta as f, performanceDistribution as p, timeToHire as m, utilizationByPersonWeek as h } from "../lib/analytics.js";
11
+ import { useMemo as g, useState as _ } from "react";
12
+ import { Activity as v, BarChart3 as y, Download as b, PieChart as x, Users as S } from "lucide-react";
13
+ import { jsx as C, jsxs as w } from "react/jsx-runtime";
14
+ import { Button as T, Card as E, CardContent as D, CardHeader as O, CardTitle as k, GradientText as A, IllustratedEmptyState as j, PagePurpose as M } from "@burdenoff/fe-libs/ui";
6
15
  //#region src/crewfoundry/pages/AnalyticsAnalyticsPagePage.tsx
7
- function w() {
8
- let { employees: w, departments: T, jobPostings: E, candidates: D, projects: O } = e(), k = t(() => {
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();
16
- return {
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
24
- };
16
+ var N = [
17
+ "new",
18
+ "screening",
19
+ "interview",
20
+ "assessment",
21
+ "offer",
22
+ "hired"
23
+ ], P = [
24
+ "Needs",
25
+ "Meets",
26
+ "Exceeds",
27
+ "Outstanding"
28
+ ];
29
+ function F(e) {
30
+ return `"${String(e).replace(/"/g, "\"\"")}"`;
31
+ }
32
+ function I() {
33
+ let { employees: I, departments: L, candidates: R, projects: z, timeEntries: B } = e(), [V, H] = _("12"), U = g(() => d(I), [I]), W = f(U).deltaPercent, G = z.filter((e) => e.status === "active").length, K = g(() => u(L).slice(0, 8), [L]), q = g(() => {
34
+ if (R.length === 0) return R;
35
+ let e = R.map((e) => new Date(e.appliedDate).getTime()).filter((e) => !Number.isNaN(e));
36
+ if (e.length === 0) return R;
37
+ let t = Math.max(...e) - Number(V) * 30 * 24 * 60 * 60 * 1e3, n = R.filter((e) => {
38
+ let n = new Date(e.appliedDate).getTime();
39
+ return Number.isNaN(n) || n >= t;
25
40
  });
26
- }, [w]), A = T.map((e) => ({
27
- name: e.name,
28
- count: e.employeeCount,
29
- budget: e.budget
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(() => [
75
- {
76
- stage: "Applications",
77
- count: E.reduce((e, t) => e + t.applicants, 0),
78
- color: "bg-status-info-text"
79
- },
80
- {
81
- stage: "Screening",
82
- count: D.filter((e) => e.status === "screening").length,
83
- color: "bg-status-info-text"
84
- },
85
- {
86
- stage: "Interview",
87
- count: D.filter((e) => e.status === "interview").length,
88
- color: "bg-action-primary-bg"
89
- },
90
- {
91
- stage: "Assessment",
92
- count: D.filter((e) => e.status === "assessment").length,
93
- color: "bg-action-primary-bg"
94
- },
95
- {
96
- stage: "Offer",
97
- count: D.filter((e) => e.status === "offer").length,
98
- color: "bg-status-warning-text"
99
- },
100
- {
101
- stage: "Hired",
102
- count: D.filter((e) => e.status === "hired").length,
103
- color: "bg-status-success-text"
104
- }
105
- ], [D, E]), I = Math.max(1, ...F.map((e) => e.count));
106
- return /* @__PURE__ */ l("div", {
41
+ return n.length > 0 ? n : R;
42
+ }, [R, V]), J = g(() => {
43
+ let e = (e) => N.indexOf(e), t = (t) => q.filter((n) => e(n.status) >= t).length;
44
+ return [
45
+ {
46
+ label: "Applied",
47
+ value: q.length
48
+ },
49
+ {
50
+ label: "Screened",
51
+ value: t(1)
52
+ },
53
+ {
54
+ label: "Interviewed",
55
+ value: t(2)
56
+ },
57
+ {
58
+ label: "Offer",
59
+ value: t(4)
60
+ },
61
+ {
62
+ label: "Hired",
63
+ value: t(5)
64
+ }
65
+ ];
66
+ }, [q]), Y = g(() => p(I).map((e, t) => ({
67
+ label: P[t],
68
+ value: e.value
69
+ })), [I]), X = g(() => c(I), [I]), Z = g(() => {
70
+ let e = h(B, I);
71
+ if (!e.hasData) return null;
72
+ let t = l(e, I), n = Math.min(Math.max(t.avgUtilization, 0), 100);
73
+ return {
74
+ utilized: n,
75
+ available: Math.max(0, 100 - n)
76
+ };
77
+ }, [B, I]), Q = Z ? [{
78
+ label: "Utilized",
79
+ value: Z.utilized
80
+ }, {
81
+ label: "Available",
82
+ value: Z.available,
83
+ color: "var(--color-chart-grid)"
84
+ }] : null, $ = g(() => m(R), [R]);
85
+ return /* @__PURE__ */ w("div", {
107
86
  className: "space-y-6 p-6",
108
87
  children: [
109
- /* @__PURE__ */ l("div", {
110
- className: "flex items-center justify-between",
111
- children: [/* @__PURE__ */ l("div", { children: [
112
- /* @__PURE__ */ c("h1", {
88
+ /* @__PURE__ */ w("div", {
89
+ className: "flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between",
90
+ children: [/* @__PURE__ */ w("div", { children: [
91
+ /* @__PURE__ */ C("h1", {
113
92
  className: "text-2xl font-semibold",
114
- children: /* @__PURE__ */ c(_, { children: "Workforce Analytics" })
93
+ children: /* @__PURE__ */ C(A, { children: "Workforce Analytics" })
115
94
  }),
116
- /* @__PURE__ */ c("p", {
95
+ /* @__PURE__ */ C("p", {
117
96
  className: "text-sm text-text-secondary",
118
97
  children: "Comprehensive analytics across all HR domains"
119
98
  }),
120
- /* @__PURE__ */ c(v, {
99
+ /* @__PURE__ */ C(M, {
121
100
  className: "mt-1",
122
- children: "Your workforce analytics hub — track headcount, performance, and engagement trends here to spot what's working and where your teams need attention."
101
+ children: "Your workforce analytics hub — track headcount, hiring conversion, performance, and utilization here to spot what's working and where your teams need attention."
123
102
  })
124
- ] }), /* @__PURE__ */ l(u, {
125
- variant: "outline",
126
- className: "flex items-center gap-1 self-start",
127
- children: [/* @__PURE__ */ c(i, { className: "h-3.5 w-3.5" }), "Rolling 6 months"]
103
+ ] }), /* @__PURE__ */ w("div", {
104
+ className: "flex flex-wrap items-center gap-2",
105
+ children: [/* @__PURE__ */ C(s, {
106
+ "aria-label": "Reporting period",
107
+ tabs: [{
108
+ id: "6",
109
+ label: "Last 6 months"
110
+ }, {
111
+ id: "12",
112
+ label: "Last 12 months"
113
+ }],
114
+ value: V,
115
+ onChange: (e) => H(e === "6" ? "6" : "12")
116
+ }), /* @__PURE__ */ w(T, {
117
+ variant: "outline",
118
+ size: "sm",
119
+ onClick: () => {
120
+ let e = ["Section,Label,Value"];
121
+ for (let t of K) e.push(`Headcount by department,${F(t.label)},${t.value}`);
122
+ for (let t of J) e.push(`Hiring funnel,${F(t.label)},${t.value}`);
123
+ for (let t of Y) e.push(`Performance distribution,${F(t.label)},${t.value}`);
124
+ Z && (e.push(`Utilization,Utilized %,${Z.utilized}`), e.push(`Utilization,Available %,${Z.available}`));
125
+ let t = new Blob([e.join("\n")], { type: "text/csv;charset=utf-8;" }), n = URL.createObjectURL(t), r = document.createElement("a");
126
+ r.href = n, r.download = "workforce-analytics.csv", r.click(), URL.revokeObjectURL(n);
127
+ },
128
+ children: [/* @__PURE__ */ C(b, { className: "mr-1 h-4 w-4" }), "Export"]
129
+ })]
128
130
  })]
129
131
  }),
130
- /* @__PURE__ */ l("div", {
131
- className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
132
+ /* @__PURE__ */ w("div", {
133
+ className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-4",
132
134
  children: [
133
- /* @__PURE__ */ l(g, {
134
- treatment: "glass",
135
- glow: !0,
136
- className: "border-border-seam",
137
- children: [/* @__PURE__ */ l(m, {
138
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
139
- children: [/* @__PURE__ */ c(h, {
140
- className: "text-sm font-medium",
141
- children: "Total Workforce"
142
- }), /* @__PURE__ */ c(s, { className: "h-4 w-4 text-text-secondary" })]
143
- }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
144
- className: "text-2xl font-bold tabular-nums",
145
- children: w.length
146
- }), /* @__PURE__ */ l("div", {
147
- className: "flex items-center text-xs text-status-success-text",
148
- children: [/* @__PURE__ */ c(o, { className: "mr-1 h-3 w-3" }), "Live headcount data"]
149
- })] })]
135
+ /* @__PURE__ */ C(o, {
136
+ label: "Total Workforce",
137
+ value: I.length,
138
+ delta: W || void 0,
139
+ deltaLabel: "from last month",
140
+ icon: /* @__PURE__ */ C(S, { className: "h-4 w-4" }),
141
+ sparkline: U.map((e) => e.value),
142
+ sparklineVariant: "area"
150
143
  }),
151
- /* @__PURE__ */ l(g, {
152
- treatment: "metric",
153
- className: "border-border-seam",
154
- children: [/* @__PURE__ */ l(m, {
155
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
156
- children: [/* @__PURE__ */ c(h, {
157
- className: "text-sm font-medium",
158
- children: "Active Departments"
159
- }), /* @__PURE__ */ c(a, { className: "h-4 w-4 text-text-secondary" })]
160
- }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
161
- className: "text-2xl font-bold tabular-nums",
162
- children: T.length
163
- }), /* @__PURE__ */ c("p", {
164
- className: "text-xs text-text-secondary",
165
- children: "All departments tracked"
166
- })] })]
144
+ /* @__PURE__ */ C(o, {
145
+ label: "Active Departments",
146
+ value: L.length,
147
+ icon: /* @__PURE__ */ C(x, { className: "h-4 w-4" })
167
148
  }),
168
- /* @__PURE__ */ l(g, {
169
- treatment: "metric",
170
- className: "border-border-seam",
171
- children: [/* @__PURE__ */ l(m, {
172
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
173
- children: [/* @__PURE__ */ c(h, {
174
- className: "text-sm font-medium",
175
- children: "Active Projects"
176
- }), /* @__PURE__ */ c(n, { className: "h-4 w-4 text-text-secondary" })]
177
- }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
178
- className: "text-2xl font-bold tabular-nums",
179
- children: O.filter((e) => e.status === "active").length
180
- }), /* @__PURE__ */ l("p", {
181
- className: "text-xs text-text-secondary",
182
- children: [O.filter((e) => e.status === "completed").length, " completed"]
183
- })] })]
149
+ /* @__PURE__ */ C(o, {
150
+ label: "Active Projects",
151
+ value: G,
152
+ icon: /* @__PURE__ */ C(v, { className: "h-4 w-4" })
184
153
  }),
185
- /* @__PURE__ */ l(g, {
186
- treatment: "metric",
187
- className: "border-border-seam",
188
- children: [/* @__PURE__ */ l(m, {
189
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
190
- children: [/* @__PURE__ */ c(h, {
191
- className: "text-sm font-medium",
192
- children: "Hiring Pipeline"
193
- }), /* @__PURE__ */ c(r, { className: "h-4 w-4 text-text-secondary" })]
194
- }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
195
- className: "text-2xl font-bold tabular-nums",
196
- children: D.length
197
- }), /* @__PURE__ */ c("p", {
198
- className: "text-xs text-text-secondary",
199
- children: "candidates in pipeline"
200
- })] })]
154
+ /* @__PURE__ */ C(o, {
155
+ label: "Hiring Pipeline",
156
+ value: R.length,
157
+ icon: /* @__PURE__ */ C(y, { className: "h-4 w-4" })
201
158
  })
202
159
  ]
203
160
  }),
204
- /* @__PURE__ */ l(b, {
205
- defaultValue: "overview",
161
+ /* @__PURE__ */ w("div", {
162
+ className: "grid gap-4 lg:grid-cols-3",
206
163
  children: [
207
- /* @__PURE__ */ l(S, { children: [
208
- /* @__PURE__ */ c(C, {
209
- value: "overview",
210
- children: "Overview"
211
- }),
212
- /* @__PURE__ */ c(C, {
213
- value: "hiring",
214
- children: "Hiring Funnel"
215
- }),
216
- /* @__PURE__ */ c(C, {
217
- value: "departments",
218
- children: "Departments"
219
- })
220
- ] }),
221
- /* @__PURE__ */ c(x, {
222
- value: "overview",
223
- className: "space-y-4",
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, {
225
- className: "space-y-3",
226
- children: k.map((e) => /* @__PURE__ */ l("div", {
227
- className: "flex items-center gap-3",
228
- children: [
229
- /* @__PURE__ */ c("span", {
230
- className: "w-10 text-sm text-text-secondary",
231
- children: e.month
232
- }),
233
- /* @__PURE__ */ c("div", {
234
- className: "h-5 flex-1 overflow-hidden rounded bg-bg-sunken",
235
- children: /* @__PURE__ */ c("div", {
236
- className: "h-5 rounded bg-action-primary-bg",
237
- style: { width: `${Math.round(e.headcount / M * 100)}%` }
238
- })
239
- }),
240
- /* @__PURE__ */ c("span", {
241
- className: "w-10 text-right text-sm font-medium",
242
- children: e.headcount
243
- }),
244
- /* @__PURE__ */ l("div", {
245
- className: "flex w-32 justify-end gap-1",
246
- children: [/* @__PURE__ */ l(u, {
247
- variant: "default",
248
- className: "text-[10px]",
249
- children: [
250
- "+",
251
- e.hires,
252
- " hired"
253
- ]
254
- }), e.exits > 0 && /* @__PURE__ */ l(u, {
255
- variant: "destructive",
256
- className: "text-[10px]",
257
- children: [
258
- "-",
259
- e.exits,
260
- " exits"
261
- ]
262
- })]
263
- })
264
- ]
265
- }, `${e.month}-${e.headcount}`))
266
- })] })
267
- }),
268
- /* @__PURE__ */ c(x, {
269
- value: "hiring",
270
- className: "space-y-4",
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, {
272
- className: "space-y-4",
273
- children: F.map((e) => /* @__PURE__ */ l("div", {
274
- className: "flex items-center gap-3",
275
- children: [
276
- /* @__PURE__ */ c("span", {
277
- className: "w-28 text-sm font-medium",
278
- children: e.stage
279
- }),
280
- /* @__PURE__ */ c("div", {
281
- className: "h-6 flex-1 overflow-hidden rounded bg-bg-sunken",
282
- children: /* @__PURE__ */ c("div", {
283
- className: `h-6 rounded ${e.color}`,
284
- style: { width: `${Math.max(Math.round(e.count / I * 100), 5)}%` }
285
- })
286
- }),
287
- /* @__PURE__ */ c("span", {
288
- className: "w-10 text-right text-sm font-bold",
289
- children: e.count
290
- })
291
- ]
292
- }, e.stage))
293
- })] })
294
- }),
295
- /* @__PURE__ */ c(x, {
296
- value: "departments",
297
- className: "space-y-4",
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
- }) })] })
303
- })
164
+ /* @__PURE__ */ w(E, { children: [/* @__PURE__ */ C(O, { children: /* @__PURE__ */ C(k, {
165
+ className: "text-base",
166
+ children: "Headcount by department"
167
+ }) }), /* @__PURE__ */ C(D, { children: K.length > 0 ? /* @__PURE__ */ C(r, {
168
+ series: K,
169
+ colorful: !0,
170
+ height: 230,
171
+ title: "Headcount by department"
172
+ }) : /* @__PURE__ */ C(j, {
173
+ illustration: "empty-data",
174
+ title: "No departments yet",
175
+ description: "Department headcount appears once departments exist."
176
+ }) })] }),
177
+ /* @__PURE__ */ w(E, { children: [/* @__PURE__ */ C(O, { children: /* @__PURE__ */ C(k, {
178
+ className: "text-base",
179
+ children: "Hiring funnel conversion"
180
+ }) }), /* @__PURE__ */ C(D, { children: q.length > 0 ? /* @__PURE__ */ C(i, {
181
+ stages: J,
182
+ valueFormatter: (e) => `${e}`,
183
+ showConversion: !0
184
+ }) : /* @__PURE__ */ C(j, {
185
+ illustration: "empty-data",
186
+ title: "No candidates yet",
187
+ description: "The hiring funnel and stage-to-stage conversion appear once candidates apply."
188
+ }) })] }),
189
+ /* @__PURE__ */ w(E, { children: [/* @__PURE__ */ C(O, { children: /* @__PURE__ */ C(k, {
190
+ className: "text-base",
191
+ children: "Performance distribution"
192
+ }) }), /* @__PURE__ */ C(D, { children: I.length > 0 ? /* @__PURE__ */ C(r, {
193
+ series: Y,
194
+ height: 230,
195
+ title: "Performance score distribution"
196
+ }) : /* @__PURE__ */ C(j, {
197
+ illustration: "empty-data",
198
+ title: "No employees yet",
199
+ description: "Performance bands appear once employees have scores."
200
+ }) })] }),
201
+ /* @__PURE__ */ w(E, { children: [/* @__PURE__ */ C(O, { children: /* @__PURE__ */ C(k, {
202
+ className: "text-base",
203
+ children: "Attrition trend"
204
+ }) }), /* @__PURE__ */ C(D, { children: X.length > 0 ? /* @__PURE__ */ C(n, {
205
+ series: X,
206
+ height: 230,
207
+ valueFormatter: (e) => `${e}`,
208
+ title: "Employee exits by month"
209
+ }) : /* @__PURE__ */ C(j, {
210
+ illustration: "empty-data",
211
+ title: "No exits recorded",
212
+ description: "Monthly attrition appears once employees have termination dates. Nothing is shown while no exits are on record — estimated exits are never charted."
213
+ }) })] }),
214
+ /* @__PURE__ */ w(E, { children: [/* @__PURE__ */ C(O, { children: /* @__PURE__ */ C(k, {
215
+ className: "text-base",
216
+ children: "Utilization"
217
+ }) }), /* @__PURE__ */ C(D, { children: Q ? /* @__PURE__ */ C(a, {
218
+ segments: Q,
219
+ centerLabel: `${Z?.utilized ?? 0}%`,
220
+ centerCaption: "Utilized",
221
+ valueFormatter: (e) => `${e}%`
222
+ }) : /* @__PURE__ */ C(j, {
223
+ illustration: "empty-data",
224
+ title: "No logged time yet",
225
+ description: "Utilization is computed from real logged hours against a 40h weekly capacity."
226
+ }) })] }),
227
+ /* @__PURE__ */ w(E, { children: [/* @__PURE__ */ C(O, { children: /* @__PURE__ */ C(k, {
228
+ className: "text-base",
229
+ children: "Time-to-hire"
230
+ }) }), /* @__PURE__ */ C(D, { children: $ ? /* @__PURE__ */ C(o, {
231
+ label: "Average time-to-hire",
232
+ value: `${$.averageDays} days`,
233
+ deltaLabel: `from ${$.sampleSize} hires`
234
+ }) : /* @__PURE__ */ C(j, {
235
+ illustration: "empty-data",
236
+ title: "No hires recorded yet",
237
+ description: "Average time-to-hire appears once candidates carry a hired date. The elapsed applied-to-hired time is measured, never estimated."
238
+ }) })] })
304
239
  ]
305
- })
240
+ }),
241
+ U.length > 1 && /* @__PURE__ */ w(E, { children: [/* @__PURE__ */ C(O, { children: /* @__PURE__ */ C(k, {
242
+ className: "text-base",
243
+ children: "Headcount growth"
244
+ }) }), /* @__PURE__ */ C(D, { children: /* @__PURE__ */ C(t, {
245
+ series: U,
246
+ height: 220,
247
+ title: "Cumulative headcount by month"
248
+ }) })] })
306
249
  ]
307
250
  });
308
251
  }
309
252
  //#endregion
310
- export { w as AnalyticsAnalyticsPagePage };
253
+ export { I as AnalyticsAnalyticsPagePage };
311
254
 
312
255
  //# sourceMappingURL=AnalyticsAnalyticsPagePage.js.map