@burdenoff/microfe-crewfoundry 2026.704.3 → 2026.704.5

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 (101) hide show
  1. package/dist/crewfoundry/pages/AdminAdminPagePage.js +76 -75
  2. package/dist/crewfoundry/pages/AdminAdminPagePage.js.map +1 -1
  3. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +118 -117
  4. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
  5. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +115 -114
  6. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
  7. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +105 -104
  8. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
  9. package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js +52 -51
  10. package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js.map +1 -1
  11. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +94 -93
  12. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
  13. package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js +97 -96
  14. package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js.map +1 -1
  15. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +68 -67
  16. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
  17. package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js +96 -95
  18. package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js.map +1 -1
  19. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +153 -152
  20. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
  21. package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +111 -110
  22. package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
  23. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +77 -76
  24. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
  25. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +80 -79
  26. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
  27. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +1 -1
  28. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
  29. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +102 -101
  30. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
  31. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +126 -125
  32. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
  33. package/dist/crewfoundry/pages/HiringJobsPagePage.js +64 -63
  34. package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
  35. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +96 -95
  36. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
  37. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +129 -127
  38. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
  39. package/dist/crewfoundry/pages/HrPayrollPagePage.js +118 -117
  40. package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
  41. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +123 -122
  42. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
  43. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +1 -1
  44. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
  45. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +1 -1
  46. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
  47. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +77 -76
  48. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
  49. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +49 -48
  50. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
  51. package/dist/crewfoundry/pages/LearningCoursesPagePage.js +62 -61
  52. package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
  53. package/dist/crewfoundry/pages/LearningLearningPagePage.js +72 -71
  54. package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
  55. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +70 -69
  56. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
  57. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +57 -56
  58. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
  59. package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +58 -57
  60. package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +1 -1
  61. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +122 -121
  62. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +1 -1
  63. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +2 -2
  64. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
  65. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +70 -69
  66. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
  67. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +41 -40
  68. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
  69. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +65 -64
  70. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
  71. package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +75 -74
  72. package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +1 -1
  73. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +4 -4
  74. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
  75. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +60 -59
  76. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
  77. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +53 -52
  78. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
  79. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js +37 -36
  80. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js.map +1 -1
  81. package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +1 -1
  82. package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
  83. package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +126 -125
  84. package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
  85. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +62 -61
  86. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
  87. package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js +50 -49
  88. package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
  89. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +72 -71
  90. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
  91. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +40 -39
  92. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
  93. package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +134 -133
  94. package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
  95. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +60 -59
  96. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
  97. package/dist/crewfoundry/store/crewfoundryStore.js +177 -146
  98. package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
  99. package/dist/crewfoundry/utils/formatEnumLabel.js +8 -0
  100. package/dist/crewfoundry/utils/formatEnumLabel.js.map +1 -0
  101. package/package.json +1 -1
@@ -1,28 +1,29 @@
1
1
  import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
- import { useMemo as t } from "react";
3
- import { Briefcase as n, Clock as r, Target as i, Users as a } from "lucide-react";
4
- import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
5
- import { Badge as l, Card as u, CardContent as d, CardDescription as f, CardHeader as p, CardTitle as m, GlassCard as h, GradientText as g, IllustratedEmptyState as _, PagePurpose as v, Pagination as y, ResponsiveTable as b } from "@burdenoff/fe-libs/ui";
6
- import { usePagination as x } from "@burdenoff/fe-libs/shared/hooks";
2
+ import { formatEnumLabel as t } from "../utils/formatEnumLabel.js";
3
+ import { useMemo as n } from "react";
4
+ import { Briefcase as r, Clock as i, Target as a, Users as o } from "lucide-react";
5
+ import { Fragment as s, jsx as c, jsxs as l } from "react/jsx-runtime";
6
+ import { Badge as u, Card as d, CardContent as f, CardDescription as p, CardHeader as m, CardTitle as h, GlassCard as g, GradientText as _, IllustratedEmptyState as v, PagePurpose as y, Pagination as b, ResponsiveTable as x } from "@burdenoff/fe-libs/ui";
7
+ import { usePagination as S } from "@burdenoff/fe-libs/shared/hooks";
7
8
  //#region src/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.tsx
