@burdenoff/microfe-crewfoundry 2026.1107.1 → 2026.1107.2

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.
@@ -1,33 +1,34 @@
1
1
  import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
- import { useCallback as t, useEffect as n, useMemo as r } from "react";
3
- import { Building2 as i, Percent as a, RefreshCw as o, Target as s, UserPlus as c, Users as l } from "lucide-react";
4
- import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
5
- import { Badge as p, Button as m, Card as h, CardContent as g, CardDescription as _, CardHeader as v, CardTitle as y, GlassCard as b, GradientText as x, IllustratedEmptyState as S, PagePurpose as C, ResponsiveTable as w, Separator as T, Spinner as E } from "@burdenoff/fe-libs/ui";
2
+ import { WorkforceForecastCard as t } from "../components/WorkforceForecastCard.js";
3
+ import { useCallback as n, useEffect as r, useMemo as i } from "react";
4
+ import { Building2 as a, Percent as o, RefreshCw as s, Target as c, UserPlus as l, Users as u } from "lucide-react";
5
+ import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
6
+ import { Badge as m, Button as h, Card as g, CardContent as _, CardDescription as v, CardHeader as y, CardTitle as b, GlassCard as x, GradientText as S, IllustratedEmptyState as C, PagePurpose as w, ResponsiveTable as T, Separator as E, Spinner as D } from "@burdenoff/fe-libs/ui";
6
7
  //#region src/crewfoundry/pages/DashboardExecutiveDashboardPage.tsx