8
- var S = (e) => {
9
+ var C = (e) => {
9
10
  let t = new Date(e);
10
11
  return `${t.getFullYear()}-${String(t.getMonth()).padStart(2, "0")}`;
11
- }, C = (/* @__PURE__ */ new Date("2026-03-01")).getTime();
12
- function w() {
13
- let { jobPostings: w, candidates: T, interviews: E } = e(), D = t(() => T.length === 0 && E.length === 0 ? [] : Array.from(new Set([...T.map((e) => S(e.appliedDate)), ...E.map((e) => S(e.date))])).sort().slice(-6).map((e) => {
12
+ }, w = (/* @__PURE__ */ new Date("2026-03-01")).getTime();
13
+ function T() {
14
+ let { jobPostings: T, candidates: E, interviews: D } = e(), O = n(() => E.length === 0 && D.length === 0 ? [] : Array.from(new Set([...E.map((e) => C(e.appliedDate)), ...D.map((e) => C(e.date))])).sort().slice(-6).map((e) => {
14
15
  let [t, n] = e.split("-").map(Number), r = new Date(t, n, 1).toLocaleString("en-US", {
15
16
  month: "short",
16
17
  year: "2-digit"
17
- }), i = T.filter((t) => S(t.appliedDate) === e);
18
+ }), i = E.filter((t) => C(t.appliedDate) === e);
18
19
  return {
19
20
  month: r,
20
21
  applications: i.length,
21
- interviews: E.filter((t) => S(t.date) === e).length,
22
+ interviews: D.filter((t) => C(t.date) === e).length,
22
23
  hires: i.filter((e) => e.status === "hired").length
23
24
  };
24
- }), [T, E]), O = t(() => {
25
- let e = T.reduce((e, t) => {
25
+ }), [E, D]), k = n(() => {
26
+ let e = E.reduce((e, t) => {
26
27
  let n = t.source || "Unknown", r = e[n] || {
27
28
  applications: 0,
28
29
  hires: 0
@@ -35,192 +36,192 @@ function w() {
35
36
  hires: t.hires,
36
37
  conversionRate: Number((t.hires / Math.max(t.applications, 1) * 100).toFixed(1))
37
38
  })).sort((e, t) => t.conversionRate - e.conversionRate);
38
- }, [T]), k = t(() => {
39
- let e = w.filter((e) => e.status === "active");
39
+ }, [E]), A = n(() => {
40
+ let e = T.filter((e) => e.status === "active");
40
41
  if (e.length === 0) return 0;
41
42
  let t = e.reduce((e, t) => {
42
43
  let n = new Date(t.postedDate).getTime();
43
- return Number.isNaN(n) ? e : e + Math.max(0, (C - n) / (1e3 * 60 * 60 * 24));
44
+ return Number.isNaN(n) ? e : e + Math.max(0, (w - n) / (1e3 * 60 * 60 * 24));
44
45
  }, 0);
45
46
  return Math.round(t / e.length);
46
- }, [w]), A = w.filter((e) => e.status === "active"), j = w.reduce((e, t) => e + t.applicants, 0), M = E.filter((e) => e.status === "scheduled").length, N = E.filter((e) => e.status === "completed").length, P = T.filter((e) => e.status === "offer").length, F = T.filter((e) => e.status === "hired").length, I = T.filter((e) => [
47
+ }, [T]), j = T.filter((e) => e.status === "active"), M = T.reduce((e, t) => e + t.applicants, 0), N = D.filter((e) => e.status === "scheduled").length, P = D.filter((e) => e.status === "completed").length, F = E.filter((e) => e.status === "offer").length, I = E.filter((e) => e.status === "hired").length, L = E.filter((e) => [
47
48
  "interview",
48
49
  "assessment",
49
50
  "offer",
50
51
  "hired"
51
- ].includes(e.status)).length, L = T.filter((e) => ["offer", "hired"].includes(e.status)).length, R = Math.round(L / Math.max(I, 1) * 100), z = Math.round(F / Math.max(P + F, 1) * 100), B = Math.max(1, ...D.map((e) => e.applications)), V = [
52
+ ].includes(e.status)).length, R = E.filter((e) => ["offer", "hired"].includes(e.status)).length, z = Math.round(R / Math.max(L, 1) * 100), B = Math.round(I / Math.max(F + I, 1) * 100), V = Math.max(1, ...O.map((e) => e.applications)), H = [
52
53
  {
53
54
  status: "New",
54
- count: T.filter((e) => e.status === "new").length,
55
+ count: E.filter((e) => e.status === "new").length,
55
56
  color: "bg-text-secondary"
56
57
  },
57
58
  {
58
59
  status: "Screening",
59
- count: T.filter((e) => e.status === "screening").length,
60
+ count: E.filter((e) => e.status === "screening").length,
60
61
  color: "bg-status-info-text"
61
62
  },
62
63
  {
63
64
  status: "Interview",
64
- count: T.filter((e) => e.status === "interview").length,
65
+ count: E.filter((e) => e.status === "interview").length,
65
66
  color: "bg-status-info-text"
66
67
  },
67
68
  {
68
69
  status: "Assessment",
69
- count: T.filter((e) => e.status === "assessment").length,
70
+ count: E.filter((e) => e.status === "assessment").length,
70
71
  color: "bg-action-primary-bg"
71
72
  },
72
73
  {
73
74
  status: "Offer",
74
- count: P,
75
+ count: F,
75
76
  color: "bg-status-warning-text"
76
77
  },
77
78
  {
78
79
  status: "Hired",
79
- count: F,
80
+ count: I,
80
81
  color: "bg-status-success-text"
81
82
  },
82
83
  {
83
84
  status: "Rejected",
84
- count: T.filter((e) => e.status === "rejected").length,
85
+ count: E.filter((e) => e.status === "rejected").length,
85
86
  color: "bg-status-error-text"
86
87
  }
87
- ], H = V.reduce((e, t) => e + t.count, 0), U = [...A].sort((e, t) => t.applicants - e.applicants), { page: W, pageSize: G, offset: K, setPage: q } = x({ initialPageSize: 8 }), J = U.slice(K, K + G);
88
- return /* @__PURE__ */ c("div", {
88
+ ], U = H.reduce((e, t) => e + t.count, 0), W = [...j].sort((e, t) => t.applicants - e.applicants), { page: G, pageSize: K, offset: q, setPage: J } = S({ initialPageSize: 8 }), Y = W.slice(q, q + K);
89
+ return /* @__PURE__ */ l("div", {
89
90
  className: "space-y-6 p-6",
90
91
  children: [
91
- /* @__PURE__ */ s("div", {
92
+ /* @__PURE__ */ c("div", {
92
93
  className: "flex items-center justify-between",
93
- children: /* @__PURE__ */ c("div", { children: [
94
- /* @__PURE__ */ s("h1", {
94
+ children: /* @__PURE__ */ l("div", { children: [
95
+ /* @__PURE__ */ c("h1", {
95
96
  className: "text-2xl font-semibold",
96
- children: /* @__PURE__ */ s(g, { children: "Hiring Analytics" })
97
+ children: /* @__PURE__ */ c(_, { children: "Hiring Analytics" })
97
98
  }),
98
- /* @__PURE__ */ s("p", {
99
+ /* @__PURE__ */ c("p", {
99
100
  className: "text-sm text-text-secondary",
100
101
  children: "Recruitment performance and pipeline analysis"
101
102
  }),
102
- /* @__PURE__ */ s(v, {
103
+ /* @__PURE__ */ c(y, {
103
104
  className: "mt-1",
104
105
  children: "Measure how your hiring funnel performs — applications, time-to-hire, and source quality — to make recruiting faster and more effective."
105
106
  })
106
107
  ] })
107
108
  }),
108
- /* @__PURE__ */ c("div", {
109
+ /* @__PURE__ */ l("div", {
109
110
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
110
111
  children: [
111
- /* @__PURE__ */ c(h, {
112
+ /* @__PURE__ */ l(g, {
112
113
  treatment: "glass",
113
114
  glow: !0,
114
115
  className: "border-border-seam",
115
- children: [/* @__PURE__ */ c(p, {
116
+ children: [/* @__PURE__ */ l(m, {
116
117
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
117
- children: [/* @__PURE__ */ s(m, {
118
+ children: [/* @__PURE__ */ c(h, {
118
119
  className: "text-sm font-medium",
119
120
  children: "Active Postings"
120
- }), /* @__PURE__ */ s(n, { className: "h-4 w-4 text-text-secondary" })]
121
- }), /* @__PURE__ */ c(d, { children: [/* @__PURE__ */ s("div", {
121
+ }), /* @__PURE__ */ c(r, { className: "h-4 w-4 text-text-secondary" })]
122
+ }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
122
123
  className: "text-2xl font-bold tabular-nums",
123
- children: A.length
124
- }), /* @__PURE__ */ c("p", {
124
+ children: j.length
125
+ }), /* @__PURE__ */ l("p", {
125
126
  className: "text-xs text-text-secondary",
126
- children: [j, " total applicants"]
127
+ children: [M, " total applicants"]
127
128
  })] })]
128
129
  }),
129
- /* @__PURE__ */ c(h, {
130
+ /* @__PURE__ */ l(g, {
130
131
  treatment: "metric",
131
132
  className: "border-border-seam",
132
- children: [/* @__PURE__ */ c(p, {
133
+ children: [/* @__PURE__ */ l(m, {
133
134
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
134
- children: [/* @__PURE__ */ s(m, {
135
+ children: [/* @__PURE__ */ c(h, {
135
136
  className: "text-sm font-medium",
136
137
  children: "Avg Days Open"
137
- }), /* @__PURE__ */ s(r, { className: "h-4 w-4 text-text-secondary" })]
138
- }), /* @__PURE__ */ c(d, { children: [/* @__PURE__ */ c("div", {
138
+ }), /* @__PURE__ */ c(i, { className: "h-4 w-4 text-text-secondary" })]
139
+ }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ l("div", {
139
140
  className: "text-2xl font-bold tabular-nums",
140
- children: [k, " days"]
141
- }), /* @__PURE__ */ s("p", {
141
+ children: [A, " days"]
142
+ }), /* @__PURE__ */ c("p", {
142
143
  className: "text-xs text-text-secondary",
143
144
  children: "Across active postings"
144
145
  })] })]
145
146
  }),
146
- /* @__PURE__ */ c(h, {
147
+ /* @__PURE__ */ l(g, {
147
148
  treatment: "metric",
148
149
  className: "border-border-seam",
149
- children: [/* @__PURE__ */ c(p, {
150
+ children: [/* @__PURE__ */ l(m, {
150
151
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
151
- children: [/* @__PURE__ */ s(m, {
152
+ children: [/* @__PURE__ */ c(h, {
152
153
  className: "text-sm font-medium",
153
154
  children: "Interview to Offer"
154
- }), /* @__PURE__ */ s(i, { className: "h-4 w-4 text-text-secondary" })]
155
- }), /* @__PURE__ */ c(d, { children: [/* @__PURE__ */ c("div", {
155
+ }), /* @__PURE__ */ c(a, { className: "h-4 w-4 text-text-secondary" })]
156
+ }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ l("div", {
156
157
  className: "text-2xl font-bold tabular-nums",
157
- children: [R, "%"]
158
- }), /* @__PURE__ */ c("p", {
158
+ children: [z, "%"]
159
+ }), /* @__PURE__ */ l("p", {
159
160
  className: "text-xs text-text-secondary",
160
161
  children: [
161
- M,
162
- " scheduled, ",
163
162
  N,
163
+ " scheduled, ",
164
+ P,
164
165
  " completed"
165
166
  ]
166
167
  })] })]
167
168
  }),
168
- /* @__PURE__ */ c(h, {
169
+ /* @__PURE__ */ l(g, {
169
170
  treatment: "metric",
170
171
  className: "border-border-seam",
171
- children: [/* @__PURE__ */ c(p, {
172
+ children: [/* @__PURE__ */ l(m, {
172
173
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
173
- children: [/* @__PURE__ */ s(m, {
174
+ children: [/* @__PURE__ */ c(h, {
174
175
  className: "text-sm font-medium",
175
176
  children: "Offer Acceptance"
176
- }), /* @__PURE__ */ s(a, { className: "h-4 w-4 text-text-secondary" })]
177
- }), /* @__PURE__ */ c(d, { children: [/* @__PURE__ */ c("div", {
177
+ }), /* @__PURE__ */ c(o, { className: "h-4 w-4 text-text-secondary" })]
178
+ }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ l("div", {
178
179
  className: "text-2xl font-bold tabular-nums",
179
- children: [z, "%"]
180
- }), /* @__PURE__ */ c("p", {
180
+ children: [B, "%"]
181
+ }), /* @__PURE__ */ l("p", {
181
182
  className: "text-xs text-text-secondary",
182
- children: [F, " hired to date"]
183
+ children: [I, " hired to date"]
183
184
  })] })]
184
185
  })
185
186
  ]
186
187
  }),
187
- /* @__PURE__ */ c("div", {
188
+ /* @__PURE__ */ l("div", {
188
189
  className: "grid gap-4 md:grid-cols-7",
189
- children: [/* @__PURE__ */ c(u, {
190
+ children: [/* @__PURE__ */ l(d, {
190
191
  className: "col-span-4",
191
- children: [/* @__PURE__ */ c(p, { children: [/* @__PURE__ */ s(m, { children: "Monthly Hiring Activity" }), /* @__PURE__ */ s(f, { children: "Applications, interviews, and hires over time" })] }), /* @__PURE__ */ c(d, {
192
+ children: [/* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c(h, { children: "Monthly Hiring Activity" }), /* @__PURE__ */ c(p, { children: "Applications, interviews, and hires over time" })] }), /* @__PURE__ */ l(f, {
192
193
  className: "space-y-3",
193
- children: [D.length === 0 && /* @__PURE__ */ s("p", {
194
+ children: [O.length === 0 && /* @__PURE__ */ c("p", {
194
195
  className: "py-6 text-center text-sm text-text-secondary",
195
196
  children: "No hiring activity recorded yet."
196
- }), D.map((e) => /* @__PURE__ */ c("div", {
197
+ }), O.map((e) => /* @__PURE__ */ l("div", {
197
198
  className: "flex items-center gap-3",
198
199
  children: [
199
- /* @__PURE__ */ s("span", {
200
+ /* @__PURE__ */ c("span", {
200
201
  className: "w-12 text-sm text-text-secondary",
201
202
  children: e.month
202
203
  }),
203
- /* @__PURE__ */ s("div", {
204
+ /* @__PURE__ */ c("div", {
204
205
  className: "flex-1 h-5 bg-bg-sunken rounded overflow-hidden",
205
- children: /* @__PURE__ */ s("div", {
206
+ children: /* @__PURE__ */ c("div", {
206
207
  className: "h-5 bg-action-primary-bg rounded",
207
- style: { width: `${Math.round(e.applications / B * 100)}%` }
208
+ style: { width: `${Math.round(e.applications / V * 100)}%` }
208
209
  })
209
210
  }),
210
- /* @__PURE__ */ c("div", {
211
+ /* @__PURE__ */ l("div", {
211
212
  className: "flex gap-1 w-48 justify-end",
212
213
  children: [
213
- /* @__PURE__ */ c(l, {
214
+ /* @__PURE__ */ l(u, {
214
215
  variant: "outline",
215
216
  className: "text-[10px]",
216
217
  children: [e.applications, " apps"]
217
218
  }),
218
- /* @__PURE__ */ c(l, {
219
+ /* @__PURE__ */ l(u, {
219
220
  variant: "secondary",
220
221
  className: "text-[10px]",
221
222
  children: [e.interviews, " int"]
222
223
  }),
223
- /* @__PURE__ */ c(l, {
224
+ /* @__PURE__ */ l(u, {
224
225
  variant: "default",
225
226
  className: "text-[10px]",
226
227
  children: [e.hires, " hired"]
@@ -230,26 +231,26 @@ function w() {
230
231
  ]
231
232
  }, e.month))]
232
233
  })]
233
- }), /* @__PURE__ */ c(u, {
234
+ }), /* @__PURE__ */ l(d, {
234
235
  className: "col-span-3",
235
- children: [/* @__PURE__ */ c(p, { children: [/* @__PURE__ */ s(m, { children: "Pipeline Status" }), /* @__PURE__ */ s(f, { children: "Current candidate distribution" })] }), /* @__PURE__ */ s(d, {
236
+ children: [/* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c(h, { children: "Pipeline Status" }), /* @__PURE__ */ c(p, { children: "Current candidate distribution" })] }), /* @__PURE__ */ c(f, {
236
237
  className: "space-y-3",
237
- children: V.map((e) => /* @__PURE__ */ c("div", {
238
+ children: H.map((e) => /* @__PURE__ */ l("div", {
238
239
  className: "flex items-center gap-3",
239
240
  children: [
240
- /* @__PURE__ */ s("div", { className: `h-3 w-3 rounded-full ${e.color}` }),
241
- /* @__PURE__ */ s("span", {
241
+ /* @__PURE__ */ c("div", { className: `h-3 w-3 rounded-full ${e.color}` }),
242
+ /* @__PURE__ */ c("span", {
242
243
  className: "w-20 text-sm",
243
- children: e.status
244
+ children: t(e.status)
244
245
  }),
245
- /* @__PURE__ */ s("div", {
246
+ /* @__PURE__ */ c("div", {
246
247
  className: "flex-1 h-3 bg-bg-sunken rounded overflow-hidden",
247
- children: /* @__PURE__ */ s("div", {
248
+ children: /* @__PURE__ */ c("div", {
248
249
  className: `h-3 rounded ${e.color}`,
249
- style: { width: `${H > 0 ? Math.max(Math.round(e.count / H * 100), 3) : 3}%` }
250
+ style: { width: `${U > 0 ? Math.max(Math.round(e.count / U * 100), 3) : 3}%` }
250
251
  })
251
252
  }),
252
- /* @__PURE__ */ s("span", {
253
+ /* @__PURE__ */ c("span", {
253
254
  className: "text-sm font-medium w-6 text-right",
254
255
  children: e.count
255
256
  })
@@ -258,13 +259,13 @@ function w() {
258
259
  })]
259
260
  })]
260
261
  }),
261
- /* @__PURE__ */ c(u, { children: [/* @__PURE__ */ c(p, { children: [/* @__PURE__ */ s(m, { children: "Source Effectiveness" }), /* @__PURE__ */ s(f, { children: "Recruitment channel performance comparison" })] }), /* @__PURE__ */ s(d, { children: /* @__PURE__ */ s(b, {
262
+ /* @__PURE__ */ l(d, { children: [/* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c(h, { children: "Source Effectiveness" }), /* @__PURE__ */ c(p, { children: "Recruitment channel performance comparison" })] }), /* @__PURE__ */ c(f, { children: /* @__PURE__ */ c(x, {
262
263
  columns: [
263
264
  {
264
265
  key: "source",
265
266
  header: "Source",
266
267
  priority: "primary",
267
- cell: (e) => /* @__PURE__ */ s("span", {
268
+ cell: (e) => /* @__PURE__ */ c("span", {
268
269
  className: "font-medium",
269
270
  children: e.source
270
271
  })
@@ -273,7 +274,7 @@ function w() {
273
274
  key: "applications",
274
275
  header: "Applications",
275
276
  priority: "secondary",
276
- cell: (e) => /* @__PURE__ */ s("span", {
277
+ cell: (e) => /* @__PURE__ */ c("span", {
277
278
  className: "md:block md:text-right",
278
279
  children: e.applications
279
280
  })
@@ -282,7 +283,7 @@ function w() {
282
283
  key: "hires",
283
284
  header: "Hires",
284
285
  priority: "secondary",
285
- cell: (e) => /* @__PURE__ */ s("span", {
286
+ cell: (e) => /* @__PURE__ */ c("span", {
286
287
  className: "md:block md:text-right",
287
288
  children: e.hires
288
289
  })
@@ -291,9 +292,9 @@ function w() {
291
292
  key: "conversion",
292
293
  header: "Conversion",
293
294
  priority: "primary",
294
- cell: (e) => /* @__PURE__ */ s("span", {
295
+ cell: (e) => /* @__PURE__ */ c("span", {
295
296
  className: "md:block md:text-right",
296
- children: /* @__PURE__ */ c(l, {
297
+ children: /* @__PURE__ */ l(u, {
297
298
  variant: e.conversionRate >= 5 ? "default" : "secondary",
298
299
  className: "text-[10px]",
299
300
  children: [e.conversionRate, "%"]
@@ -301,24 +302,24 @@ function w() {
301
302
  })
302
303
  }
303
304
  ],
304
- data: O,
305
+ data: k,
305
306
  rowKey: (e) => e.source,
306
- emptyState: /* @__PURE__ */ s("p", {
307
+ emptyState: /* @__PURE__ */ c("p", {
307
308
  className: "py-6 text-center text-sm text-text-secondary",
308
309
  children: "No candidate source data yet."
309
310
  })
310
311
  }) })] }),
311
- /* @__PURE__ */ c(u, { children: [/* @__PURE__ */ c(p, { children: [/* @__PURE__ */ s(m, { children: "Open Positions Detail" }), /* @__PURE__ */ s(f, { children: "Active job postings and applicant counts" })] }), /* @__PURE__ */ s(d, { children: U.length === 0 ? /* @__PURE__ */ s(_, {
312
+ /* @__PURE__ */ l(d, { children: [/* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c(h, { children: "Open Positions Detail" }), /* @__PURE__ */ c(p, { children: "Active job postings and applicant counts" })] }), /* @__PURE__ */ c(f, { children: W.length === 0 ? /* @__PURE__ */ c(v, {
312
313
  illustration: "empty-data",
313
314
  title: "No open positions",
314
315
  description: "Active job postings will appear here once you publish a role."
315
- }) : /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ s(b, {
316
+ }) : /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ c(x, {
316
317
  columns: [
317
318
  {
318
319
  key: "title",
319
320
  header: "Position",
320
321
  priority: "primary",
321
- cell: (e) => /* @__PURE__ */ s("span", {
322
+ cell: (e) => /* @__PURE__ */ c("span", {
322
323
  className: "font-medium",
323
324
  children: e.title
324
325
  })
@@ -327,7 +328,7 @@ function w() {
327
328
  key: "department",
328
329
  header: "Department",
329
330
  priority: "secondary",
330
- cell: (e) => /* @__PURE__ */ s("span", {
331
+ cell: (e) => /* @__PURE__ */ c("span", {
331
332
  className: "text-text-secondary",
332
333
  children: e.department
333
334
  })
@@ -336,17 +337,17 @@ function w() {
336
337
  key: "level",
337
338
  header: "Level",
338
339
  priority: "hidden-on-mobile",
339
- cell: (e) => /* @__PURE__ */ s(l, {
340
+ cell: (e) => /* @__PURE__ */ c(u, {
340
341
  variant: "outline",
341
342
  className: "w-fit text-[10px]",
342
- children: e.experienceLevel
343
+ children: t(e.experienceLevel)
343
344
  })
344
345
  },
345
346
  {
346
347
  key: "applicants",
347
348
  header: "Applicants",
348
349
  priority: "secondary",
349
- cell: (e) => /* @__PURE__ */ s("span", {
350
+ cell: (e) => /* @__PURE__ */ c("span", {
350
351
  className: "md:block md:text-right",
351
352
  children: e.applicants
352
353
  })
@@ -355,7 +356,7 @@ function w() {
355
356
  key: "salary",
356
357
  header: "Salary Range",
357
358
  priority: "secondary",
358
- cell: (e) => /* @__PURE__ */ c("span", {
359
+ cell: (e) => /* @__PURE__ */ l("span", {
359
360
  className: "md:block md:text-right text-text-secondary",
360
361
  children: [
361
362
  "$",
@@ -370,26 +371,26 @@ function w() {
370
371
  key: "status",
371
372
  header: "Status",
372
373
  priority: "primary",
373
- cell: (e) => /* @__PURE__ */ s(l, {
374
+ cell: (e) => /* @__PURE__ */ c(u, {
374
375
  variant: "default",
375
376
  className: "text-[10px]",
376
- children: e.status
377
+ children: t(e.status)
377
378
  })
378
379
  }
379
380
  ],
380
- data: J,
381
+ data: Y,
381
382
  rowKey: (e) => e.id
382
- }), U.length > G && /* @__PURE__ */ s(y, {
383
- page: W,
384
- pageSize: G,
385
- totalItems: U.length,
386
- onPageChange: q,
383
+ }), W.length > K && /* @__PURE__ */ c(b, {
384
+ page: G,
385
+ pageSize: K,
386
+ totalItems: W.length,
387
+ onPageChange: J,
387
388
  className: "mt-3"
388
389
  })] }) })] })
389
390
  ]
390
391
  });
391
392
  }
392
393
  //#endregion
393
- export { w as AnalyticsHiringAnalyticsPagePage };
394
+ export { T as AnalyticsHiringAnalyticsPagePage };
394
395
 
395
396
  //# sourceMappingURL=AnalyticsHiringAnalyticsPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsHiringAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n Pagination,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\nimport { Briefcase, Clock, Target, Users } from 'lucide-react';\nimport { useMemo } from 'react';\nimport { useCrewFoundryStore, type JobPosting } from '../store/crewfoundryStore';\n\ntype SourceRow = {\n source: string;\n applications: number;\n hires: number;\n conversionRate: number;\n};\n\nconst monthKeyOf = (value: string) => {\n const date = new Date(value);\n return `${date.getFullYear()}-${String(date.getMonth()).padStart(2, '0')}`;\n};\n\n// Stable \"as of\" anchor for this dataset (avoids impure Date.now() in render).\nconst AS_OF = new Date('2026-03-01').getTime();\n\nexport function AnalyticsHiringAnalyticsPagePage() {\n const { jobPostings, candidates, interviews } = useCrewFoundryStore();\n\n // Real monthly activity derived from candidate/interview dates.\n const hiringMetrics = useMemo(() => {\n if (candidates.length === 0 && interviews.length === 0) {\n return [];\n }\n const keys = Array.from(\n new Set([\n ...candidates.map((candidate) => monthKeyOf(candidate.appliedDate)),\n ...interviews.map((interview) => monthKeyOf(interview.date)),\n ])\n )\n .sort()\n .slice(-6);\n return keys.map((key) => {\n const [year, month] = key.split('-').map(Number);\n const label = new Date(year, month, 1).toLocaleString('en-US', {\n month: 'short',\n year: '2-digit',\n });\n const monthCandidates = candidates.filter(\n (candidate) => monthKeyOf(candidate.appliedDate) === key\n );\n return {\n month: label,\n applications: monthCandidates.length,\n interviews: interviews.filter((interview) => monthKeyOf(interview.date) === key).length,\n hires: monthCandidates.filter((candidate) => candidate.status === 'hired').length,\n };\n });\n }, [candidates, interviews]);\n\n const sourceEffectiveness = useMemo<SourceRow[]>(() => {\n const grouped = candidates.reduce<Record<string, { applications: number; hires: number }>>(\n (acc, candidate) => {\n const source = candidate.source || 'Unknown';\n const value = acc[source] || { applications: 0, hires: 0 };\n value.applications += 1;\n if (candidate.status === 'hired') {\n value.hires += 1;\n }\n acc[source] = value;\n return acc;\n },\n {}\n );\n\n return Object.entries(grouped)\n .map(([source, value]) => ({\n source,\n applications: value.applications,\n hires: value.hires,\n conversionRate: Number(((value.hires / Math.max(value.applications, 1)) * 100).toFixed(1)),\n }))\n .sort((a, b) => b.conversionRate - a.conversionRate);\n }, [candidates]);\n\n // Real average number of days active postings have been open.\n const avgDaysOpen = useMemo(() => {\n const activePostings = jobPostings.filter((posting) => posting.status === 'active');\n if (activePostings.length === 0) {\n return 0;\n }\n const totalDays = activePostings.reduce((sum, posting) => {\n const posted = new Date(posting.postedDate).getTime();\n if (Number.isNaN(posted)) {\n return sum;\n }\n return sum + Math.max(0, (AS_OF - posted) / (1000 * 60 * 60 * 24));\n }, 0);\n return Math.round(totalDays / activePostings.length);\n }, [jobPostings]);\n\n const activeJobs = jobPostings.filter((j) => j.status === 'active');\n const totalApplicants = jobPostings.reduce((s, j) => s + j.applicants, 0);\n const scheduledInterviews = interviews.filter((i) => i.status === 'scheduled').length;\n const completedInterviews = interviews.filter((i) => i.status === 'completed').length;\n const offeredCandidates = candidates.filter((c) => c.status === 'offer').length;\n const hiredCandidates = candidates.filter((c) => c.status === 'hired').length;\n\n const interviewedOrBeyond = candidates.filter((c) =>\n ['interview', 'assessment', 'offer', 'hired'].includes(c.status)\n ).length;\n const offerOrBeyond = candidates.filter((c) => ['offer', 'hired'].includes(c.status)).length;\n const interviewToOffer = Math.round((offerOrBeyond / Math.max(interviewedOrBeyond, 1)) * 100);\n const offerAcceptance = Math.round(\n (hiredCandidates / Math.max(offeredCandidates + hiredCandidates, 1)) * 100\n );\n\n const maxApplications = Math.max(1, ...hiringMetrics.map((m) => m.applications));\n\n const statusPipeline = [\n {\n status: 'New',\n count: candidates.filter((c) => c.status === 'new').length,\n color: 'bg-text-secondary',\n },\n {\n status: 'Screening',\n count: candidates.filter((c) => c.status === 'screening').length,\n color: 'bg-status-info-text',\n },\n {\n status: 'Interview',\n count: candidates.filter((c) => c.status === 'interview').length,\n color: 'bg-status-info-text',\n },\n {\n status: 'Assessment',\n count: candidates.filter((c) => c.status === 'assessment').length,\n color: 'bg-action-primary-bg',\n },\n { status: 'Offer', count: offeredCandidates, color: 'bg-status-warning-text' },\n { status: 'Hired', count: hiredCandidates, color: 'bg-status-success-text' },\n {\n status: 'Rejected',\n count: candidates.filter((c) => c.status === 'rejected').length,\n color: 'bg-status-error-text',\n },\n ];\n const totalPipeline = statusPipeline.reduce((s, p) => s + p.count, 0);\n\n // Open Positions = active postings only, paginated to match the card title.\n const openPositions = [...activeJobs].sort((a, b) => b.applicants - a.applicants);\n const {\n page: jobPage,\n pageSize: jobPageSize,\n offset: jobOffset,\n setPage: setJobPage,\n } = usePagination({ initialPageSize: 8 });\n const jobPageItems = openPositions.slice(jobOffset, jobOffset + jobPageSize);\n\n const sourceColumns: ResponsiveTableColumn<SourceRow>[] = [\n {\n key: 'source',\n header: 'Source',\n priority: 'primary',\n cell: (src) => <span className=\"font-medium\">{src.source}</span>,\n },\n {\n key: 'applications',\n header: 'Applications',\n priority: 'secondary',\n cell: (src) => <span className=\"md:block md:text-right\">{src.applications}</span>,\n },\n {\n key: 'hires',\n header: 'Hires',\n priority: 'secondary',\n cell: (src) => <span className=\"md:block md:text-right\">{src.hires}</span>,\n },\n {\n key: 'conversion',\n header: 'Conversion',\n priority: 'primary',\n cell: (src) => (\n <span className=\"md:block md:text-right\">\n <Badge\n variant={src.conversionRate >= 5 ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {src.conversionRate}%\n </Badge>\n </span>\n ),\n },\n ];\n\n const jobColumns: ResponsiveTableColumn<JobPosting>[] = [\n {\n key: 'title',\n header: 'Position',\n priority: 'primary',\n cell: (job) => <span className=\"font-medium\">{job.title}</span>,\n },\n {\n key: 'department',\n header: 'Department',\n priority: 'secondary',\n cell: (job) => <span className=\"text-text-secondary\">{job.department}</span>,\n },\n {\n key: 'level',\n header: 'Level',\n priority: 'hidden-on-mobile',\n cell: (job) => (\n <Badge variant=\"outline\" className=\"w-fit text-[10px]\">\n {job.experienceLevel}\n </Badge>\n ),\n },\n {\n key: 'applicants',\n header: 'Applicants',\n priority: 'secondary',\n cell: (job) => <span className=\"md:block md:text-right\">{job.applicants}</span>,\n },\n {\n key: 'salary',\n header: 'Salary Range',\n priority: 'secondary',\n cell: (job) => (\n <span className=\"md:block md:text-right text-text-secondary\">\n ${(job.salaryMin / 1000).toFixed(0)}K-${(job.salaryMax / 1000).toFixed(0)}K\n </span>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n priority: 'primary',\n cell: (job) => (\n <Badge variant=\"default\" className=\"text-[10px]\">\n {job.status}\n </Badge>\n ),\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>Hiring Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Recruitment performance and pipeline analysis\n </p>\n <PagePurpose className=\"mt-1\">\n Measure how your hiring funnel performs — applications, time-to-hire, and source quality\n — to make recruiting faster and more effective.\n </PagePurpose>\n </div>\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\">Active Postings</CardTitle>\n <Briefcase className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activeJobs.length}</div>\n <p className=\"text-xs text-text-secondary\">{totalApplicants} total applicants</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\">Avg Days Open</CardTitle>\n <Clock className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{avgDaysOpen} days</div>\n <p className=\"text-xs text-text-secondary\">Across active postings</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\">Interview to Offer</CardTitle>\n <Target className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{interviewToOffer}%</div>\n <p className=\"text-xs text-text-secondary\">\n {scheduledInterviews} scheduled, {completedInterviews} 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\">Offer Acceptance</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{offerAcceptance}%</div>\n <p className=\"text-xs text-text-secondary\">{hiredCandidates} hired to date</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-7\">\n <Card className=\"col-span-4\">\n <CardHeader>\n <CardTitle>Monthly Hiring Activity</CardTitle>\n <CardDescription>Applications, interviews, and hires over time</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {hiringMetrics.length === 0 && (\n <p className=\"py-6 text-center text-sm text-text-secondary\">\n No hiring activity recorded yet.\n </p>\n )}\n {hiringMetrics.map((m) => (\n <div key={m.month} className=\"flex items-center gap-3\">\n <span className=\"w-12 text-sm text-text-secondary\">{m.month}</span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-5 bg-action-primary-bg rounded\"\n style={{\n width: `${Math.round((m.applications / maxApplications) * 100)}%`,\n }}\n />\n </div>\n <div className=\"flex gap-1 w-48 justify-end\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {m.applications} apps\n </Badge>\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n {m.interviews} int\n </Badge>\n <Badge variant=\"default\" className=\"text-[10px]\">\n {m.hires} hired\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card className=\"col-span-3\">\n <CardHeader>\n <CardTitle>Pipeline Status</CardTitle>\n <CardDescription>Current candidate distribution</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {statusPipeline.map((stage) => (\n <div key={stage.status} className=\"flex items-center gap-3\">\n <div className={`h-3 w-3 rounded-full ${stage.color}`} />\n <span className=\"w-20 text-sm\">{stage.status}</span>\n <div className=\"flex-1 h-3 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-3 rounded ${stage.color}`}\n style={{\n width: `${totalPipeline > 0 ? Math.max(Math.round((stage.count / totalPipeline) * 100), 3) : 3}%`,\n }}\n />\n </div>\n <span className=\"text-sm font-medium w-6 text-right\">{stage.count}</span>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Source Effectiveness</CardTitle>\n <CardDescription>Recruitment channel performance comparison</CardDescription>\n </CardHeader>\n <CardContent>\n <ResponsiveTable\n columns={sourceColumns}\n data={sourceEffectiveness}\n rowKey={(src) => src.source}\n emptyState={\n <p className=\"py-6 text-center text-sm text-text-secondary\">\n No candidate source data yet.\n </p>\n }\n />\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Open Positions Detail</CardTitle>\n <CardDescription>Active job postings and applicant counts</CardDescription>\n </CardHeader>\n <CardContent>\n {openPositions.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No open positions\"\n description=\"Active job postings will appear here once you publish a role.\"\n />\n ) : (\n <>\n <ResponsiveTable columns={jobColumns} data={jobPageItems} rowKey={(job) => job.id} />\n {openPositions.length > jobPageSize && (\n <Pagination\n page={jobPage}\n pageSize={jobPageSize}\n totalItems={openPositions.length}\n onPageChange={setJobPage}\n className=\"mt-3\"\n />\n )}\n </>\n )}\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":";;;;;;;AA2BA,IAAM,KAAc,MAAkB;CACpC,IAAM,IAAO,IAAI,KAAK,EAAM;AAC5B,QAAO,GAAG,EAAK,aAAa,CAAC,GAAG,OAAO,EAAK,UAAU,CAAC,CAAC,SAAS,GAAG,IAAI;GAIpE,qBAAQ,IAAI,KAAK,aAAa,EAAC,SAAS;AAE9C,SAAgB,IAAmC;CACjD,IAAM,EAAE,gBAAa,eAAY,kBAAe,GAAqB,EAG/D,IAAgB,QAChB,EAAW,WAAW,KAAK,EAAW,WAAW,IAC5C,EAAE,GAEE,MAAM,KACjB,IAAI,IAAI,CACN,GAAG,EAAW,KAAK,MAAc,EAAW,EAAU,YAAY,CAAC,EACnE,GAAG,EAAW,KAAK,MAAc,EAAW,EAAU,KAAK,CAAC,CAC7D,CAAC,CACH,CACE,MAAM,CACN,MAAM,GAAG,CACA,KAAK,MAAQ;EACvB,IAAM,CAAC,GAAM,KAAS,EAAI,MAAM,IAAI,CAAC,IAAI,OAAO,EAC1C,IAAQ,IAAI,KAAK,GAAM,GAAO,EAAE,CAAC,eAAe,SAAS;GAC7D,OAAO;GACP,MAAM;GACP,CAAC,EACI,IAAkB,EAAW,QAChC,MAAc,EAAW,EAAU,YAAY,KAAK,EACtD;AACD,SAAO;GACL,OAAO;GACP,cAAc,EAAgB;GAC9B,YAAY,EAAW,QAAQ,MAAc,EAAW,EAAU,KAAK,KAAK,EAAI,CAAC;GACjF,OAAO,EAAgB,QAAQ,MAAc,EAAU,WAAW,QAAQ,CAAC;GAC5E;GACD,EACD,CAAC,GAAY,EAAW,CAAC,EAEtB,IAAsB,QAA2B;EACrD,IAAM,IAAU,EAAW,QACxB,GAAK,MAAc;GAClB,IAAM,IAAS,EAAU,UAAU,WAC7B,IAAQ,EAAI,MAAW;IAAE,cAAc;IAAG,OAAO;IAAG;AAM1D,UALA,EAAM,gBAAgB,GAClB,EAAU,WAAW,YACvB,EAAM,SAAS,IAEjB,EAAI,KAAU,GACP;KAET,EAAE,CACH;AAED,SAAO,OAAO,QAAQ,EAAQ,CAC3B,KAAK,CAAC,GAAQ,QAAY;GACzB;GACA,cAAc,EAAM;GACpB,OAAO,EAAM;GACb,gBAAgB,QAAS,EAAM,QAAQ,KAAK,IAAI,EAAM,cAAc,EAAE,GAAI,KAAK,QAAQ,EAAE,CAAC;GAC3F,EAAE,CACF,MAAM,GAAG,MAAM,EAAE,iBAAiB,EAAE,eAAe;IACrD,CAAC,EAAW,CAAC,EAGV,IAAc,QAAc;EAChC,IAAM,IAAiB,EAAY,QAAQ,MAAY,EAAQ,WAAW,SAAS;AACnF,MAAI,EAAe,WAAW,EAC5B,QAAO;EAET,IAAM,IAAY,EAAe,QAAQ,GAAK,MAAY;GACxD,IAAM,IAAS,IAAI,KAAK,EAAQ,WAAW,CAAC,SAAS;AAIrD,UAHI,OAAO,MAAM,EAAO,GACf,IAEF,IAAM,KAAK,IAAI,IAAI,IAAQ,MAAW,MAAO,KAAK,KAAK,IAAI;KACjE,EAAE;AACL,SAAO,KAAK,MAAM,IAAY,EAAe,OAAO;IACnD,CAAC,EAAY,CAAC,EAEX,IAAa,EAAY,QAAQ,MAAM,EAAE,WAAW,SAAS,EAC7D,IAAkB,EAAY,QAAQ,GAAG,MAAM,IAAI,EAAE,YAAY,EAAE,EACnE,IAAsB,EAAW,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC,QACzE,IAAsB,EAAW,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC,QACzE,IAAoB,EAAW,QAAQ,MAAM,EAAE,WAAW,QAAQ,CAAC,QACnE,IAAkB,EAAW,QAAQ,MAAM,EAAE,WAAW,QAAQ,CAAC,QAEjE,IAAsB,EAAW,QAAQ,MAC7C;EAAC;EAAa;EAAc;EAAS;EAAQ,CAAC,SAAS,EAAE,OAAO,CACjE,CAAC,QACI,IAAgB,EAAW,QAAQ,MAAM,CAAC,SAAS,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,QAChF,IAAmB,KAAK,MAAO,IAAgB,KAAK,IAAI,GAAqB,EAAE,GAAI,IAAI,EACvF,IAAkB,KAAK,MAC1B,IAAkB,KAAK,IAAI,IAAoB,GAAiB,EAAE,GAAI,IACxE,EAEK,IAAkB,KAAK,IAAI,GAAG,GAAG,EAAc,KAAK,MAAM,EAAE,aAAa,CAAC,EAE1E,IAAiB;EACrB;GACE,QAAQ;GACR,OAAO,EAAW,QAAQ,MAAM,EAAE,WAAW,MAAM,CAAC;GACpD,OAAO;GACR;EACD;GACE,QAAQ;GACR,OAAO,EAAW,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC;GAC1D,OAAO;GACR;EACD;GACE,QAAQ;GACR,OAAO,EAAW,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC;GAC1D,OAAO;GACR;EACD;GACE,QAAQ;GACR,OAAO,EAAW,QAAQ,MAAM,EAAE,WAAW,aAAa,CAAC;GAC3D,OAAO;GACR;EACD;GAAE,QAAQ;GAAS,OAAO;GAAmB,OAAO;GAA0B;EAC9E;GAAE,QAAQ;GAAS,OAAO;GAAiB,OAAO;GAA0B;EAC5E;GACE,QAAQ;GACR,OAAO,EAAW,QAAQ,MAAM,EAAE,WAAW,WAAW,CAAC;GACzD,OAAO;GACR;EACF,EACK,IAAgB,EAAe,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,EAAE,EAG/D,IAAgB,CAAC,GAAG,EAAW,CAAC,MAAM,GAAG,MAAM,EAAE,aAAa,EAAE,WAAW,EAC3E,EACJ,MAAM,GACN,UAAU,GACV,QAAQ,GACR,SAAS,MACP,EAAc,EAAE,iBAAiB,GAAG,CAAC,EACnC,IAAe,EAAc,MAAM,GAAW,IAAY,EAAY;AAyF5E,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD,EAAA,UAAA;KACE,kBAAC,MAAD;MAAI,WAAU;gBACZ,kBAAC,GAAD,EAAA,UAAc,oBAA+B,CAAA;MAC1C,CAAA;KACL,kBAAC,KAAD;MAAG,WAAU;gBAA8B;MAEvC,CAAA;KACJ,kBAAC,GAAD;MAAa,WAAU;gBAAO;MAGhB,CAAA;KACV,EAAA,CAAA;IACF,CAAA;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MAAW,WAAU;MAAQ,MAAA;MAAK,WAAU;gBAA5C,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAAsB;QAA2B,CAAA,EACtE,kBAAC,GAAD,EAAW,WAAU,+BAAgC,CAAA,CAC1C;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAmC,EAAW;OAAa,CAAA,EAC1E,kBAAC,KAAD;OAAG,WAAU;iBAAb,CAA4C,GAAgB,oBAAqB;SACrE,EAAA,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAAsB;QAAyB,CAAA,EACpE,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,CACtC;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CAAkD,GAAY,QAAW;UACzE,kBAAC,KAAD;OAAG,WAAU;iBAA8B;OAA0B,CAAA,CACzD,EAAA,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAAsB;QAA8B,CAAA,EACzE,kBAAC,GAAD,EAAQ,WAAU,+BAAgC,CAAA,CACvC;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CAAkD,GAAiB,IAAO;UAC1E,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG;QAAoB;QAAa;QAAoB;QACpD;SACQ,EAAA,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAAsB;QAA4B,CAAA,EACvE,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,CACtC;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CAAkD,GAAgB,IAAO;UACzE,kBAAC,KAAD;OAAG,WAAU;iBAAb,CAA4C,GAAgB,iBAAkB;SAClE,EAAA,CAAA,CACJ;;KACR;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAM,WAAU;eAAhB,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAW,2BAAmC,CAAA,EAC9C,kBAAC,GAAD,EAAA,UAAiB,iDAA+D,CAAA,CACrE,EAAA,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACG,EAAc,WAAW,KACxB,kBAAC,KAAD;OAAG,WAAU;iBAA+C;OAExD,CAAA,EAEL,EAAc,KAAK,MAClB,kBAAC,OAAD;OAAmB,WAAU;iBAA7B;QACE,kBAAC,QAAD;SAAM,WAAU;mBAAoC,EAAE;SAAa,CAAA;QACnE,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,OAAD;UACE,WAAU;UACV,OAAO,EACL,OAAO,GAAG,KAAK,MAAO,EAAE,eAAe,IAAmB,IAAI,CAAC,IAChE;UACD,CAAA;SACE,CAAA;QACN,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,GAAD;WAAO,SAAQ;WAAU,WAAU;qBAAnC,CACG,EAAE,cAAa,QACV;;UACR,kBAAC,GAAD;WAAO,SAAQ;WAAY,WAAU;qBAArC,CACG,EAAE,YAAW,OACR;;UACR,kBAAC,GAAD;WAAO,SAAQ;WAAU,WAAU;qBAAnC,CACG,EAAE,OAAM,SACH;;UACJ;;QACF;SArBI,EAAE,MAqBN,CACN,CACU;QACT;QAEP,kBAAC,GAAD;KAAM,WAAU;eAAhB,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAW,mBAA2B,CAAA,EACtC,kBAAC,GAAD,EAAA,UAAiB,kCAAgD,CAAA,CACtD,EAAA,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBACpB,EAAe,KAAK,MACnB,kBAAC,OAAD;OAAwB,WAAU;iBAAlC;QACE,kBAAC,OAAD,EAAK,WAAW,wBAAwB,EAAM,SAAW,CAAA;QACzD,kBAAC,QAAD;SAAM,WAAU;mBAAgB,EAAM;SAAc,CAAA;QACpD,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,OAAD;UACE,WAAW,eAAe,EAAM;UAChC,OAAO,EACL,OAAO,GAAG,IAAgB,IAAI,KAAK,IAAI,KAAK,MAAO,EAAM,QAAQ,IAAiB,IAAI,EAAE,EAAE,GAAG,EAAE,IAChG;UACD,CAAA;SACE,CAAA;QACN,kBAAC,QAAD;SAAM,WAAU;mBAAsC,EAAM;SAAa,CAAA;QACrE;SAZI,EAAM,OAYV,CACN;MACU,CAAA,CACT;OACH;;GAEN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAW,wBAAgC,CAAA,EAC3C,kBAAC,GAAD,EAAA,UAAiB,8CAA4D,CAAA,CAClE,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IACE,SA5NgD;KACxD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAAe,EAAI;OAAc,CAAA;MACjE;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAA0B,EAAI;OAAoB,CAAA;MAClF;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAA0B,EAAI;OAAa,CAAA;MAC3E;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MACL,kBAAC,QAAD;OAAM,WAAU;iBACd,kBAAC,GAAD;QACE,SAAS,EAAI,kBAAkB,IAAI,YAAY;QAC/C,WAAU;kBAFZ,CAIG,EAAI,gBAAe,IACd;;OACH,CAAA;MAEV;KACF;IA2LS,MAAM;IACN,SAAS,MAAQ,EAAI;IACrB,YACE,kBAAC,KAAD;KAAG,WAAU;eAA+C;KAExD,CAAA;IAEN,CAAA,EACU,CAAA,CACT,EAAA,CAAA;GAEP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAW,yBAAiC,CAAA,EAC5C,kBAAC,GAAD,EAAA,UAAiB,4CAA0D,CAAA,CAChE,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACG,EAAc,WAAW,IACxB,kBAAC,GAAD;IACE,cAAa;IACb,OAAM;IACN,aAAY;IACZ,CAAA,GAEF,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;IAAiB,SAlN2B;KACtD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAAe,EAAI;OAAa,CAAA;MAChE;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAAuB,EAAI;OAAkB,CAAA;MAC7E;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MACL,kBAAC,GAAD;OAAO,SAAQ;OAAU,WAAU;iBAChC,EAAI;OACC,CAAA;MAEX;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAA0B,EAAI;OAAkB,CAAA;MAChF;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MACL,kBAAC,QAAD;OAAM,WAAU;iBAAhB;QAA6D;SACxD,EAAI,YAAY,KAAM,QAAQ,EAAE;QAAC;SAAK,EAAI,YAAY,KAAM,QAAQ,EAAE;QAAC;QACrE;;MAEV;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MACL,kBAAC,GAAD;OAAO,SAAQ;OAAU,WAAU;iBAChC,EAAI;OACC,CAAA;MAEX;KACF;IAiKiD,MAAM;IAAc,SAAS,MAAQ,EAAI;IAAM,CAAA,EACpF,EAAc,SAAS,KACtB,kBAAC,GAAD;IACE,MAAM;IACN,UAAU;IACV,YAAY,EAAc;IAC1B,cAAc;IACd,WAAU;IACV,CAAA,CAEH,EAAA,CAAA,EAEO,CAAA,CACT,EAAA,CAAA;GACH"}
1
+ {"version":3,"file":"AnalyticsHiringAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n Pagination,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\nimport { Briefcase, Clock, Target, Users } from 'lucide-react';\nimport { useMemo } from 'react';\nimport { useCrewFoundryStore, type JobPosting } from '../store/crewfoundryStore';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\n\ntype SourceRow = {\n source: string;\n applications: number;\n hires: number;\n conversionRate: number;\n};\n\nconst monthKeyOf = (value: string) => {\n const date = new Date(value);\n return `${date.getFullYear()}-${String(date.getMonth()).padStart(2, '0')}`;\n};\n\n// Stable \"as of\" anchor for this dataset (avoids impure Date.now() in render).\nconst AS_OF = new Date('2026-03-01').getTime();\n\nexport function AnalyticsHiringAnalyticsPagePage() {\n const { jobPostings, candidates, interviews } = useCrewFoundryStore();\n\n // Real monthly activity derived from candidate/interview dates.\n const hiringMetrics = useMemo(() => {\n if (candidates.length === 0 && interviews.length === 0) {\n return [];\n }\n const keys = Array.from(\n new Set([\n ...candidates.map((candidate) => monthKeyOf(candidate.appliedDate)),\n ...interviews.map((interview) => monthKeyOf(interview.date)),\n ])\n )\n .sort()\n .slice(-6);\n return keys.map((key) => {\n const [year, month] = key.split('-').map(Number);\n const label = new Date(year, month, 1).toLocaleString('en-US', {\n month: 'short',\n year: '2-digit',\n });\n const monthCandidates = candidates.filter(\n (candidate) => monthKeyOf(candidate.appliedDate) === key\n );\n return {\n month: label,\n applications: monthCandidates.length,\n interviews: interviews.filter((interview) => monthKeyOf(interview.date) === key).length,\n hires: monthCandidates.filter((candidate) => candidate.status === 'hired').length,\n };\n });\n }, [candidates, interviews]);\n\n const sourceEffectiveness = useMemo<SourceRow[]>(() => {\n const grouped = candidates.reduce<Record<string, { applications: number; hires: number }>>(\n (acc, candidate) => {\n const source = candidate.source || 'Unknown';\n const value = acc[source] || { applications: 0, hires: 0 };\n value.applications += 1;\n if (candidate.status === 'hired') {\n value.hires += 1;\n }\n acc[source] = value;\n return acc;\n },\n {}\n );\n\n return Object.entries(grouped)\n .map(([source, value]) => ({\n source,\n applications: value.applications,\n hires: value.hires,\n conversionRate: Number(((value.hires / Math.max(value.applications, 1)) * 100).toFixed(1)),\n }))\n .sort((a, b) => b.conversionRate - a.conversionRate);\n }, [candidates]);\n\n // Real average number of days active postings have been open.\n const avgDaysOpen = useMemo(() => {\n const activePostings = jobPostings.filter((posting) => posting.status === 'active');\n if (activePostings.length === 0) {\n return 0;\n }\n const totalDays = activePostings.reduce((sum, posting) => {\n const posted = new Date(posting.postedDate).getTime();\n if (Number.isNaN(posted)) {\n return sum;\n }\n return sum + Math.max(0, (AS_OF - posted) / (1000 * 60 * 60 * 24));\n }, 0);\n return Math.round(totalDays / activePostings.length);\n }, [jobPostings]);\n\n const activeJobs = jobPostings.filter((j) => j.status === 'active');\n const totalApplicants = jobPostings.reduce((s, j) => s + j.applicants, 0);\n const scheduledInterviews = interviews.filter((i) => i.status === 'scheduled').length;\n const completedInterviews = interviews.filter((i) => i.status === 'completed').length;\n const offeredCandidates = candidates.filter((c) => c.status === 'offer').length;\n const hiredCandidates = candidates.filter((c) => c.status === 'hired').length;\n\n const interviewedOrBeyond = candidates.filter((c) =>\n ['interview', 'assessment', 'offer', 'hired'].includes(c.status)\n ).length;\n const offerOrBeyond = candidates.filter((c) => ['offer', 'hired'].includes(c.status)).length;\n const interviewToOffer = Math.round((offerOrBeyond / Math.max(interviewedOrBeyond, 1)) * 100);\n const offerAcceptance = Math.round(\n (hiredCandidates / Math.max(offeredCandidates + hiredCandidates, 1)) * 100\n );\n\n const maxApplications = Math.max(1, ...hiringMetrics.map((m) => m.applications));\n\n const statusPipeline = [\n {\n status: 'New',\n count: candidates.filter((c) => c.status === 'new').length,\n color: 'bg-text-secondary',\n },\n {\n status: 'Screening',\n count: candidates.filter((c) => c.status === 'screening').length,\n color: 'bg-status-info-text',\n },\n {\n status: 'Interview',\n count: candidates.filter((c) => c.status === 'interview').length,\n color: 'bg-status-info-text',\n },\n {\n status: 'Assessment',\n count: candidates.filter((c) => c.status === 'assessment').length,\n color: 'bg-action-primary-bg',\n },\n { status: 'Offer', count: offeredCandidates, color: 'bg-status-warning-text' },\n { status: 'Hired', count: hiredCandidates, color: 'bg-status-success-text' },\n {\n status: 'Rejected',\n count: candidates.filter((c) => c.status === 'rejected').length,\n color: 'bg-status-error-text',\n },\n ];\n const totalPipeline = statusPipeline.reduce((s, p) => s + p.count, 0);\n\n // Open Positions = active postings only, paginated to match the card title.\n const openPositions = [...activeJobs].sort((a, b) => b.applicants - a.applicants);\n const {\n page: jobPage,\n pageSize: jobPageSize,\n offset: jobOffset,\n setPage: setJobPage,\n } = usePagination({ initialPageSize: 8 });\n const jobPageItems = openPositions.slice(jobOffset, jobOffset + jobPageSize);\n\n const sourceColumns: ResponsiveTableColumn<SourceRow>[] = [\n {\n key: 'source',\n header: 'Source',\n priority: 'primary',\n cell: (src) => <span className=\"font-medium\">{src.source}</span>,\n },\n {\n key: 'applications',\n header: 'Applications',\n priority: 'secondary',\n cell: (src) => <span className=\"md:block md:text-right\">{src.applications}</span>,\n },\n {\n key: 'hires',\n header: 'Hires',\n priority: 'secondary',\n cell: (src) => <span className=\"md:block md:text-right\">{src.hires}</span>,\n },\n {\n key: 'conversion',\n header: 'Conversion',\n priority: 'primary',\n cell: (src) => (\n <span className=\"md:block md:text-right\">\n <Badge\n variant={src.conversionRate >= 5 ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {src.conversionRate}%\n </Badge>\n </span>\n ),\n },\n ];\n\n const jobColumns: ResponsiveTableColumn<JobPosting>[] = [\n {\n key: 'title',\n header: 'Position',\n priority: 'primary',\n cell: (job) => <span className=\"font-medium\">{job.title}</span>,\n },\n {\n key: 'department',\n header: 'Department',\n priority: 'secondary',\n cell: (job) => <span className=\"text-text-secondary\">{job.department}</span>,\n },\n {\n key: 'level',\n header: 'Level',\n priority: 'hidden-on-mobile',\n cell: (job) => (\n <Badge variant=\"outline\" className=\"w-fit text-[10px]\">\n {formatEnumLabel(job.experienceLevel)}\n </Badge>\n ),\n },\n {\n key: 'applicants',\n header: 'Applicants',\n priority: 'secondary',\n cell: (job) => <span className=\"md:block md:text-right\">{job.applicants}</span>,\n },\n {\n key: 'salary',\n header: 'Salary Range',\n priority: 'secondary',\n cell: (job) => (\n <span className=\"md:block md:text-right text-text-secondary\">\n ${(job.salaryMin / 1000).toFixed(0)}K-${(job.salaryMax / 1000).toFixed(0)}K\n </span>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n priority: 'primary',\n cell: (job) => (\n <Badge variant=\"default\" className=\"text-[10px]\">\n {formatEnumLabel(job.status)}\n </Badge>\n ),\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>Hiring Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Recruitment performance and pipeline analysis\n </p>\n <PagePurpose className=\"mt-1\">\n Measure how your hiring funnel performs — applications, time-to-hire, and source quality\n — to make recruiting faster and more effective.\n </PagePurpose>\n </div>\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\">Active Postings</CardTitle>\n <Briefcase className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activeJobs.length}</div>\n <p className=\"text-xs text-text-secondary\">{totalApplicants} total applicants</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\">Avg Days Open</CardTitle>\n <Clock className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{avgDaysOpen} days</div>\n <p className=\"text-xs text-text-secondary\">Across active postings</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\">Interview to Offer</CardTitle>\n <Target className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{interviewToOffer}%</div>\n <p className=\"text-xs text-text-secondary\">\n {scheduledInterviews} scheduled, {completedInterviews} 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\">Offer Acceptance</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{offerAcceptance}%</div>\n <p className=\"text-xs text-text-secondary\">{hiredCandidates} hired to date</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-7\">\n <Card className=\"col-span-4\">\n <CardHeader>\n <CardTitle>Monthly Hiring Activity</CardTitle>\n <CardDescription>Applications, interviews, and hires over time</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {hiringMetrics.length === 0 && (\n <p className=\"py-6 text-center text-sm text-text-secondary\">\n No hiring activity recorded yet.\n </p>\n )}\n {hiringMetrics.map((m) => (\n <div key={m.month} className=\"flex items-center gap-3\">\n <span className=\"w-12 text-sm text-text-secondary\">{m.month}</span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-5 bg-action-primary-bg rounded\"\n style={{\n width: `${Math.round((m.applications / maxApplications) * 100)}%`,\n }}\n />\n </div>\n <div className=\"flex gap-1 w-48 justify-end\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {m.applications} apps\n </Badge>\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n {m.interviews} int\n </Badge>\n <Badge variant=\"default\" className=\"text-[10px]\">\n {m.hires} hired\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card className=\"col-span-3\">\n <CardHeader>\n <CardTitle>Pipeline Status</CardTitle>\n <CardDescription>Current candidate distribution</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {statusPipeline.map((stage) => (\n <div key={stage.status} className=\"flex items-center gap-3\">\n <div className={`h-3 w-3 rounded-full ${stage.color}`} />\n <span className=\"w-20 text-sm\">{formatEnumLabel(stage.status)}</span>\n <div className=\"flex-1 h-3 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-3 rounded ${stage.color}`}\n style={{\n width: `${totalPipeline > 0 ? Math.max(Math.round((stage.count / totalPipeline) * 100), 3) : 3}%`,\n }}\n />\n </div>\n <span className=\"text-sm font-medium w-6 text-right\">{stage.count}</span>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Source Effectiveness</CardTitle>\n <CardDescription>Recruitment channel performance comparison</CardDescription>\n </CardHeader>\n <CardContent>\n <ResponsiveTable\n columns={sourceColumns}\n data={sourceEffectiveness}\n rowKey={(src) => src.source}\n emptyState={\n <p className=\"py-6 text-center text-sm text-text-secondary\">\n No candidate source data yet.\n </p>\n }\n />\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Open Positions Detail</CardTitle>\n <CardDescription>Active job postings and applicant counts</CardDescription>\n </CardHeader>\n <CardContent>\n {openPositions.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No open positions\"\n description=\"Active job postings will appear here once you publish a role.\"\n />\n ) : (\n <>\n <ResponsiveTable columns={jobColumns} data={jobPageItems} rowKey={(job) => job.id} />\n {openPositions.length > jobPageSize && (\n <Pagination\n page={jobPage}\n pageSize={jobPageSize}\n totalItems={openPositions.length}\n onPageChange={setJobPage}\n className=\"mt-3\"\n />\n )}\n </>\n )}\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AA4BA,IAAM,KAAc,MAAkB;CACpC,IAAM,IAAO,IAAI,KAAK,EAAM;AAC5B,QAAO,GAAG,EAAK,aAAa,CAAC,GAAG,OAAO,EAAK,UAAU,CAAC,CAAC,SAAS,GAAG,IAAI;GAIpE,qBAAQ,IAAI,KAAK,aAAa,EAAC,SAAS;AAE9C,SAAgB,IAAmC;CACjD,IAAM,EAAE,gBAAa,eAAY,kBAAe,GAAqB,EAG/D,IAAgB,QAChB,EAAW,WAAW,KAAK,EAAW,WAAW,IAC5C,EAAE,GAEE,MAAM,KACjB,IAAI,IAAI,CACN,GAAG,EAAW,KAAK,MAAc,EAAW,EAAU,YAAY,CAAC,EACnE,GAAG,EAAW,KAAK,MAAc,EAAW,EAAU,KAAK,CAAC,CAC7D,CAAC,CACH,CACE,MAAM,CACN,MAAM,GAAG,CACA,KAAK,MAAQ;EACvB,IAAM,CAAC,GAAM,KAAS,EAAI,MAAM,IAAI,CAAC,IAAI,OAAO,EAC1C,IAAQ,IAAI,KAAK,GAAM,GAAO,EAAE,CAAC,eAAe,SAAS;GAC7D,OAAO;GACP,MAAM;GACP,CAAC,EACI,IAAkB,EAAW,QAChC,MAAc,EAAW,EAAU,YAAY,KAAK,EACtD;AACD,SAAO;GACL,OAAO;GACP,cAAc,EAAgB;GAC9B,YAAY,EAAW,QAAQ,MAAc,EAAW,EAAU,KAAK,KAAK,EAAI,CAAC;GACjF,OAAO,EAAgB,QAAQ,MAAc,EAAU,WAAW,QAAQ,CAAC;GAC5E;GACD,EACD,CAAC,GAAY,EAAW,CAAC,EAEtB,IAAsB,QAA2B;EACrD,IAAM,IAAU,EAAW,QACxB,GAAK,MAAc;GAClB,IAAM,IAAS,EAAU,UAAU,WAC7B,IAAQ,EAAI,MAAW;IAAE,cAAc;IAAG,OAAO;IAAG;AAM1D,UALA,EAAM,gBAAgB,GAClB,EAAU,WAAW,YACvB,EAAM,SAAS,IAEjB,EAAI,KAAU,GACP;KAET,EAAE,CACH;AAED,SAAO,OAAO,QAAQ,EAAQ,CAC3B,KAAK,CAAC,GAAQ,QAAY;GACzB;GACA,cAAc,EAAM;GACpB,OAAO,EAAM;GACb,gBAAgB,QAAS,EAAM,QAAQ,KAAK,IAAI,EAAM,cAAc,EAAE,GAAI,KAAK,QAAQ,EAAE,CAAC;GAC3F,EAAE,CACF,MAAM,GAAG,MAAM,EAAE,iBAAiB,EAAE,eAAe;IACrD,CAAC,EAAW,CAAC,EAGV,IAAc,QAAc;EAChC,IAAM,IAAiB,EAAY,QAAQ,MAAY,EAAQ,WAAW,SAAS;AACnF,MAAI,EAAe,WAAW,EAC5B,QAAO;EAET,IAAM,IAAY,EAAe,QAAQ,GAAK,MAAY;GACxD,IAAM,IAAS,IAAI,KAAK,EAAQ,WAAW,CAAC,SAAS;AAIrD,UAHI,OAAO,MAAM,EAAO,GACf,IAEF,IAAM,KAAK,IAAI,IAAI,IAAQ,MAAW,MAAO,KAAK,KAAK,IAAI;KACjE,EAAE;AACL,SAAO,KAAK,MAAM,IAAY,EAAe,OAAO;IACnD,CAAC,EAAY,CAAC,EAEX,IAAa,EAAY,QAAQ,MAAM,EAAE,WAAW,SAAS,EAC7D,IAAkB,EAAY,QAAQ,GAAG,MAAM,IAAI,EAAE,YAAY,EAAE,EACnE,IAAsB,EAAW,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC,QACzE,IAAsB,EAAW,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC,QACzE,IAAoB,EAAW,QAAQ,MAAM,EAAE,WAAW,QAAQ,CAAC,QACnE,IAAkB,EAAW,QAAQ,MAAM,EAAE,WAAW,QAAQ,CAAC,QAEjE,IAAsB,EAAW,QAAQ,MAC7C;EAAC;EAAa;EAAc;EAAS;EAAQ,CAAC,SAAS,EAAE,OAAO,CACjE,CAAC,QACI,IAAgB,EAAW,QAAQ,MAAM,CAAC,SAAS,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,QAChF,IAAmB,KAAK,MAAO,IAAgB,KAAK,IAAI,GAAqB,EAAE,GAAI,IAAI,EACvF,IAAkB,KAAK,MAC1B,IAAkB,KAAK,IAAI,IAAoB,GAAiB,EAAE,GAAI,IACxE,EAEK,IAAkB,KAAK,IAAI,GAAG,GAAG,EAAc,KAAK,MAAM,EAAE,aAAa,CAAC,EAE1E,IAAiB;EACrB;GACE,QAAQ;GACR,OAAO,EAAW,QAAQ,MAAM,EAAE,WAAW,MAAM,CAAC;GACpD,OAAO;GACR;EACD;GACE,QAAQ;GACR,OAAO,EAAW,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC;GAC1D,OAAO;GACR;EACD;GACE,QAAQ;GACR,OAAO,EAAW,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC;GAC1D,OAAO;GACR;EACD;GACE,QAAQ;GACR,OAAO,EAAW,QAAQ,MAAM,EAAE,WAAW,aAAa,CAAC;GAC3D,OAAO;GACR;EACD;GAAE,QAAQ;GAAS,OAAO;GAAmB,OAAO;GAA0B;EAC9E;GAAE,QAAQ;GAAS,OAAO;GAAiB,OAAO;GAA0B;EAC5E;GACE,QAAQ;GACR,OAAO,EAAW,QAAQ,MAAM,EAAE,WAAW,WAAW,CAAC;GACzD,OAAO;GACR;EACF,EACK,IAAgB,EAAe,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,EAAE,EAG/D,IAAgB,CAAC,GAAG,EAAW,CAAC,MAAM,GAAG,MAAM,EAAE,aAAa,EAAE,WAAW,EAC3E,EACJ,MAAM,GACN,UAAU,GACV,QAAQ,GACR,SAAS,MACP,EAAc,EAAE,iBAAiB,GAAG,CAAC,EACnC,IAAe,EAAc,MAAM,GAAW,IAAY,EAAY;AAyF5E,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD,EAAA,UAAA;KACE,kBAAC,MAAD;MAAI,WAAU;gBACZ,kBAAC,GAAD,EAAA,UAAc,oBAA+B,CAAA;MAC1C,CAAA;KACL,kBAAC,KAAD;MAAG,WAAU;gBAA8B;MAEvC,CAAA;KACJ,kBAAC,GAAD;MAAa,WAAU;gBAAO;MAGhB,CAAA;KACV,EAAA,CAAA;IACF,CAAA;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MAAW,WAAU;MAAQ,MAAA;MAAK,WAAU;gBAA5C,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAAsB;QAA2B,CAAA,EACtE,kBAAC,GAAD,EAAW,WAAU,+BAAgC,CAAA,CAC1C;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAmC,EAAW;OAAa,CAAA,EAC1E,kBAAC,KAAD;OAAG,WAAU;iBAAb,CAA4C,GAAgB,oBAAqB;SACrE,EAAA,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAAsB;QAAyB,CAAA,EACpE,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,CACtC;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CAAkD,GAAY,QAAW;UACzE,kBAAC,KAAD;OAAG,WAAU;iBAA8B;OAA0B,CAAA,CACzD,EAAA,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAAsB;QAA8B,CAAA,EACzE,kBAAC,GAAD,EAAQ,WAAU,+BAAgC,CAAA,CACvC;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CAAkD,GAAiB,IAAO;UAC1E,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG;QAAoB;QAAa;QAAoB;QACpD;SACQ,EAAA,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAAsB;QAA4B,CAAA,EACvE,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,CACtC;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CAAkD,GAAgB,IAAO;UACzE,kBAAC,KAAD;OAAG,WAAU;iBAAb,CAA4C,GAAgB,iBAAkB;SAClE,EAAA,CAAA,CACJ;;KACR;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAM,WAAU;eAAhB,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAW,2BAAmC,CAAA,EAC9C,kBAAC,GAAD,EAAA,UAAiB,iDAA+D,CAAA,CACrE,EAAA,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBAAvB,CACG,EAAc,WAAW,KACxB,kBAAC,KAAD;OAAG,WAAU;iBAA+C;OAExD,CAAA,EAEL,EAAc,KAAK,MAClB,kBAAC,OAAD;OAAmB,WAAU;iBAA7B;QACE,kBAAC,QAAD;SAAM,WAAU;mBAAoC,EAAE;SAAa,CAAA;QACnE,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,OAAD;UACE,WAAU;UACV,OAAO,EACL,OAAO,GAAG,KAAK,MAAO,EAAE,eAAe,IAAmB,IAAI,CAAC,IAChE;UACD,CAAA;SACE,CAAA;QACN,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,GAAD;WAAO,SAAQ;WAAU,WAAU;qBAAnC,CACG,EAAE,cAAa,QACV;;UACR,kBAAC,GAAD;WAAO,SAAQ;WAAY,WAAU;qBAArC,CACG,EAAE,YAAW,OACR;;UACR,kBAAC,GAAD;WAAO,SAAQ;WAAU,WAAU;qBAAnC,CACG,EAAE,OAAM,SACH;;UACJ;;QACF;SArBI,EAAE,MAqBN,CACN,CACU;QACT;QAEP,kBAAC,GAAD;KAAM,WAAU;eAAhB,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAW,mBAA2B,CAAA,EACtC,kBAAC,GAAD,EAAA,UAAiB,kCAAgD,CAAA,CACtD,EAAA,CAAA,EACb,kBAAC,GAAD;MAAa,WAAU;gBACpB,EAAe,KAAK,MACnB,kBAAC,OAAD;OAAwB,WAAU;iBAAlC;QACE,kBAAC,OAAD,EAAK,WAAW,wBAAwB,EAAM,SAAW,CAAA;QACzD,kBAAC,QAAD;SAAM,WAAU;mBAAgB,EAAgB,EAAM,OAAO;SAAQ,CAAA;QACrE,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,OAAD;UACE,WAAW,eAAe,EAAM;UAChC,OAAO,EACL,OAAO,GAAG,IAAgB,IAAI,KAAK,IAAI,KAAK,MAAO,EAAM,QAAQ,IAAiB,IAAI,EAAE,EAAE,GAAG,EAAE,IAChG;UACD,CAAA;SACE,CAAA;QACN,kBAAC,QAAD;SAAM,WAAU;mBAAsC,EAAM;SAAa,CAAA;QACrE;SAZI,EAAM,OAYV,CACN;MACU,CAAA,CACT;OACH;;GAEN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAW,wBAAgC,CAAA,EAC3C,kBAAC,GAAD,EAAA,UAAiB,8CAA4D,CAAA,CAClE,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;IACE,SA5NgD;KACxD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAAe,EAAI;OAAc,CAAA;MACjE;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAA0B,EAAI;OAAoB,CAAA;MAClF;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAA0B,EAAI;OAAa,CAAA;MAC3E;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MACL,kBAAC,QAAD;OAAM,WAAU;iBACd,kBAAC,GAAD;QACE,SAAS,EAAI,kBAAkB,IAAI,YAAY;QAC/C,WAAU;kBAFZ,CAIG,EAAI,gBAAe,IACd;;OACH,CAAA;MAEV;KACF;IA2LS,MAAM;IACN,SAAS,MAAQ,EAAI;IACrB,YACE,kBAAC,KAAD;KAAG,WAAU;eAA+C;KAExD,CAAA;IAEN,CAAA,EACU,CAAA,CACT,EAAA,CAAA;GAEP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAW,yBAAiC,CAAA,EAC5C,kBAAC,GAAD,EAAA,UAAiB,4CAA0D,CAAA,CAChE,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACG,EAAc,WAAW,IACxB,kBAAC,GAAD;IACE,cAAa;IACb,OAAM;IACN,aAAY;IACZ,CAAA,GAEF,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;IAAiB,SAlN2B;KACtD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAAe,EAAI;OAAa,CAAA;MAChE;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAAuB,EAAI;OAAkB,CAAA;MAC7E;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MACL,kBAAC,GAAD;OAAO,SAAQ;OAAU,WAAU;iBAChC,EAAgB,EAAI,gBAAgB;OAC/B,CAAA;MAEX;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MAAQ,kBAAC,QAAD;OAAM,WAAU;iBAA0B,EAAI;OAAkB,CAAA;MAChF;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MACL,kBAAC,QAAD;OAAM,WAAU;iBAAhB;QAA6D;SACxD,EAAI,YAAY,KAAM,QAAQ,EAAE;QAAC;SAAK,EAAI,YAAY,KAAM,QAAQ,EAAE;QAAC;QACrE;;MAEV;KACD;MACE,KAAK;MACL,QAAQ;MACR,UAAU;MACV,OAAO,MACL,kBAAC,GAAD;OAAO,SAAQ;OAAU,WAAU;iBAChC,EAAgB,EAAI,OAAO;OACtB,CAAA;MAEX;KACF;IAiKiD,MAAM;IAAc,SAAS,MAAQ,EAAI;IAAM,CAAA,EACpF,EAAc,SAAS,KACtB,kBAAC,GAAD;IACE,MAAM;IACN,UAAU;IACV,YAAY,EAAc;IAC1B,cAAc;IACd,WAAU;IACV,CAAA,CAEH,EAAA,CAAA,EAEO,CAAA,CACT,EAAA,CAAA;GACH"}