7
- var D = 8, O = {
8
+ var O = 8, k = {
8
9
  HIGH: "destructive",
9
10
  MEDIUM: "warning",
10
11
  LOW: "secondary"
11
12
  };
12
- function k(e) {
13
+ function A(e) {
13
14
  return Math.abs(e) >= 1e6 ? `$${(e / 1e6).toFixed(1)}M` : Math.abs(e) >= 1e3 ? `$${(e / 1e3).toFixed(0)}K` : `$${Math.round(e)}`;
14
15
  }
15
- function A(e) {
16
+ function j(e) {
16
17
  let t = new Date(e);
17
18
  return Number.isNaN(t.getTime()) ? "" : t.toLocaleString(void 0, {
18
19
  dateStyle: "medium",
19
20
  timeStyle: "short"
20
21
  });
21
22
  }
22
- var j = [
23
+ var M = [
23
24
  {
24
25
  key: "employee",
25
26
  header: "Employee",
26
27
  priority: "primary",
27
- cell: (e) => /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("p", {
28
+ cell: (e) => /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("p", {
28
29
  className: "font-medium",
29
30
  children: e.employeeName
30
- }), /* @__PURE__ */ d("p", {
31
+ }), /* @__PURE__ */ f("p", {
31
32
  className: "text-xs text-text-secondary",
32
33
  children: e.department
33
34
  })] })
@@ -36,8 +37,8 @@ var j = [
36
37
  key: "level",
37
38
  header: "Risk",
38
39
  priority: "primary",
39
- cell: (e) => /* @__PURE__ */ f(p, {
40
- variant: O[e.riskLevel],
40
+ cell: (e) => /* @__PURE__ */ p(m, {
41
+ variant: k[e.riskLevel],
41
42
  children: [
42
43
  e.riskLevel.charAt(0),
43
44
  e.riskLevel.slice(1).toLowerCase(),
@@ -50,17 +51,17 @@ var j = [
50
51
  key: "drivers",
51
52
  header: "Drivers",
52
53
  priority: "secondary",
53
- cell: (e) => /* @__PURE__ */ d("span", {
54
+ cell: (e) => /* @__PURE__ */ f("span", {
54
55
  className: "text-sm text-text-secondary",
55
56
  children: e.drivers.length > 0 ? e.drivers.join(", ") : "No risk signals"
56
57
  })
57
58
  }
58
- ], M = [
59
+ ], N = [
59
60
  {
60
61
  key: "department",
61
62
  header: "Department",
62
63
  priority: "primary",
63
- cell: (e) => /* @__PURE__ */ d("span", {
64
+ cell: (e) => /* @__PURE__ */ f("span", {
64
65
  className: "font-medium",
65
66
  children: e.department
66
67
  })
@@ -69,7 +70,7 @@ var j = [
69
70
  key: "current",
70
71
  header: "Active",
71
72
  priority: "secondary",
72
- cell: (e) => /* @__PURE__ */ d("span", {
73
+ cell: (e) => /* @__PURE__ */ f("span", {
73
74
  className: "tabular-nums md:block md:text-right",
74
75
  children: e.current
75
76
  })
@@ -78,7 +79,7 @@ var j = [
78
79
  key: "open",
79
80
  header: "Open roles",
80
81
  priority: "primary",
81
- cell: (e) => /* @__PURE__ */ d("span", {
82
+ cell: (e) => /* @__PURE__ */ f("span", {
82
83
  className: "tabular-nums md:block md:text-right",
83
84
  children: e.openPostings
84
85
  })
@@ -87,17 +88,17 @@ var j = [
87
88
  key: "projected",
88
89
  header: "Projected",
89
90
  priority: "secondary",
90
- cell: (e) => /* @__PURE__ */ d("span", {
91
+ cell: (e) => /* @__PURE__ */ f("span", {
91
92
  className: "tabular-nums md:block md:text-right",
92
93
  children: e.projectedHeadcount
93
94
  })
94
95
  }
95
- ], N = [
96
+ ], P = [
96
97
  {
97
98
  key: "skill",
98
99
  header: "Skill",
99
100
  priority: "primary",
100
- cell: (e) => /* @__PURE__ */ d("span", {
101
+ cell: (e) => /* @__PURE__ */ f("span", {
101
102
  className: "font-medium",
102
103
  children: e.skill
103
104
  })
@@ -106,7 +107,7 @@ var j = [
106
107
  key: "supply",
107
108
  header: "People",
108
109
  priority: "secondary",
109
- cell: (e) => /* @__PURE__ */ d("span", {
110
+ cell: (e) => /* @__PURE__ */ f("span", {
110
111
  className: "tabular-nums md:block md:text-right",
111
112
  children: e.employeesWithSkill
112
113
  })
@@ -115,7 +116,7 @@ var j = [
115
116
  key: "demand",
116
117
  header: "Open roles",
117
118
  priority: "secondary",
118
- cell: (e) => /* @__PURE__ */ d("span", {
119
+ cell: (e) => /* @__PURE__ */ f("span", {
119
120
  className: "tabular-nums md:block md:text-right",
120
121
  children: e.openJobsRequiringSkill
121
122
  })
@@ -124,17 +125,17 @@ var j = [
124
125
  key: "shortage",
125
126
  header: "Shortage",
126
127
  priority: "primary",
127
- cell: (e) => /* @__PURE__ */ d("span", {
128
+ cell: (e) => /* @__PURE__ */ f("span", {
128
129
  className: "font-semibold tabular-nums text-status-warning-text md:block md:text-right",
129
130
  children: e.shortage
130
131
  })
131
132
  }
132
- ], P = [
133
+ ], F = [
133
134
  {
134
135
  key: "department",
135
136
  header: "Department",
136
137
  priority: "primary",
137
- cell: (e) => /* @__PURE__ */ d("span", {
138
+ cell: (e) => /* @__PURE__ */ f("span", {
138
139
  className: "font-medium",
139
140
  children: e.department
140
141
  })
@@ -143,7 +144,7 @@ var j = [
143
144
  key: "headcount",
144
145
  header: "Active",
145
146
  priority: "secondary",
146
- cell: (e) => /* @__PURE__ */ d("span", {
147
+ cell: (e) => /* @__PURE__ */ f("span", {
147
148
  className: "tabular-nums md:block md:text-right",
148
149
  children: e.headcount
149
150
  })
@@ -152,26 +153,26 @@ var j = [
152
153
  key: "monthly",
153
154
  header: "Monthly",
154
155
  priority: "secondary",
155
- cell: (e) => /* @__PURE__ */ d("span", {
156
+ cell: (e) => /* @__PURE__ */ f("span", {
156
157
  className: "tabular-nums md:block md:text-right",
157
- children: k(e.monthly)
158
+ children: A(e.monthly)
158
159
  })
159
160
  },
160
161
  {
161
162
  key: "annual",
162
163
  header: "Annual",
163
164
  priority: "primary",
164
- cell: (e) => /* @__PURE__ */ d("span", {
165
+ cell: (e) => /* @__PURE__ */ f("span", {
165
166
  className: "tabular-nums md:block md:text-right",
166
- children: k(e.annual)
167
+ children: A(e.annual)
167
168
  })
168
169
  }
169
- ], F = [
170
+ ], I = [
170
171
  {
171
172
  key: "name",
172
173
  header: "Department",
173
174
  priority: "primary",
174
- cell: (e) => /* @__PURE__ */ d("span", {
175
+ cell: (e) => /* @__PURE__ */ f("span", {
175
176
  className: "font-medium",
176
177
  children: e.name
177
178
  })
@@ -180,7 +181,7 @@ var j = [
180
181
  key: "head",
181
182
  header: "Head",
182
183
  priority: "secondary",
183
- cell: (e) => /* @__PURE__ */ d("span", {
184
+ cell: (e) => /* @__PURE__ */ f("span", {
184
185
  className: "text-text-secondary",
185
186
  children: e.headName
186
187
  })
@@ -189,7 +190,7 @@ var j = [
189
190
  key: "headcount",
190
191
  header: "Headcount",
191
192
  priority: "secondary",
192
- cell: (e) => /* @__PURE__ */ d("span", {
193
+ cell: (e) => /* @__PURE__ */ f("span", {
193
194
  className: "md:block md:text-right",
194
195
  children: e.employeeCount
195
196
  })
@@ -198,88 +199,88 @@ var j = [
198
199
  key: "budget",
199
200
  header: "Budget",
200
201
  priority: "secondary",
201
- cell: (e) => /* @__PURE__ */ d("span", {
202
+ cell: (e) => /* @__PURE__ */ f("span", {
202
203
  className: "md:block md:text-right",
203
- children: k(e.budget)
204
+ children: A(e.budget)
204
205
  })
205
206
  },
206
207
  {
207
208
  key: "costPerEmployee",
208
209
  header: "Cost/Employee",
209
210
  priority: "primary",
210
- cell: (e) => /* @__PURE__ */ d("span", {
211
+ cell: (e) => /* @__PURE__ */ f("span", {
211
212
  className: "md:block md:text-right",
212
- children: k(e.employeeCount > 0 ? Math.round(e.budget / e.employeeCount) : 0)
213
+ children: A(e.employeeCount > 0 ? Math.round(e.budget / e.employeeCount) : 0)
213
214
  })
214
215
  }
215
216
  ];
216
- function I({ label: e, value: t, caption: n, icon: r, testId: i }) {
217
- return /* @__PURE__ */ f(b, {
217
+ function L({ label: e, value: t, caption: n, icon: r, testId: i }) {
218
+ return /* @__PURE__ */ p(x, {
218
219
  treatment: "metric",
219
220
  className: "border-border-seam",
220
221
  "data-testid": i,
221
- children: [/* @__PURE__ */ f(v, {
222
+ children: [/* @__PURE__ */ p(y, {
222
223
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
223
- children: [/* @__PURE__ */ d(y, {
224
+ children: [/* @__PURE__ */ f(b, {
224
225
  className: "text-sm font-medium",
225
226
  children: e
226
227
  }), r]
227
- }), /* @__PURE__ */ f(g, { children: [/* @__PURE__ */ d("div", {
228
+ }), /* @__PURE__ */ p(_, { children: [/* @__PURE__ */ f("div", {
228
229
  className: "text-2xl font-bold tabular-nums",
229
230
  children: t
230
- }), /* @__PURE__ */ d("p", {
231
+ }), /* @__PURE__ */ f("p", {
231
232
  className: "text-xs text-text-secondary",
232
233
  children: n
233
234
  })] })]
234
235
  });
235
236
  }
236
- function L({ analytics: e, budget: t, retention: n }) {
237
- let r = e.costProjection.reduce((e, t) => e + t.annual, 0), o = e.headcountGap.reduce((e, t) => e + t.openPostings, 0), u = t.total > 0 ? Math.round(t.spent / t.total * 100) : 0, p = n.total > 0 ? `${Math.round(n.retained / n.total * 100)}%` : "—", m = "h-4 w-4 text-text-secondary";
238
- return /* @__PURE__ */ f("div", {
237
+ function R({ analytics: e, budget: t, retention: n }) {
238
+ let r = e.costProjection.reduce((e, t) => e + t.annual, 0), i = e.headcountGap.reduce((e, t) => e + t.openPostings, 0), s = t.total > 0 ? Math.round(t.spent / t.total * 100) : 0, d = n.total > 0 ? `${Math.round(n.retained / n.total * 100)}%` : "—", m = "h-4 w-4 text-text-secondary";
239
+ return /* @__PURE__ */ p("div", {
239
240
  className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-4",
240
241
  children: [
241
- /* @__PURE__ */ d(I, {
242
+ /* @__PURE__ */ f(L, {
242
243
  label: "Active headcount",
243
244
  value: e.activeHeadcount,
244
245
  caption: `${e.totalHeadcount} people on record`,
245
- icon: /* @__PURE__ */ d(l, { className: m }),
246
+ icon: /* @__PURE__ */ f(u, { className: m }),
246
247
  testId: "kpi-active-headcount"
247
248
  }),
248
- /* @__PURE__ */ d(I, {
249
+ /* @__PURE__ */ f(L, {
249
250
  label: "Hires and exits (90 days)",
250
251
  value: `${e.newHiresLast90Days} / ${e.exitsLast90Days}`,
251
252
  caption: `${e.newHiresLast90Days} joined, ${e.exitsLast90Days} left`,
252
- icon: /* @__PURE__ */ d(c, { className: m })
253
+ icon: /* @__PURE__ */ f(l, { className: m })
253
254
  }),
254
- /* @__PURE__ */ d(I, {
255
+ /* @__PURE__ */ f(L, {
255
256
  label: "Average tenure",
256
257
  value: `${e.averageTenureMonths.toFixed(1)} mo`,
257
258
  caption: `Average performance ${e.averagePerformanceScore.toFixed(2)} of 5`,
258
- icon: /* @__PURE__ */ d(s, { className: m })
259
+ icon: /* @__PURE__ */ f(c, { className: m })
259
260
  }),
260
- /* @__PURE__ */ d(I, {
261
+ /* @__PURE__ */ f(L, {
261
262
  label: "Retention rate",
262
- value: p,
263
+ value: d,
263
264
  caption: `${n.total - n.retained} of ${n.total} people on record have left`,
264
- icon: /* @__PURE__ */ d(s, { className: m })
265
+ icon: /* @__PURE__ */ f(c, { className: m })
265
266
  }),
266
- /* @__PURE__ */ d(I, {
267
+ /* @__PURE__ */ f(L, {
267
268
  label: "Payroll run-rate",
268
- value: k(r),
269
- caption: `Annual salary of active employees; ${o} open role${o === 1 ? "" : "s"} not included`,
270
- icon: /* @__PURE__ */ d(i, { className: m }),
269
+ value: A(r),
270
+ caption: `Annual salary of active employees; ${i} open role${i === 1 ? "" : "s"} not included`,
271
+ icon: /* @__PURE__ */ f(a, { className: m }),
271
272
  testId: "kpi-payroll-run-rate"
272
273
  }),
273
- /* @__PURE__ */ d(I, {
274
+ /* @__PURE__ */ f(L, {
274
275
  label: "Budget utilization",
275
- value: `${u}%`,
276
- caption: `${k(t.spent)} of ${k(t.total)} project budget`,
277
- icon: /* @__PURE__ */ d(a, { className: m })
276
+ value: `${s}%`,
277
+ caption: `${A(t.spent)} of ${A(t.total)} project budget`,
278
+ icon: /* @__PURE__ */ f(o, { className: m })
278
279
  })
279
280
  ]
280
281
  });
281
282
  }
282
- var R = [
283
+ var z = [
283
284
  {
284
285
  key: "high",
285
286
  label: "High",
@@ -296,85 +297,85 @@ var R = [
296
297
  dot: "bg-status-success-text"
297
298
  }
298
299
  ];
299
- function z({ risk: e }) {
300
+ function B({ risk: e }) {
300
301
  let t = {
301
302
  high: e.highCount,
302
303
  medium: e.mediumCount,
303
304
  low: e.lowCount
304
305
  };
305
- return /* @__PURE__ */ f(h, { children: [/* @__PURE__ */ f(v, { children: [/* @__PURE__ */ d(y, { children: "Attrition risk" }), /* @__PURE__ */ d(_, { children: "Heuristic risk bands from performance, tenure, contract type and recent leave. A signal to start a conversation, not a prediction." })] }), /* @__PURE__ */ f(g, {
306
+ return /* @__PURE__ */ p(g, { children: [/* @__PURE__ */ p(y, { children: [/* @__PURE__ */ f(b, { children: "Attrition risk" }), /* @__PURE__ */ f(v, { children: "Heuristic risk bands from performance, tenure, contract type and recent leave. A signal to start a conversation, not a prediction." })] }), /* @__PURE__ */ p(_, {
306
307
  className: "space-y-4",
307
- children: [/* @__PURE__ */ d("div", {
308
+ children: [/* @__PURE__ */ f("div", {
308
309
  className: "grid gap-3 sm:grid-cols-3",
309
- children: R.map((e) => /* @__PURE__ */ f("div", {
310
+ children: z.map((e) => /* @__PURE__ */ p("div", {
310
311
  className: "flex items-center justify-between rounded border p-3",
311
312
  "data-testid": `attrition-${e.key}`,
312
- children: [/* @__PURE__ */ f("div", {
313
+ children: [/* @__PURE__ */ p("div", {
313
314
  className: "flex items-center gap-3",
314
- children: [/* @__PURE__ */ d("div", { className: `h-3 w-3 rounded-full ${e.dot}` }), /* @__PURE__ */ f("p", {
315
+ children: [/* @__PURE__ */ f("div", { className: `h-3 w-3 rounded-full ${e.dot}` }), /* @__PURE__ */ p("p", {
315
316
  className: "text-sm font-medium",
316
317
  children: [e.label, " risk"]
317
318
  })]
318
- }), /* @__PURE__ */ d("span", {
319
+ }), /* @__PURE__ */ f("span", {
319
320
  className: "text-lg font-bold tabular-nums",
320
321
  children: t[e.key]
321
322
  })]
322
323
  }, e.key))
323
- }), e.totalAssessed === 0 ? /* @__PURE__ */ d(S, {
324
+ }), e.totalAssessed === 0 ? /* @__PURE__ */ f(C, {
324
325
  illustration: "empty-data",
325
326
  title: "No active employees to assess",
326
327
  description: "Add employees to see where retention attention is needed."
327
- }) : /* @__PURE__ */ d(w, {
328
- columns: j,
328
+ }) : /* @__PURE__ */ f(T, {
329
+ columns: M,
329
330
  data: e.topRisks,
330
331
  rowKey: (e) => e.employeeId
331
332
  })]
332
333
  })] });
333
334
  }
334
- function B({ title: e, description: t, columns: n, rows: r, rowKey: i, emptyTitle: a, emptyDescription: o }) {
335
- return /* @__PURE__ */ f(h, { children: [/* @__PURE__ */ f(v, { children: [/* @__PURE__ */ d(y, { children: e }), /* @__PURE__ */ d(_, { children: t })] }), /* @__PURE__ */ d(g, { children: r.length > 0 ? /* @__PURE__ */ d(w, {
335
+ function V({ title: e, description: t, columns: n, rows: r, rowKey: i, emptyTitle: a, emptyDescription: o }) {
336
+ return /* @__PURE__ */ p(g, { children: [/* @__PURE__ */ p(y, { children: [/* @__PURE__ */ f(b, { children: e }), /* @__PURE__ */ f(v, { children: t })] }), /* @__PURE__ */ f(_, { children: r.length > 0 ? /* @__PURE__ */ f(T, {
336
337
  columns: n,
337
338
  data: r,
338
339
  rowKey: i
339
- }) : /* @__PURE__ */ d(S, {
340
+ }) : /* @__PURE__ */ f(C, {
340
341
  illustration: "empty-data",
341
342
  title: a,
342
343
  description: o
343
344
  }) })] });
344
345
  }
345
- function V({ analytics: e, budget: t, retention: n }) {
346
- let r = e.skillsGap.filter((e) => e.shortage > 0).slice(0, D);
347
- return /* @__PURE__ */ f(u, { children: [
348
- /* @__PURE__ */ d(L, {
346
+ function H({ analytics: e, budget: t, retention: n }) {
347
+ let r = e.skillsGap.filter((e) => e.shortage > 0).slice(0, O);
348
+ return /* @__PURE__ */ p(d, { children: [
349
+ /* @__PURE__ */ f(R, {
349
350
  analytics: e,
350
351
  budget: t,
351
352
  retention: n
352
353
  }),
353
- /* @__PURE__ */ d(z, { risk: e.attritionRisk }),
354
- /* @__PURE__ */ f("div", {
354
+ /* @__PURE__ */ f(B, { risk: e.attritionRisk }),
355
+ /* @__PURE__ */ p("div", {
355
356
  className: "grid gap-4 lg:grid-cols-2",
356
- children: [/* @__PURE__ */ d(B, {
357
+ children: [/* @__PURE__ */ f(V, {
357
358
  title: "Headcount plan",
358
359
  description: "Active people per department plus open (active or paused) roles.",
359
- columns: M,
360
+ columns: N,
360
361
  rows: e.headcountGap,
361
362
  rowKey: (e) => e.department,
362
363
  emptyTitle: "No headcount yet",
363
364
  emptyDescription: "Departments appear here once they have active people or open roles."
364
- }), /* @__PURE__ */ d(B, {
365
+ }), /* @__PURE__ */ f(V, {
365
366
  title: "Skills shortages",
366
367
  description: "Skills open roles ask for that more roles need than people have.",
367
- columns: N,
368
+ columns: P,
368
369
  rows: r,
369
370
  rowKey: (e) => e.skill,
370
371
  emptyTitle: "No skills shortages",
371
372
  emptyDescription: "Every skill listed on an open role is covered by at least as many active employees."
372
373
  })]
373
374
  }),
374
- /* @__PURE__ */ d(B, {
375
+ /* @__PURE__ */ f(V, {
375
376
  title: "Payroll run-rate by department",
376
377
  description: "Annualised salary of active employees",
377
- columns: P,
378
+ columns: F,
378
379
  rows: e.costProjection,
379
380
  rowKey: (e) => e.department,
380
381
  emptyTitle: "No salaried employees yet",
@@ -382,108 +383,116 @@ function V({ analytics: e, budget: t, retention: n }) {
382
383
  })
383
384
  ] });
384
385
  }
385
- function H({ departments: e }) {
386
+ function U({ departments: e }) {
386
387
  let t = e.reduce((e, t) => e + t.budget, 0), n = e.reduce((e, t) => e + t.employeeCount, 0), r = n > 0 ? t / n : 0;
387
- return /* @__PURE__ */ f(h, { children: [/* @__PURE__ */ f(v, { children: [/* @__PURE__ */ d(y, { children: "Department Budget Status" }), /* @__PURE__ */ d(_, { children: "Annual budget allocation and headcount" })] }), /* @__PURE__ */ f(g, { children: [
388
- /* @__PURE__ */ d(w, {
389
- columns: F,
388
+ return /* @__PURE__ */ p(g, { children: [/* @__PURE__ */ p(y, { children: [/* @__PURE__ */ f(b, { children: "Department Budget Status" }), /* @__PURE__ */ f(v, { children: "Annual budget allocation and headcount" })] }), /* @__PURE__ */ p(_, { children: [
389
+ /* @__PURE__ */ f(T, {
390
+ columns: I,
390
391
  data: e,
391
392
  rowKey: (e) => e.id
392
393
  }),
393
- /* @__PURE__ */ d(T, { className: "my-3" }),
394
- /* @__PURE__ */ f("div", {
394
+ /* @__PURE__ */ f(E, { className: "my-3" }),
395
+ /* @__PURE__ */ p("div", {
395
396
  className: "flex flex-wrap items-center justify-between gap-2 text-sm font-bold",
396
397
  children: [
397
- /* @__PURE__ */ d("span", { children: "Total" }),
398
- /* @__PURE__ */ f("span", { children: [n, " employees"] }),
399
- /* @__PURE__ */ f("span", { children: [k(t), " budget"] }),
400
- /* @__PURE__ */ f("span", { children: [k(r), " / employee"] })
398
+ /* @__PURE__ */ f("span", { children: "Total" }),
399
+ /* @__PURE__ */ p("span", { children: [n, " employees"] }),
400
+ /* @__PURE__ */ p("span", { children: [A(t), " budget"] }),
401
+ /* @__PURE__ */ p("span", { children: [A(r), " / employee"] })
401
402
  ]
402
403
  })
403
404
  ] })] });
404
405
  }
405
- function U() {
406
- let i = e((e) => e.initialized), a = e((e) => e.initParams.workspaceId), s = e((e) => e.departments), c = e((e) => e.projects), l = e((e) => e.employees), u = e((e) => e.executiveDashboard), _ = e((e) => e.executiveDashboardLoading), v = e((e) => e.executiveDashboardError), y = e((e) => e.fetchExecutiveDashboard), b = t(() => {
407
- y();
408
- }, [y]);
409
- n(() => {
410
- !i || !a || b();
406
+ function W() {
407
+ let a = e((e) => e.initialized), o = e((e) => e.initParams.workspaceId), c = e((e) => e.departments), l = e((e) => e.projects), u = e((e) => e.employees), d = e((e) => e.executiveDashboard), v = e((e) => e.executiveDashboardLoading), y = e((e) => e.executiveDashboardError), b = e((e) => e.fetchExecutiveDashboard), x = e((e) => e.workforceForecast), C = e((e) => e.workforceForecastLoading), T = e((e) => e.workforceForecastError), E = e((e) => e.fetchWorkforceForecast), O = n(() => {
408
+ E();
409
+ }, [E]), k = n(() => {
410
+ b(), O();
411
+ }, [b, O]);
412
+ r(() => {
413
+ !a || !o || k();
411
414
  }, [
412
- i,
413
415
  a,
414
- b
416
+ o,
417
+ k
415
418
  ]);
416
- let S = r(() => ({
417
- spent: c.reduce((e, t) => e + t.spent, 0),
418
- total: c.reduce((e, t) => e + t.budget, 0)
419
- }), [c]), w = r(() => ({
420
- retained: l.filter((e) => e.status !== "terminated").length,
421
- total: l.length
422
- }), [l]);
423
- return i ? /* @__PURE__ */ f("div", {
419
+ let A = i(() => ({
420
+ spent: l.reduce((e, t) => e + t.spent, 0),
421
+ total: l.reduce((e, t) => e + t.budget, 0)
422
+ }), [l]), M = i(() => ({
423
+ retained: u.filter((e) => e.status !== "terminated").length,
424
+ total: u.length
425
+ }), [u]);
426
+ return a ? /* @__PURE__ */ p("div", {
424
427
  className: "space-y-6 p-6",
425
428
  children: [
426
- /* @__PURE__ */ f("div", {
429
+ /* @__PURE__ */ p("div", {
427
430
  className: "flex flex-wrap items-start justify-between gap-3",
428
- children: [/* @__PURE__ */ f("div", { children: [
429
- /* @__PURE__ */ d("h1", {
431
+ children: [/* @__PURE__ */ p("div", { children: [
432
+ /* @__PURE__ */ f("h1", {
430
433
  className: "text-2xl font-semibold",
431
- children: /* @__PURE__ */ d(x, { children: "Executive Dashboard" })
434
+ children: /* @__PURE__ */ f(S, { children: "Executive Dashboard" })
432
435
  }),
433
- /* @__PURE__ */ d("p", {
436
+ /* @__PURE__ */ f("p", {
434
437
  className: "text-sm text-text-secondary",
435
438
  children: "Strategic workforce insights for leadership"
436
439
  }),
437
- /* @__PURE__ */ d(C, {
440
+ /* @__PURE__ */ f(w, {
438
441
  className: "mt-1",
439
442
  children: "The executive snapshot — headcount, attrition risk, hiring plan, skills shortages and payroll run-rate in one view, computed from your workspace's own records."
440
443
  })
441
- ] }), /* @__PURE__ */ f("div", {
444
+ ] }), /* @__PURE__ */ p("div", {
442
445
  className: "flex items-center gap-2",
443
- children: [u ? /* @__PURE__ */ f(p, {
446
+ children: [d ? /* @__PURE__ */ p(m, {
444
447
  variant: "outline",
445
- children: ["Updated ", A(u.generatedAt)]
446
- }) : null, /* @__PURE__ */ f(m, {
448
+ children: ["Updated ", j(d.generatedAt)]
449
+ }) : null, /* @__PURE__ */ p(h, {
447
450
  variant: "outline",
448
451
  size: "sm",
449
- onClick: b,
450
- disabled: _,
452
+ onClick: k,
453
+ disabled: v || C,
451
454
  "aria-label": "Refresh workforce analytics",
452
- children: [/* @__PURE__ */ d(o, { className: `mr-2 h-4 w-4 ${_ ? "animate-spin" : ""}` }), "Refresh"]
455
+ children: [/* @__PURE__ */ f(s, { className: `mr-2 h-4 w-4 ${v || C ? "animate-spin" : ""}` }), "Refresh"]
453
456
  })]
454
457
  })]
455
458
  }),
456
- v ? /* @__PURE__ */ d(h, {
459
+ y ? /* @__PURE__ */ f(g, {
457
460
  className: "border-status-error-border",
458
- children: /* @__PURE__ */ f(g, {
461
+ children: /* @__PURE__ */ p(_, {
459
462
  className: "flex flex-wrap items-center justify-between gap-3 py-4",
460
- children: [/* @__PURE__ */ d("p", {
463
+ children: [/* @__PURE__ */ f("p", {
461
464
  className: "text-sm text-status-error-text",
462
- children: v
463
- }), /* @__PURE__ */ d(m, {
465
+ children: y
466
+ }), /* @__PURE__ */ f(h, {
464
467
  variant: "outline",
465
468
  size: "sm",
466
- onClick: b,
469
+ onClick: k,
467
470
  children: "Try again"
468
471
  })]
469
472
  })
470
473
  }) : null,
471
- u ? /* @__PURE__ */ d(V, {
472
- analytics: u,
473
- budget: S,
474
- retention: w
475
- }) : _ ? /* @__PURE__ */ d("div", {
474
+ d ? /* @__PURE__ */ f(H, {
475
+ analytics: d,
476
+ budget: A,
477
+ retention: M
478
+ }) : v ? /* @__PURE__ */ f("div", {
476
479
  className: "flex min-h-[12rem] items-center justify-center",
477
- children: /* @__PURE__ */ d(E, { size: "md" })
480
+ children: /* @__PURE__ */ f(D, { size: "md" })
478
481
  }) : null,
479
- /* @__PURE__ */ d(H, { departments: s })
482
+ /* @__PURE__ */ f(t, {
483
+ forecast: x,
484
+ loading: C,
485
+ error: T,
486
+ onRetry: O
487
+ }),
488
+ /* @__PURE__ */ f(U, { departments: c })
480
489
  ]
481
- }) : /* @__PURE__ */ d("div", {
490
+ }) : /* @__PURE__ */ f("div", {
482
491
  className: "flex min-h-[60vh] items-center justify-center p-6",
483
- children: /* @__PURE__ */ d(E, { size: "lg" })
492
+ children: /* @__PURE__ */ f(D, { size: "lg" })
484
493
  });
485
494
  }
486
495
  //#endregion
487
- export { U as DashboardExecutiveDashboardPage };
496
+ export { W as DashboardExecutiveDashboardPage };
488
497
 
489
498
  //# sourceMappingURL=DashboardExecutiveDashboardPage.js.map