@burdenoff/microfe-crewfoundry 2026.626.1 → 2026.703.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/crewfoundry/components/forms/ConfirmDialog.js +43 -0
  2. package/dist/crewfoundry/components/forms/ConfirmDialog.js.map +1 -0
  3. package/dist/crewfoundry/components/forms/FormModal.js +220 -0
  4. package/dist/crewfoundry/components/forms/FormModal.js.map +1 -0
  5. package/dist/crewfoundry/components/forms/formValues.js +20 -0
  6. package/dist/crewfoundry/components/forms/formValues.js.map +1 -0
  7. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +255 -65
  8. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
  9. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +28 -17
  10. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +1 -1
  11. package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js +57 -53
  12. package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js.map +1 -1
  13. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +32 -23
  14. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
  15. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +44 -29
  16. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +1 -1
  17. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +183 -57
  18. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
  19. package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js.map +1 -1
  20. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +214 -92
  21. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
  22. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +165 -131
  23. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
  24. package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +163 -133
  25. package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
  26. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +269 -54
  27. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
  28. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +225 -78
  29. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
  30. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +213 -59
  31. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
  32. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +287 -90
  33. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
  34. package/dist/crewfoundry/pages/HiringJobsPagePage.js +49 -47
  35. package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
  36. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +166 -59
  37. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
  38. package/dist/crewfoundry/pages/HrEmployeesPagePage.js +274 -83
  39. package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
  40. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +198 -88
  41. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
  42. package/dist/crewfoundry/pages/HrPayrollPagePage.js +216 -88
  43. package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
  44. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +216 -66
  45. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
  46. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +6 -7
  47. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
  48. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +83 -68
  49. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
  50. package/dist/crewfoundry/pages/LearningCoursesPagePage.js +167 -46
  51. package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
  52. package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
  53. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +75 -55
  54. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
  55. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +152 -79
  56. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
  57. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +75 -63
  58. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
  59. package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +3 -1
  60. package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
  61. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
  62. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +235 -87
  63. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
  64. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +199 -86
  65. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
  66. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
  67. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js +21 -40
  68. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js.map +1 -1
  69. package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +117 -45
  70. package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
  71. package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +249 -90
  72. package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
  73. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +47 -45
  74. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
  75. package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
  76. package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +262 -133
  77. package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
  78. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +144 -77
  79. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
  80. package/dist/crewfoundry/store/crewfoundryStore.js +306 -51
  81. package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
  82. package/package.json +1 -1
@@ -1,197 +1,211 @@
1
- import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
- import { useState as t } from "react";
3
- import { Activity as n, Briefcase as r, Calendar as i, TrendingUp as a, Users as o } from "lucide-react";
4
- import { useNavigate as s } from "react-router-dom";
5
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
6
- import { AuroraBackground as u, Badge as d, Button as f, Card as p, CardContent as m, CardDescription as h, CardHeader as g, CardTitle as _, EmphasisPanel as v, GlassCard as y, GradientText as b, IllustratedEmptyState as x, NextSteps as S, PagePurpose as C } from "@burdenoff/fe-libs/ui";
7
- import { useI18n as w } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
1
+ import { useCrewFoundry as e } from "../providers/CrewFoundryProvider.js";
2
+ import { useCrewFoundryStore as t } from "../store/crewfoundryStore.js";
3
+ import { useState as n } from "react";
4
+ import { Activity as r, Briefcase as i, Calendar as a, TrendingUp as o, Users as s } from "lucide-react";
5
+ import { useNavigate as c } from "react-router-dom";
6
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
7
+ import { AuroraBackground as d, Badge as f, Button as p, Card as m, CardContent as h, CardDescription as g, CardHeader as _, CardTitle as v, EmphasisPanel as y, GlassCard as b, GradientText as x, IllustratedEmptyState as S, NextSteps as C, PagePurpose as w } from "@burdenoff/fe-libs/ui";
8
+ import { useGlobalUi as T } from "@burdenoff/fe-libs/shared/providers/shell";
9
+ import { useI18n as E } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
8
10
  //#region src/crewfoundry/pages/DashboardDashboardPagePage.tsx
9
- function T() {
10
- let { t: T } = w(), E = s(), { employees: D, jobPostings: O, leaveRequests: k, notifications: A, projects: j } = e(), [M, N] = t("month"), P = (e, t) => {
11
- let n = T(e);
11
+ function D() {
12
+ let { t: D } = E(), O = c(), { showToast: k } = T(), { currentUser: A } = e(), { employees: j, jobPostings: M, leaveRequests: N, notifications: P, projects: F, updateLeaveRequest: I } = t(), [L, R] = n("month"), [z, B] = n(null), V = A?.name || [A?.firstName, A?.lastName].filter(Boolean).join(" ") || A?.email || "Manager", H = async (e, t) => {
13
+ B(e);
14
+ try {
15
+ await I(e, {
16
+ status: t,
17
+ approverName: V
18
+ }), k(t === "approved" ? "Leave approved" : "Leave rejected", "success");
19
+ } catch (e) {
20
+ k(e instanceof Error ? e.message : "Unable to update leave request", "error");
21
+ } finally {
22
+ B(null);
23
+ }
24
+ }, U = (e, t) => {
25
+ let n = D(e);
12
26
  return n === e ? t : n;
13
- }, F = D.filter((e) => e.status === "active").length, I = D.filter((e) => e.status === "on_leave").length, L = O.filter((e) => e.status === "active").length, R = O.reduce((e, t) => e + t.applicants, 0), z = k.filter((e) => e.status === "pending").length, B = A.filter((e) => !e.read).length, V = j.filter((e) => e.status === "active").length, H = (D.reduce((e, t) => e + t.performanceScore, 0) / D.length).toFixed(1), U = D.reduce((e, t) => (e[t.department] = (e[t.department] || 0) + 1, e), {}), W = Math.max(...Object.values(U));
14
- return /* @__PURE__ */ l("div", {
27
+ }, W = j.filter((e) => e.status === "active").length, G = j.filter((e) => e.status === "on_leave").length, K = M.filter((e) => e.status === "active").length, q = M.reduce((e, t) => e + t.applicants, 0), J = N.filter((e) => e.status === "pending").length, Y = P.filter((e) => !e.read).length, X = F.filter((e) => e.status === "active").length, Z = (j.reduce((e, t) => e + t.performanceScore, 0) / j.length).toFixed(1), Q = j.reduce((e, t) => (e[t.department] = (e[t.department] || 0) + 1, e), {}), $ = Math.max(...Object.values(Q));
28
+ return /* @__PURE__ */ u("div", {
15
29
  className: "space-y-6 p-6",
16
30
  children: [
17
- /* @__PURE__ */ l("div", {
31
+ /* @__PURE__ */ u("div", {
18
32
  className: "relative overflow-hidden rounded-xl border border-border-seam bg-gloss-card p-6",
19
- children: [/* @__PURE__ */ c(u, { intensity: "subtle" }), /* @__PURE__ */ l("div", {
33
+ children: [/* @__PURE__ */ l(d, { intensity: "subtle" }), /* @__PURE__ */ u("div", {
20
34
  className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
21
- children: [/* @__PURE__ */ l("div", { children: [
22
- /* @__PURE__ */ c("h1", {
35
+ children: [/* @__PURE__ */ u("div", { children: [
36
+ /* @__PURE__ */ l("h1", {
23
37
  className: "text-2xl font-semibold",
24
- children: /* @__PURE__ */ c(b, { children: P("crewfoundry.dashboard.title", "Workforce Dashboard") })
38
+ children: /* @__PURE__ */ l(x, { children: U("crewfoundry.dashboard.title", "Workforce Dashboard") })
25
39
  }),
26
- /* @__PURE__ */ c("p", {
40
+ /* @__PURE__ */ l("p", {
27
41
  className: "text-sm text-text-secondary",
28
- children: P("crewfoundry.dashboard.subtitle", "Overview of your organization's workforce metrics")
42
+ children: U("crewfoundry.dashboard.subtitle", "Overview of your organization's workforce metrics")
29
43
  }),
30
- /* @__PURE__ */ c(C, {
44
+ /* @__PURE__ */ l(w, {
31
45
  className: "mt-2",
32
- children: P("crewfoundry.dashboard.purpose", "Your workforce command center — see headcount, hiring, performance, and projects at a glance, then jump straight to the area that needs your attention.")
46
+ children: U("crewfoundry.dashboard.purpose", "Your workforce command center — see headcount, hiring, performance, and projects at a glance, then jump straight to the area that needs your attention.")
33
47
  })
34
- ] }), /* @__PURE__ */ c("div", {
48
+ ] }), /* @__PURE__ */ l("div", {
35
49
  className: "flex gap-2",
36
50
  children: [
37
51
  "week",
38
52
  "month",
39
53
  "quarter"
40
- ].map((e) => /* @__PURE__ */ c(f, {
41
- variant: M === e ? "default" : "outline",
54
+ ].map((e) => /* @__PURE__ */ l(p, {
55
+ variant: L === e ? "default" : "outline",
42
56
  size: "sm",
43
- onClick: () => N(e),
44
- children: P(`crewfoundry.dashboard.period.${e}`, e.charAt(0).toUpperCase() + e.slice(1))
57
+ onClick: () => R(e),
58
+ children: U(`crewfoundry.dashboard.period.${e}`, e.charAt(0).toUpperCase() + e.slice(1))
45
59
  }, e))
46
60
  })]
47
61
  })]
48
62
  }),
49
- /* @__PURE__ */ c(S, {
63
+ /* @__PURE__ */ l(C, {
50
64
  storageKey: "crewfoundry-dashboard",
51
65
  steps: [
52
66
  {
53
67
  id: "employees",
54
- label: P("crewfoundry.dashboard.next.employees", "Review your team"),
55
- description: P("crewfoundry.dashboard.next.employeesDesc", "Open the employee directory to see who is active and on leave."),
56
- icon: /* @__PURE__ */ c(o, { className: "h-4 w-4" }),
57
- onClick: () => E("../../hr/employees-page")
68
+ label: U("crewfoundry.dashboard.next.employees", "Review your team"),
69
+ description: U("crewfoundry.dashboard.next.employeesDesc", "Open the employee directory to see who is active and on leave."),
70
+ icon: /* @__PURE__ */ l(s, { className: "h-4 w-4" }),
71
+ onClick: () => O("../../hr/employees-page")
58
72
  },
59
73
  {
60
74
  id: "hiring",
61
- label: P("crewfoundry.dashboard.next.hiring", "Post a new job"),
62
- description: P("crewfoundry.dashboard.next.hiringDesc", "Create an opening to start collecting applicants."),
63
- icon: /* @__PURE__ */ c(r, { className: "h-4 w-4" }),
64
- onClick: () => E("../../hiring/create-job-page")
75
+ label: U("crewfoundry.dashboard.next.hiring", "Post a new job"),
76
+ description: U("crewfoundry.dashboard.next.hiringDesc", "Create an opening to start collecting applicants."),
77
+ icon: /* @__PURE__ */ l(i, { className: "h-4 w-4" }),
78
+ onClick: () => O("../../hiring/create-job-page")
65
79
  },
66
80
  {
67
81
  id: "projects",
68
- label: P("crewfoundry.dashboard.next.projects", "Check active projects"),
69
- description: P("crewfoundry.dashboard.next.projectsDesc", "Track progress and budgets across in-flight work."),
70
- icon: /* @__PURE__ */ c(n, { className: "h-4 w-4" }),
71
- onClick: () => E("../../projects/projects-page")
82
+ label: U("crewfoundry.dashboard.next.projects", "Check active projects"),
83
+ description: U("crewfoundry.dashboard.next.projectsDesc", "Track progress and budgets across in-flight work."),
84
+ icon: /* @__PURE__ */ l(r, { className: "h-4 w-4" }),
85
+ onClick: () => O("../../projects/projects-page")
72
86
  }
73
87
  ]
74
88
  }),
75
- /* @__PURE__ */ l("div", {
89
+ /* @__PURE__ */ u("div", {
76
90
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
77
91
  children: [
78
- /* @__PURE__ */ l(y, {
92
+ /* @__PURE__ */ u(b, {
79
93
  treatment: "glass",
80
94
  glow: !0,
81
95
  className: "border-border-seam",
82
- children: [/* @__PURE__ */ l(g, {
96
+ children: [/* @__PURE__ */ u(_, {
83
97
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
84
- children: [/* @__PURE__ */ c(_, {
98
+ children: [/* @__PURE__ */ l(v, {
85
99
  className: "text-sm font-medium",
86
- children: P("crewfoundry.dashboard.stats.totalEmployees", "Total Employees")
87
- }), /* @__PURE__ */ c(o, { className: "h-4 w-4 text-text-secondary" })]
88
- }), /* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c("div", {
100
+ children: U("crewfoundry.dashboard.stats.totalEmployees", "Total Employees")
101
+ }), /* @__PURE__ */ l(s, { className: "h-4 w-4 text-text-secondary" })]
102
+ }), /* @__PURE__ */ u(h, { children: [/* @__PURE__ */ l("div", {
89
103
  className: "text-2xl font-bold tabular-nums",
90
- children: D.length
91
- }), /* @__PURE__ */ l("p", {
104
+ children: j.length
105
+ }), /* @__PURE__ */ u("p", {
92
106
  className: "text-xs text-text-secondary",
93
107
  children: [
94
- F,
108
+ W,
95
109
  " ",
96
- P("crewfoundry.dashboard.stats.active", "active"),
110
+ U("crewfoundry.dashboard.stats.active", "active"),
97
111
  ", ",
98
- I,
112
+ G,
99
113
  " ",
100
- P("crewfoundry.dashboard.stats.onLeave", "on leave")
114
+ U("crewfoundry.dashboard.stats.onLeave", "on leave")
101
115
  ]
102
116
  })] })]
103
117
  }),
104
- /* @__PURE__ */ l(y, {
118
+ /* @__PURE__ */ u(b, {
105
119
  treatment: "metric",
106
120
  className: "border-border-seam",
107
- children: [/* @__PURE__ */ l(g, {
121
+ children: [/* @__PURE__ */ u(_, {
108
122
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
109
- children: [/* @__PURE__ */ c(_, {
123
+ children: [/* @__PURE__ */ l(v, {
110
124
  className: "text-sm font-medium",
111
- children: P("crewfoundry.dashboard.stats.openPositions", "Open Positions")
112
- }), /* @__PURE__ */ c(r, { className: "h-4 w-4 text-text-secondary" })]
113
- }), /* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c("div", {
125
+ children: U("crewfoundry.dashboard.stats.openPositions", "Open Positions")
126
+ }), /* @__PURE__ */ l(i, { className: "h-4 w-4 text-text-secondary" })]
127
+ }), /* @__PURE__ */ u(h, { children: [/* @__PURE__ */ l("div", {
114
128
  className: "text-2xl font-bold tabular-nums",
115
- children: L
116
- }), /* @__PURE__ */ l("p", {
129
+ children: K
130
+ }), /* @__PURE__ */ u("p", {
117
131
  className: "text-xs text-text-secondary",
118
132
  children: [
119
- R,
133
+ q,
120
134
  " ",
121
- P("crewfoundry.dashboard.stats.totalApplicants", "total applicants")
135
+ U("crewfoundry.dashboard.stats.totalApplicants", "total applicants")
122
136
  ]
123
137
  })] })]
124
138
  }),
125
- /* @__PURE__ */ l(y, {
139
+ /* @__PURE__ */ u(b, {
126
140
  treatment: "metric",
127
141
  className: "border-border-seam",
128
- children: [/* @__PURE__ */ l(g, {
142
+ children: [/* @__PURE__ */ u(_, {
129
143
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
130
- children: [/* @__PURE__ */ c(_, {
144
+ children: [/* @__PURE__ */ l(v, {
131
145
  className: "text-sm font-medium",
132
- children: P("crewfoundry.dashboard.stats.avgPerformance", "Avg Performance")
133
- }), /* @__PURE__ */ c(a, { className: "h-4 w-4 text-text-secondary" })]
134
- }), /* @__PURE__ */ l(m, { children: [/* @__PURE__ */ l("div", {
146
+ children: U("crewfoundry.dashboard.stats.avgPerformance", "Avg Performance")
147
+ }), /* @__PURE__ */ l(o, { className: "h-4 w-4 text-text-secondary" })]
148
+ }), /* @__PURE__ */ u(h, { children: [/* @__PURE__ */ u("div", {
135
149
  className: "text-2xl font-bold tabular-nums",
136
- children: [H, "/5"]
137
- }), /* @__PURE__ */ c("p", {
150
+ children: [Z, "/5"]
151
+ }), /* @__PURE__ */ l("p", {
138
152
  className: "text-xs text-text-secondary",
139
- children: P("crewfoundry.dashboard.stats.performanceTrend", "+0.2 from last quarter")
153
+ children: U("crewfoundry.dashboard.stats.performanceTrend", "+0.2 from last quarter")
140
154
  })] })]
141
155
  }),
142
- /* @__PURE__ */ l(y, {
156
+ /* @__PURE__ */ u(b, {
143
157
  treatment: "metric",
144
158
  className: "border-border-seam",
145
- children: [/* @__PURE__ */ l(g, {
159
+ children: [/* @__PURE__ */ u(_, {
146
160
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
147
- children: [/* @__PURE__ */ c(_, {
161
+ children: [/* @__PURE__ */ l(v, {
148
162
  className: "text-sm font-medium",
149
- children: P("crewfoundry.dashboard.stats.activeProjects", "Active Projects")
150
- }), /* @__PURE__ */ c(n, { className: "h-4 w-4 text-text-secondary" })]
151
- }), /* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c("div", {
163
+ children: U("crewfoundry.dashboard.stats.activeProjects", "Active Projects")
164
+ }), /* @__PURE__ */ l(r, { className: "h-4 w-4 text-text-secondary" })]
165
+ }), /* @__PURE__ */ u(h, { children: [/* @__PURE__ */ l("div", {
152
166
  className: "text-2xl font-bold tabular-nums",
153
- children: V
154
- }), /* @__PURE__ */ l("p", {
167
+ children: X
168
+ }), /* @__PURE__ */ u("p", {
155
169
  className: "text-xs text-text-secondary",
156
170
  children: [
157
- z,
171
+ J,
158
172
  " ",
159
- P("crewfoundry.dashboard.stats.pendingLeaveRequests", "pending leave requests")
173
+ U("crewfoundry.dashboard.stats.pendingLeaveRequests", "pending leave requests")
160
174
  ]
161
175
  })] })]
162
176
  })
163
177
  ]
164
178
  }),
165
- /* @__PURE__ */ l("div", {
179
+ /* @__PURE__ */ u("div", {
166
180
  className: "grid gap-4 md:grid-cols-7",
167
- children: [/* @__PURE__ */ l(v, {
181
+ children: [/* @__PURE__ */ u(y, {
168
182
  className: "col-span-4",
169
183
  children: [
170
- /* @__PURE__ */ c("div", {
184
+ /* @__PURE__ */ l("div", {
171
185
  className: "mb-1 text-lg font-semibold",
172
- children: P("crewfoundry.dashboard.departmentHeadcount.title", "Department Headcount")
186
+ children: U("crewfoundry.dashboard.departmentHeadcount.title", "Department Headcount")
173
187
  }),
174
- /* @__PURE__ */ c("p", {
188
+ /* @__PURE__ */ l("p", {
175
189
  className: "mb-4 text-sm text-text-secondary",
176
- children: P("crewfoundry.dashboard.departmentHeadcount.description", "Employee distribution across departments")
190
+ children: U("crewfoundry.dashboard.departmentHeadcount.description", "Employee distribution across departments")
177
191
  }),
178
- /* @__PURE__ */ c("div", {
192
+ /* @__PURE__ */ l("div", {
179
193
  className: "space-y-3",
180
- children: Object.entries(U).sort(([, e], [, t]) => t - e).map(([e, t]) => /* @__PURE__ */ l("div", {
194
+ children: Object.entries(Q).sort(([, e], [, t]) => t - e).map(([e, t]) => /* @__PURE__ */ u("div", {
181
195
  className: "flex items-center gap-3",
182
196
  children: [
183
- /* @__PURE__ */ c("span", {
197
+ /* @__PURE__ */ l("span", {
184
198
  className: "w-24 text-sm text-text-secondary truncate",
185
199
  children: e
186
200
  }),
187
- /* @__PURE__ */ c("div", {
201
+ /* @__PURE__ */ l("div", {
188
202
  className: "flex-1 h-4 bg-bg-sunken rounded overflow-hidden",
189
- children: /* @__PURE__ */ c("div", {
203
+ children: /* @__PURE__ */ l("div", {
190
204
  className: "h-4 bg-action-primary-bg rounded",
191
- style: { width: `${Math.round(t / W * 100)}%` }
205
+ style: { width: `${Math.round(t / $ * 100)}%` }
192
206
  })
193
207
  }),
194
- /* @__PURE__ */ c("span", {
208
+ /* @__PURE__ */ l("span", {
195
209
  className: "text-sm font-medium w-8 text-right tabular-nums",
196
210
  children: t
197
211
  })
@@ -199,28 +213,28 @@ function T() {
199
213
  }, e))
200
214
  })
201
215
  ]
202
- }), /* @__PURE__ */ l(p, {
216
+ }), /* @__PURE__ */ u(m, {
203
217
  className: "col-span-3",
204
- children: [/* @__PURE__ */ l(g, {
218
+ children: [/* @__PURE__ */ u(_, {
205
219
  className: "flex flex-row items-center justify-between",
206
- children: [/* @__PURE__ */ c(_, { children: P("crewfoundry.dashboard.notifications.title", "Recent Notifications") }), /* @__PURE__ */ l(d, {
220
+ children: [/* @__PURE__ */ l(v, { children: U("crewfoundry.dashboard.notifications.title", "Recent Notifications") }), /* @__PURE__ */ u(f, {
207
221
  variant: "secondary",
208
222
  children: [
209
- B,
223
+ Y,
210
224
  " ",
211
- P("crewfoundry.dashboard.notifications.unread", "unread")
225
+ U("crewfoundry.dashboard.notifications.unread", "unread")
212
226
  ]
213
227
  })]
214
- }), /* @__PURE__ */ c(m, {
228
+ }), /* @__PURE__ */ l(h, {
215
229
  className: "space-y-4",
216
- children: A.slice(0, 5).map((e) => /* @__PURE__ */ l("div", {
230
+ children: P.slice(0, 5).map((e) => /* @__PURE__ */ u("div", {
217
231
  className: "flex items-start gap-3",
218
- children: [/* @__PURE__ */ c("div", { className: `mt-1 h-2 w-2 rounded-full flex-shrink-0 motion-safe:animate-vc-glow-pulse ${e.type === "success" ? "bg-status-success-text" : e.type === "warning" ? "bg-status-warning-text" : e.type === "error" ? "bg-status-error-text" : "bg-status-info-text"}` }), /* @__PURE__ */ l("div", {
232
+ children: [/* @__PURE__ */ l("div", { className: `mt-1 h-2 w-2 rounded-full flex-shrink-0 motion-safe:animate-vc-glow-pulse ${e.type === "success" ? "bg-status-success-text" : e.type === "warning" ? "bg-status-warning-text" : e.type === "error" ? "bg-status-error-text" : "bg-status-info-text"}` }), /* @__PURE__ */ u("div", {
219
233
  className: "flex-1 min-w-0",
220
- children: [/* @__PURE__ */ c("p", {
234
+ children: [/* @__PURE__ */ l("p", {
221
235
  className: `text-sm ${e.read ? "text-text-secondary" : "font-medium"}`,
222
236
  children: e.title
223
- }), /* @__PURE__ */ c("p", {
237
+ }), /* @__PURE__ */ l("p", {
224
238
  className: "text-xs text-text-secondary truncate",
225
239
  children: e.message
226
240
  })]
@@ -229,62 +243,82 @@ function T() {
229
243
  })]
230
244
  })]
231
245
  }),
232
- /* @__PURE__ */ l("div", {
246
+ /* @__PURE__ */ u("div", {
233
247
  className: "grid gap-4 md:grid-cols-2",
234
- children: [/* @__PURE__ */ l(p, { children: [/* @__PURE__ */ l(g, { children: [/* @__PURE__ */ c(_, { children: P("crewfoundry.dashboard.upcomingInterviews.title", "Upcoming Interviews") }), /* @__PURE__ */ c(h, { children: P("crewfoundry.dashboard.upcomingInterviews.description", "Scheduled for this week") })] }), /* @__PURE__ */ c(m, {
248
+ children: [/* @__PURE__ */ u(m, { children: [/* @__PURE__ */ u(_, { children: [/* @__PURE__ */ l(v, { children: U("crewfoundry.dashboard.upcomingInterviews.title", "Upcoming Interviews") }), /* @__PURE__ */ l(g, { children: U("crewfoundry.dashboard.upcomingInterviews.description", "Scheduled for this week") })] }), /* @__PURE__ */ l(h, {
235
249
  className: "space-y-3",
236
- children: j.filter((e) => e.status === "active").slice(0, 4).map((e) => /* @__PURE__ */ l("div", {
250
+ children: F.filter((e) => e.status === "active").slice(0, 4).map((e) => /* @__PURE__ */ u("div", {
237
251
  className: "flex items-center justify-between rounded border p-3",
238
- children: [/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("p", {
252
+ children: [/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("p", {
239
253
  className: "text-sm font-medium",
240
254
  children: e.name
241
- }), /* @__PURE__ */ c("p", {
255
+ }), /* @__PURE__ */ l("p", {
242
256
  className: "text-xs text-text-secondary",
243
257
  children: e.teamName
244
- })] }), /* @__PURE__ */ l("div", {
258
+ })] }), /* @__PURE__ */ u("div", {
245
259
  className: "flex items-center gap-2",
246
- children: [/* @__PURE__ */ c("div", {
260
+ children: [/* @__PURE__ */ l("div", {
247
261
  className: "w-24 h-2 bg-bg-sunken rounded overflow-hidden",
248
- children: /* @__PURE__ */ c("div", {
262
+ children: /* @__PURE__ */ l("div", {
249
263
  className: "h-2 bg-action-primary-bg rounded",
250
264
  style: { width: `${e.progress}%` }
251
265
  })
252
- }), /* @__PURE__ */ l("span", {
266
+ }), /* @__PURE__ */ u("span", {
253
267
  className: "text-xs text-text-secondary",
254
268
  children: [e.progress, "%"]
255
269
  })]
256
270
  })]
257
271
  }, e.id))
258
- })] }), /* @__PURE__ */ l(p, { children: [/* @__PURE__ */ l(g, { children: [/* @__PURE__ */ c(_, { children: P("crewfoundry.dashboard.leaveRequests.title", "Recent Leave Requests") }), /* @__PURE__ */ c(h, { children: P("crewfoundry.dashboard.leaveRequests.description", "Pending approval") })] }), /* @__PURE__ */ l(m, {
272
+ })] }), /* @__PURE__ */ u(m, { children: [/* @__PURE__ */ u(_, { children: [/* @__PURE__ */ l(v, { children: U("crewfoundry.dashboard.leaveRequests.title", "Recent Leave Requests") }), /* @__PURE__ */ l(g, { children: U("crewfoundry.dashboard.leaveRequests.description", "Pending approval") })] }), /* @__PURE__ */ u(h, {
259
273
  className: "space-y-3",
260
- children: [k.length === 0 && /* @__PURE__ */ c(x, {
274
+ children: [N.length === 0 && /* @__PURE__ */ l(S, {
261
275
  illustration: "empty-data",
262
- title: P("crewfoundry.dashboard.leaveRequests.emptyTitle", "No leave requests"),
263
- description: P("crewfoundry.dashboard.leaveRequests.emptyDescription", "Pending leave requests will appear here.")
264
- }), k.map((e) => /* @__PURE__ */ l("div", {
276
+ title: U("crewfoundry.dashboard.leaveRequests.emptyTitle", "No leave requests"),
277
+ description: U("crewfoundry.dashboard.leaveRequests.emptyDescription", "Pending leave requests will appear here.")
278
+ }), N.map((e) => /* @__PURE__ */ u("div", {
265
279
  className: "flex items-center justify-between rounded border p-3",
266
- children: [/* @__PURE__ */ c("div", {
280
+ children: [/* @__PURE__ */ l("div", {
267
281
  className: "flex items-center gap-3",
268
- children: /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("p", {
282
+ children: /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("p", {
269
283
  className: "text-sm font-medium",
270
284
  children: e.employeeName
271
- }), /* @__PURE__ */ l("div", {
285
+ }), /* @__PURE__ */ u("div", {
272
286
  className: "flex items-center gap-2 text-xs text-text-secondary",
273
- children: [/* @__PURE__ */ c(i, { className: "h-3 w-3" }), /* @__PURE__ */ l("span", { children: [
287
+ children: [/* @__PURE__ */ l(a, { className: "h-3 w-3" }), /* @__PURE__ */ u("span", { children: [
274
288
  e.startDate,
275
289
  " - ",
276
290
  e.endDate
277
291
  ] })]
278
292
  })] })
279
- }), /* @__PURE__ */ l("div", {
293
+ }), /* @__PURE__ */ u("div", {
280
294
  className: "flex items-center gap-2",
281
- children: [/* @__PURE__ */ c(d, {
282
- variant: e.status === "approved" ? "default" : e.status === "pending" ? "secondary" : "destructive",
283
- children: e.status
284
- }), /* @__PURE__ */ c(d, {
285
- variant: "outline",
286
- children: e.type
287
- })]
295
+ children: [
296
+ e.status === "pending" && /* @__PURE__ */ u("div", {
297
+ className: "flex gap-1",
298
+ children: [/* @__PURE__ */ l(p, {
299
+ size: "sm",
300
+ variant: "outline",
301
+ className: "h-7 text-xs",
302
+ disabled: z === e.id,
303
+ onClick: () => void H(e.id, "rejected"),
304
+ children: U("crewfoundry.dashboard.leaveRequests.reject", "Reject")
305
+ }), /* @__PURE__ */ l(p, {
306
+ size: "sm",
307
+ className: "h-7 text-xs",
308
+ disabled: z === e.id,
309
+ onClick: () => void H(e.id, "approved"),
310
+ children: U("crewfoundry.dashboard.leaveRequests.approve", "Approve")
311
+ })]
312
+ }),
313
+ /* @__PURE__ */ l(f, {
314
+ variant: e.status === "approved" ? "default" : e.status === "pending" ? "secondary" : "destructive",
315
+ children: e.status
316
+ }),
317
+ /* @__PURE__ */ l(f, {
318
+ variant: "outline",
319
+ children: e.type
320
+ })
321
+ ]
288
322
  })]
289
323
  }, e.id))]
290
324
  })] })]
@@ -293,6 +327,6 @@ function T() {
293
327
  });
294
328
  }
295
329
  //#endregion
296
- export { T as DashboardDashboardPagePage };
330
+ export { D as DashboardDashboardPagePage };
297
331
 
298
332
  //# sourceMappingURL=DashboardDashboardPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardDashboardPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/DashboardDashboardPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n AuroraBackground,\n EmphasisPanel,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Activity,\n ArrowUpRight,\n Briefcase,\n Calendar,\n Clock,\n TrendingUp,\n Users,\n UserCheck,\n} from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function DashboardDashboardPagePage() {\n const { t: translate } = useI18n();\n const navigate = useNavigate();\n const { employees, jobPostings, leaveRequests, notifications, projects } = useCrewFoundryStore();\n const [selectedPeriod, setSelectedPeriod] = useState<'week' | 'month' | 'quarter'>('month');\n const t = (key: string, fallback: string) => {\n const value = translate(key);\n return value === key ? fallback : value;\n };\n\n const activeEmployees = employees.filter((e) => e.status === 'active').length;\n const onLeave = employees.filter((e) => e.status === 'on_leave').length;\n const openPositions = jobPostings.filter((j) => j.status === 'active').length;\n const totalApplicants = jobPostings.reduce((sum, j) => sum + j.applicants, 0);\n const pendingLeaves = leaveRequests.filter((l) => l.status === 'pending').length;\n const unreadNotifications = notifications.filter((n) => !n.read).length;\n const activeProjects = projects.filter((p) => p.status === 'active').length;\n const avgPerformance = (\n employees.reduce((sum, e) => sum + e.performanceScore, 0) / employees.length\n ).toFixed(1);\n\n const departmentHeadcount = employees.reduce<Record<string, number>>((acc, e) => {\n acc[e.department] = (acc[e.department] || 0) + 1;\n return acc;\n }, {});\n\n const maxHeadcount = Math.max(...Object.values(departmentHeadcount));\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"relative overflow-hidden rounded-xl border border-border-seam bg-gloss-card p-6\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>{t('crewfoundry.dashboard.title', 'Workforce Dashboard')}</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'crewfoundry.dashboard.subtitle',\n \"Overview of your organization's workforce metrics\"\n )}\n </p>\n <PagePurpose className=\"mt-2\">\n {t(\n 'crewfoundry.dashboard.purpose',\n 'Your workforce command center — see headcount, hiring, performance, and projects at a glance, then jump straight to the area that needs your attention.'\n )}\n </PagePurpose>\n </div>\n <div className=\"flex gap-2\">\n {(['week', 'month', 'quarter'] as const).map((period) => (\n <Button\n key={period}\n variant={selectedPeriod === period ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setSelectedPeriod(period)}\n >\n {t(\n `crewfoundry.dashboard.period.${period}`,\n period.charAt(0).toUpperCase() + period.slice(1)\n )}\n </Button>\n ))}\n </div>\n </div>\n </div>\n\n <NextSteps\n storageKey=\"crewfoundry-dashboard\"\n steps={[\n {\n id: 'employees',\n label: t('crewfoundry.dashboard.next.employees', 'Review your team'),\n description: t(\n 'crewfoundry.dashboard.next.employeesDesc',\n 'Open the employee directory to see who is active and on leave.'\n ),\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => navigate('../../hr/employees-page'),\n },\n {\n id: 'hiring',\n label: t('crewfoundry.dashboard.next.hiring', 'Post a new job'),\n description: t(\n 'crewfoundry.dashboard.next.hiringDesc',\n 'Create an opening to start collecting applicants.'\n ),\n icon: <Briefcase className=\"h-4 w-4\" />,\n onClick: () => navigate('../../hiring/create-job-page'),\n },\n {\n id: 'projects',\n label: t('crewfoundry.dashboard.next.projects', 'Check active projects'),\n description: t(\n 'crewfoundry.dashboard.next.projectsDesc',\n 'Track progress and budgets across in-flight work.'\n ),\n icon: <Activity className=\"h-4 w-4\" />,\n onClick: () => navigate('../../projects/projects-page'),\n },\n ]}\n />\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\">\n {t('crewfoundry.dashboard.stats.totalEmployees', 'Total Employees')}\n </CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{employees.length}</div>\n <p className=\"text-xs text-text-secondary\">\n {activeEmployees} {t('crewfoundry.dashboard.stats.active', 'active')}, {onLeave}{' '}\n {t('crewfoundry.dashboard.stats.onLeave', 'on leave')}\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\">\n {t('crewfoundry.dashboard.stats.openPositions', 'Open Positions')}\n </CardTitle>\n <Briefcase className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{openPositions}</div>\n <p className=\"text-xs text-text-secondary\">\n {totalApplicants}{' '}\n {t('crewfoundry.dashboard.stats.totalApplicants', 'total applicants')}\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\">\n {t('crewfoundry.dashboard.stats.avgPerformance', 'Avg Performance')}\n </CardTitle>\n <TrendingUp className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{avgPerformance}/5</div>\n <p className=\"text-xs text-text-secondary\">\n {t('crewfoundry.dashboard.stats.performanceTrend', '+0.2 from last quarter')}\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\">\n {t('crewfoundry.dashboard.stats.activeProjects', 'Active Projects')}\n </CardTitle>\n <Activity className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activeProjects}</div>\n <p className=\"text-xs text-text-secondary\">\n {pendingLeaves}{' '}\n {t('crewfoundry.dashboard.stats.pendingLeaveRequests', 'pending leave requests')}\n </p>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-7\">\n <EmphasisPanel className=\"col-span-4\">\n <div className=\"mb-1 text-lg font-semibold\">\n {t('crewfoundry.dashboard.departmentHeadcount.title', 'Department Headcount')}\n </div>\n <p className=\"mb-4 text-sm text-text-secondary\">\n {t(\n 'crewfoundry.dashboard.departmentHeadcount.description',\n 'Employee distribution across departments'\n )}\n </p>\n <div className=\"space-y-3\">\n {Object.entries(departmentHeadcount)\n .sort(([, a], [, b]) => b - a)\n .map(([dept, count]) => (\n <div key={dept} className=\"flex items-center gap-3\">\n <span className=\"w-24 text-sm text-text-secondary truncate\">{dept}</span>\n <div className=\"flex-1 h-4 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-4 bg-action-primary-bg rounded\"\n style={{ width: `${Math.round((count / maxHeadcount) * 100)}%` }}\n />\n </div>\n <span className=\"text-sm font-medium w-8 text-right tabular-nums\">{count}</span>\n </div>\n ))}\n </div>\n </EmphasisPanel>\n\n <Card className=\"col-span-3\">\n <CardHeader className=\"flex flex-row items-center justify-between\">\n <CardTitle>\n {t('crewfoundry.dashboard.notifications.title', 'Recent Notifications')}\n </CardTitle>\n <Badge variant=\"secondary\">\n {unreadNotifications} {t('crewfoundry.dashboard.notifications.unread', 'unread')}\n </Badge>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {notifications.slice(0, 5).map((notif) => (\n <div key={notif.id} className=\"flex items-start gap-3\">\n <div\n className={`mt-1 h-2 w-2 rounded-full flex-shrink-0 motion-safe:animate-vc-glow-pulse ${\n notif.type === 'success'\n ? 'bg-status-success-text'\n : notif.type === 'warning'\n ? 'bg-status-warning-text'\n : notif.type === 'error'\n ? 'bg-status-error-text'\n : 'bg-status-info-text'\n }`}\n />\n <div className=\"flex-1 min-w-0\">\n <p className={`text-sm ${notif.read ? 'text-text-secondary' : 'font-medium'}`}>\n {notif.title}\n </p>\n <p className=\"text-xs text-text-secondary truncate\">{notif.message}</p>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle>\n {t('crewfoundry.dashboard.upcomingInterviews.title', 'Upcoming Interviews')}\n </CardTitle>\n <CardDescription>\n {t('crewfoundry.dashboard.upcomingInterviews.description', 'Scheduled for this week')}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {projects\n .filter((p) => p.status === 'active')\n .slice(0, 4)\n .map((project) => (\n <div\n key={project.id}\n className=\"flex items-center justify-between rounded border p-3\"\n >\n <div>\n <p className=\"text-sm font-medium\">{project.name}</p>\n <p className=\"text-xs text-text-secondary\">{project.teamName}</p>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-24 h-2 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-2 bg-action-primary-bg rounded\"\n style={{ width: `${project.progress}%` }}\n />\n </div>\n <span className=\"text-xs text-text-secondary\">{project.progress}%</span>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>\n {t('crewfoundry.dashboard.leaveRequests.title', 'Recent Leave Requests')}\n </CardTitle>\n <CardDescription>\n {t('crewfoundry.dashboard.leaveRequests.description', 'Pending approval')}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {leaveRequests.length === 0 && (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('crewfoundry.dashboard.leaveRequests.emptyTitle', 'No leave requests')}\n description={t(\n 'crewfoundry.dashboard.leaveRequests.emptyDescription',\n 'Pending leave requests will appear here.'\n )}\n />\n )}\n {leaveRequests.map((leave) => (\n <div key={leave.id} className=\"flex items-center justify-between rounded border p-3\">\n <div className=\"flex items-center gap-3\">\n <div>\n <p className=\"text-sm font-medium\">{leave.employeeName}</p>\n <div className=\"flex items-center gap-2 text-xs text-text-secondary\">\n <Calendar className=\"h-3 w-3\" />\n <span>\n {leave.startDate} - {leave.endDate}\n </span>\n </div>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <Badge\n variant={\n leave.status === 'approved'\n ? 'default'\n : leave.status === 'pending'\n ? 'secondary'\n : 'destructive'\n }\n >\n {leave.status}\n </Badge>\n <Badge variant=\"outline\">{leave.type}</Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DashboardDashboardPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/DashboardDashboardPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n AuroraBackground,\n EmphasisPanel,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Activity, Briefcase, Calendar, TrendingUp, Users } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\nimport { useCrewFoundry } from '../providers/CrewFoundryProvider';\n\nexport function DashboardDashboardPagePage() {\n const { t: translate } = useI18n();\n const navigate = useNavigate();\n const { showToast } = useGlobalUi();\n const { currentUser } = useCrewFoundry();\n const { employees, jobPostings, leaveRequests, notifications, projects, updateLeaveRequest } =\n useCrewFoundryStore();\n const [selectedPeriod, setSelectedPeriod] = useState<'week' | 'month' | 'quarter'>('month');\n const [processingLeaveId, setProcessingLeaveId] = useState<string | null>(null);\n\n const approverName =\n currentUser?.name ||\n [currentUser?.firstName, currentUser?.lastName].filter(Boolean).join(' ') ||\n currentUser?.email ||\n 'Manager';\n\n const decideLeave = async (id: string, status: 'approved' | 'rejected') => {\n setProcessingLeaveId(id);\n try {\n await updateLeaveRequest(id, { status, approverName });\n showToast(status === 'approved' ? 'Leave approved' : 'Leave rejected', 'success');\n } catch (error) {\n showToast(\n error instanceof Error ? error.message : 'Unable to update leave request',\n 'error'\n );\n } finally {\n setProcessingLeaveId(null);\n }\n };\n const t = (key: string, fallback: string) => {\n const value = translate(key);\n return value === key ? fallback : value;\n };\n\n const activeEmployees = employees.filter((e) => e.status === 'active').length;\n const onLeave = employees.filter((e) => e.status === 'on_leave').length;\n const openPositions = jobPostings.filter((j) => j.status === 'active').length;\n const totalApplicants = jobPostings.reduce((sum, j) => sum + j.applicants, 0);\n const pendingLeaves = leaveRequests.filter((l) => l.status === 'pending').length;\n const unreadNotifications = notifications.filter((n) => !n.read).length;\n const activeProjects = projects.filter((p) => p.status === 'active').length;\n const avgPerformance = (\n employees.reduce((sum, e) => sum + e.performanceScore, 0) / employees.length\n ).toFixed(1);\n\n const departmentHeadcount = employees.reduce<Record<string, number>>((acc, e) => {\n acc[e.department] = (acc[e.department] || 0) + 1;\n return acc;\n }, {});\n\n const maxHeadcount = Math.max(...Object.values(departmentHeadcount));\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"relative overflow-hidden rounded-xl border border-border-seam bg-gloss-card p-6\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>{t('crewfoundry.dashboard.title', 'Workforce Dashboard')}</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'crewfoundry.dashboard.subtitle',\n \"Overview of your organization's workforce metrics\"\n )}\n </p>\n <PagePurpose className=\"mt-2\">\n {t(\n 'crewfoundry.dashboard.purpose',\n 'Your workforce command center — see headcount, hiring, performance, and projects at a glance, then jump straight to the area that needs your attention.'\n )}\n </PagePurpose>\n </div>\n <div className=\"flex gap-2\">\n {(['week', 'month', 'quarter'] as const).map((period) => (\n <Button\n key={period}\n variant={selectedPeriod === period ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setSelectedPeriod(period)}\n >\n {t(\n `crewfoundry.dashboard.period.${period}`,\n period.charAt(0).toUpperCase() + period.slice(1)\n )}\n </Button>\n ))}\n </div>\n </div>\n </div>\n\n <NextSteps\n storageKey=\"crewfoundry-dashboard\"\n steps={[\n {\n id: 'employees',\n label: t('crewfoundry.dashboard.next.employees', 'Review your team'),\n description: t(\n 'crewfoundry.dashboard.next.employeesDesc',\n 'Open the employee directory to see who is active and on leave.'\n ),\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => navigate('../../hr/employees-page'),\n },\n {\n id: 'hiring',\n label: t('crewfoundry.dashboard.next.hiring', 'Post a new job'),\n description: t(\n 'crewfoundry.dashboard.next.hiringDesc',\n 'Create an opening to start collecting applicants.'\n ),\n icon: <Briefcase className=\"h-4 w-4\" />,\n onClick: () => navigate('../../hiring/create-job-page'),\n },\n {\n id: 'projects',\n label: t('crewfoundry.dashboard.next.projects', 'Check active projects'),\n description: t(\n 'crewfoundry.dashboard.next.projectsDesc',\n 'Track progress and budgets across in-flight work.'\n ),\n icon: <Activity className=\"h-4 w-4\" />,\n onClick: () => navigate('../../projects/projects-page'),\n },\n ]}\n />\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\">\n {t('crewfoundry.dashboard.stats.totalEmployees', 'Total Employees')}\n </CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{employees.length}</div>\n <p className=\"text-xs text-text-secondary\">\n {activeEmployees} {t('crewfoundry.dashboard.stats.active', 'active')}, {onLeave}{' '}\n {t('crewfoundry.dashboard.stats.onLeave', 'on leave')}\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\">\n {t('crewfoundry.dashboard.stats.openPositions', 'Open Positions')}\n </CardTitle>\n <Briefcase className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{openPositions}</div>\n <p className=\"text-xs text-text-secondary\">\n {totalApplicants}{' '}\n {t('crewfoundry.dashboard.stats.totalApplicants', 'total applicants')}\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\">\n {t('crewfoundry.dashboard.stats.avgPerformance', 'Avg Performance')}\n </CardTitle>\n <TrendingUp className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{avgPerformance}/5</div>\n <p className=\"text-xs text-text-secondary\">\n {t('crewfoundry.dashboard.stats.performanceTrend', '+0.2 from last quarter')}\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\">\n {t('crewfoundry.dashboard.stats.activeProjects', 'Active Projects')}\n </CardTitle>\n <Activity className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activeProjects}</div>\n <p className=\"text-xs text-text-secondary\">\n {pendingLeaves}{' '}\n {t('crewfoundry.dashboard.stats.pendingLeaveRequests', 'pending leave requests')}\n </p>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-7\">\n <EmphasisPanel className=\"col-span-4\">\n <div className=\"mb-1 text-lg font-semibold\">\n {t('crewfoundry.dashboard.departmentHeadcount.title', 'Department Headcount')}\n </div>\n <p className=\"mb-4 text-sm text-text-secondary\">\n {t(\n 'crewfoundry.dashboard.departmentHeadcount.description',\n 'Employee distribution across departments'\n )}\n </p>\n <div className=\"space-y-3\">\n {Object.entries(departmentHeadcount)\n .sort(([, a], [, b]) => b - a)\n .map(([dept, count]) => (\n <div key={dept} className=\"flex items-center gap-3\">\n <span className=\"w-24 text-sm text-text-secondary truncate\">{dept}</span>\n <div className=\"flex-1 h-4 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-4 bg-action-primary-bg rounded\"\n style={{ width: `${Math.round((count / maxHeadcount) * 100)}%` }}\n />\n </div>\n <span className=\"text-sm font-medium w-8 text-right tabular-nums\">{count}</span>\n </div>\n ))}\n </div>\n </EmphasisPanel>\n\n <Card className=\"col-span-3\">\n <CardHeader className=\"flex flex-row items-center justify-between\">\n <CardTitle>\n {t('crewfoundry.dashboard.notifications.title', 'Recent Notifications')}\n </CardTitle>\n <Badge variant=\"secondary\">\n {unreadNotifications} {t('crewfoundry.dashboard.notifications.unread', 'unread')}\n </Badge>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {notifications.slice(0, 5).map((notif) => (\n <div key={notif.id} className=\"flex items-start gap-3\">\n <div\n className={`mt-1 h-2 w-2 rounded-full flex-shrink-0 motion-safe:animate-vc-glow-pulse ${\n notif.type === 'success'\n ? 'bg-status-success-text'\n : notif.type === 'warning'\n ? 'bg-status-warning-text'\n : notif.type === 'error'\n ? 'bg-status-error-text'\n : 'bg-status-info-text'\n }`}\n />\n <div className=\"flex-1 min-w-0\">\n <p className={`text-sm ${notif.read ? 'text-text-secondary' : 'font-medium'}`}>\n {notif.title}\n </p>\n <p className=\"text-xs text-text-secondary truncate\">{notif.message}</p>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle>\n {t('crewfoundry.dashboard.upcomingInterviews.title', 'Upcoming Interviews')}\n </CardTitle>\n <CardDescription>\n {t('crewfoundry.dashboard.upcomingInterviews.description', 'Scheduled for this week')}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {projects\n .filter((p) => p.status === 'active')\n .slice(0, 4)\n .map((project) => (\n <div\n key={project.id}\n className=\"flex items-center justify-between rounded border p-3\"\n >\n <div>\n <p className=\"text-sm font-medium\">{project.name}</p>\n <p className=\"text-xs text-text-secondary\">{project.teamName}</p>\n </div>\n <div className=\"flex items-center gap-2\">\n <div className=\"w-24 h-2 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-2 bg-action-primary-bg rounded\"\n style={{ width: `${project.progress}%` }}\n />\n </div>\n <span className=\"text-xs text-text-secondary\">{project.progress}%</span>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>\n {t('crewfoundry.dashboard.leaveRequests.title', 'Recent Leave Requests')}\n </CardTitle>\n <CardDescription>\n {t('crewfoundry.dashboard.leaveRequests.description', 'Pending approval')}\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {leaveRequests.length === 0 && (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('crewfoundry.dashboard.leaveRequests.emptyTitle', 'No leave requests')}\n description={t(\n 'crewfoundry.dashboard.leaveRequests.emptyDescription',\n 'Pending leave requests will appear here.'\n )}\n />\n )}\n {leaveRequests.map((leave) => (\n <div key={leave.id} className=\"flex items-center justify-between rounded border p-3\">\n <div className=\"flex items-center gap-3\">\n <div>\n <p className=\"text-sm font-medium\">{leave.employeeName}</p>\n <div className=\"flex items-center gap-2 text-xs text-text-secondary\">\n <Calendar className=\"h-3 w-3\" />\n <span>\n {leave.startDate} - {leave.endDate}\n </span>\n </div>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {leave.status === 'pending' && (\n <div className=\"flex gap-1\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs\"\n disabled={processingLeaveId === leave.id}\n onClick={() => void decideLeave(leave.id, 'rejected')}\n >\n {t('crewfoundry.dashboard.leaveRequests.reject', 'Reject')}\n </Button>\n <Button\n size=\"sm\"\n className=\"h-7 text-xs\"\n disabled={processingLeaveId === leave.id}\n onClick={() => void decideLeave(leave.id, 'approved')}\n >\n {t('crewfoundry.dashboard.leaveRequests.approve', 'Approve')}\n </Button>\n </div>\n )}\n <Badge\n variant={\n leave.status === 'approved'\n ? 'default'\n : leave.status === 'pending'\n ? 'secondary'\n : 'destructive'\n }\n >\n {leave.status}\n </Badge>\n <Badge variant=\"outline\">{leave.type}</Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAwBA,SAAgB,IAA6B;CAC3C,IAAM,EAAE,GAAG,MAAc,GAAS,EAC5B,IAAW,GAAa,EACxB,EAAE,iBAAc,GAAa,EAC7B,EAAE,mBAAgB,GAAgB,EAClC,EAAE,cAAW,gBAAa,kBAAe,kBAAe,aAAU,0BACtE,GAAqB,EACjB,CAAC,GAAgB,KAAqB,EAAuC,QAAQ,EACrF,CAAC,GAAmB,KAAwB,EAAwB,KAAK,EAEzE,IACJ,GAAa,QACb,CAAC,GAAa,WAAW,GAAa,SAAS,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI,IACzE,GAAa,SACb,WAEI,IAAc,OAAO,GAAY,MAAoC;AACzE,IAAqB,EAAG;AACxB,MAAI;AAEF,GADA,MAAM,EAAmB,GAAI;IAAE;IAAQ;IAAc,CAAC,EACtD,EAAU,MAAW,aAAa,mBAAmB,kBAAkB,UAAU;WAC1E,GAAO;AACd,KACE,aAAiB,QAAQ,EAAM,UAAU,kCACzC,QACD;YACO;AACR,KAAqB,KAAK;;IAGxB,KAAK,GAAa,MAAqB;EAC3C,IAAM,IAAQ,EAAU,EAAI;AAC5B,SAAO,MAAU,IAAM,IAAW;IAG9B,IAAkB,EAAU,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC,QACjE,IAAU,EAAU,QAAQ,MAAM,EAAE,WAAW,WAAW,CAAC,QAC3D,IAAgB,EAAY,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC,QACjE,IAAkB,EAAY,QAAQ,GAAK,MAAM,IAAM,EAAE,YAAY,EAAE,EACvE,IAAgB,EAAc,QAAQ,MAAM,EAAE,WAAW,UAAU,CAAC,QACpE,IAAsB,EAAc,QAAQ,MAAM,CAAC,EAAE,KAAK,CAAC,QAC3D,IAAiB,EAAS,QAAQ,MAAM,EAAE,WAAW,SAAS,CAAC,QAC/D,KACJ,EAAU,QAAQ,GAAK,MAAM,IAAM,EAAE,kBAAkB,EAAE,GAAG,EAAU,QACtE,QAAQ,EAAE,EAEN,IAAsB,EAAU,QAAgC,GAAK,OACzE,EAAI,EAAE,eAAe,EAAI,EAAE,eAAe,KAAK,GACxC,IACN,EAAE,CAAC,EAEA,IAAe,KAAK,IAAI,GAAG,OAAO,OAAO,EAAoB,CAAC;AAEpE,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAkB,WAAU,UAAW,CAAA,EACvC,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD,EAAA,UAAA;MACE,kBAAC,MAAD;OAAI,WAAU;iBACZ,kBAAC,GAAD,EAAA,UAAe,EAAE,+BAA+B,sBAAsB,EAAgB,CAAA;OACnF,CAAA;MACL,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,kCACA,oDACD;OACC,CAAA;MACJ,kBAAC,GAAD;OAAa,WAAU;iBACpB,EACC,iCACA,0JACD;OACW,CAAA;MACV,EAAA,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBACX;OAAC;OAAQ;OAAS;OAAU,CAAW,KAAK,MAC5C,kBAAC,GAAD;OAEE,SAAS,MAAmB,IAAS,YAAY;OACjD,MAAK;OACL,eAAe,EAAkB,EAAO;iBAEvC,EACC,gCAAgC,KAChC,EAAO,OAAO,EAAE,CAAC,aAAa,GAAG,EAAO,MAAM,EAAE,CACjD;OACM,EATF,EASE,CACT;MACE,CAAA,CACF;OACF;;GAEN,kBAAC,GAAD;IACE,YAAW;IACX,OAAO;KACL;MACE,IAAI;MACJ,OAAO,EAAE,wCAAwC,mBAAmB;MACpE,aAAa,EACX,4CACA,iEACD;MACD,MAAM,kBAAC,GAAD,EAAO,WAAU,WAAY,CAAA;MACnC,eAAe,EAAS,0BAA0B;MACnD;KACD;MACE,IAAI;MACJ,OAAO,EAAE,qCAAqC,iBAAiB;MAC/D,aAAa,EACX,yCACA,oDACD;MACD,MAAM,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA;MACvC,eAAe,EAAS,+BAA+B;MACxD;KACD;MACE,IAAI;MACJ,OAAO,EAAE,uCAAuC,wBAAwB;MACxE,aAAa,EACX,2CACA,oDACD;MACD,MAAM,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA;MACtC,eAAe,EAAS,+BAA+B;MACxD;KACF;IACD,CAAA;GAEF,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;kBAClB,EAAE,8CAA8C,kBAAkB;QACzD,CAAA,EACZ,kBAAC,GAAD,EAAO,WAAU,+BAAgC,CAAA,CACtC;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAmC,EAAU;OAAa,CAAA,EACzE,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG;QAAgB;QAAE,EAAE,sCAAsC,SAAS;QAAC;QAAG;QAAS;QAChF,EAAE,uCAAuC,WAAW;QACnD;SACQ,EAAA,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAE,6CAA6C,iBAAiB;QACvD,CAAA,EACZ,kBAAC,GAAD,EAAW,WAAU,+BAAgC,CAAA,CAC1C;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAmC;OAAoB,CAAA,EACtE,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG;QAAiB;QACjB,EAAE,+CAA+C,mBAAmB;QACnE;SACQ,EAAA,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAE,8CAA8C,kBAAkB;QACzD,CAAA,EACZ,kBAAC,GAAD,EAAY,WAAU,+BAAgC,CAAA,CAC3C;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CAAkD,GAAe,KAAQ;UACzE,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAE,gDAAgD,yBAAyB;OAC1E,CAAA,CACQ,EAAA,CAAA,CACJ;;KACZ,kBAAC,GAAD;MAAW,WAAU;MAAS,WAAU;gBAAxC,CACE,kBAAC,GAAD;OAAY,WAAU;iBAAtB,CACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAE,8CAA8C,kBAAkB;QACzD,CAAA,EACZ,kBAAC,GAAD,EAAU,WAAU,+BAAgC,CAAA,CACzC;UACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAmC;OAAqB,CAAA,EACvE,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG;QAAe;QACf,EAAE,oDAAoD,yBAAyB;QAC9E;SACQ,EAAA,CAAA,CACJ;;KACR;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAe,WAAU;eAAzB;MACE,kBAAC,OAAD;OAAK,WAAU;iBACZ,EAAE,mDAAmD,uBAAuB;OACzE,CAAA;MACN,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,yDACA,2CACD;OACC,CAAA;MACJ,kBAAC,OAAD;OAAK,WAAU;iBACZ,OAAO,QAAQ,EAAoB,CACjC,MAAM,GAAG,IAAI,GAAG,OAAO,IAAI,EAAE,CAC7B,KAAK,CAAC,GAAM,OACX,kBAAC,OAAD;QAAgB,WAAU;kBAA1B;SACE,kBAAC,QAAD;UAAM,WAAU;oBAA6C;UAAY,CAAA;SACzE,kBAAC,OAAD;UAAK,WAAU;oBACb,kBAAC,OAAD;WACE,WAAU;WACV,OAAO,EAAE,OAAO,GAAG,KAAK,MAAO,IAAQ,IAAgB,IAAI,CAAC,IAAI;WAChE,CAAA;UACE,CAAA;SACN,kBAAC,QAAD;UAAM,WAAU;oBAAmD;UAAa,CAAA;SAC5E;UATI,EASJ,CACN;OACA,CAAA;MACQ;QAEhB,kBAAC,GAAD;KAAM,WAAU;eAAhB,CACE,kBAAC,GAAD;MAAY,WAAU;gBAAtB,CACE,kBAAC,GAAD,EAAA,UACG,EAAE,6CAA6C,uBAAuB,EAC7D,CAAA,EACZ,kBAAC,GAAD;OAAO,SAAQ;iBAAf;QACG;QAAoB;QAAE,EAAE,8CAA8C,SAAS;QAC1E;SACG;SACb,kBAAC,GAAD;MAAa,WAAU;gBACpB,EAAc,MAAM,GAAG,EAAE,CAAC,KAAK,MAC9B,kBAAC,OAAD;OAAoB,WAAU;iBAA9B,CACE,kBAAC,OAAD,EACE,WAAW,6EACT,EAAM,SAAS,YACX,2BACA,EAAM,SAAS,YACb,2BACA,EAAM,SAAS,UACb,yBACA,yBAEV,CAAA,EACF,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,KAAD;SAAG,WAAW,WAAW,EAAM,OAAO,wBAAwB;mBAC3D,EAAM;SACL,CAAA,EACJ,kBAAC,KAAD;SAAG,WAAU;mBAAwC,EAAM;SAAY,CAAA,CACnE;UACF;SAlBI,EAAM,GAkBV,CACN;MACU,CAAA,CACT;OACH;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACG,EAAE,kDAAkD,sBAAsB,EACjE,CAAA,EACZ,kBAAC,GAAD,EAAA,UACG,EAAE,wDAAwD,0BAA0B,EACrE,CAAA,CACP,EAAA,CAAA,EACb,kBAAC,GAAD;KAAa,WAAU;eACpB,EACE,QAAQ,MAAM,EAAE,WAAW,SAAS,CACpC,MAAM,GAAG,EAAE,CACX,KAAK,MACJ,kBAAC,OAAD;MAEE,WAAU;gBAFZ,CAIE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;OAAG,WAAU;iBAAuB,EAAQ;OAAS,CAAA,EACrD,kBAAC,KAAD;OAAG,WAAU;iBAA+B,EAAQ;OAAa,CAAA,CAC7D,EAAA,CAAA,EACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,OAAD;SACE,WAAU;SACV,OAAO,EAAE,OAAO,GAAG,EAAQ,SAAS,IAAI;SACxC,CAAA;QACE,CAAA,EACN,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CAA+C,EAAQ,UAAS,IAAQ;UACpE;SACF;QAhBC,EAAQ,GAgBT,CACN;KACQ,CAAA,CACT,EAAA,CAAA,EAEP,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACG,EAAE,6CAA6C,wBAAwB,EAC9D,CAAA,EACZ,kBAAC,GAAD,EAAA,UACG,EAAE,mDAAmD,mBAAmB,EACzD,CAAA,CACP,EAAA,CAAA,EACb,kBAAC,GAAD;KAAa,WAAU;eAAvB,CACG,EAAc,WAAW,KACxB,kBAAC,GAAD;MACE,cAAa;MACb,OAAO,EAAE,kDAAkD,oBAAoB;MAC/E,aAAa,EACX,wDACA,2CACD;MACD,CAAA,EAEH,EAAc,KAAK,MAClB,kBAAC,OAAD;MAAoB,WAAU;gBAA9B,CACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAuB,EAAM;QAAiB,CAAA,EAC3D,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAU,WAAU,WAAY,CAAA,EAChC,kBAAC,QAAD,EAAA,UAAA;SACG,EAAM;SAAU;SAAI,EAAM;SACtB,EAAA,CAAA,CACH;UACF,EAAA,CAAA;OACF,CAAA,EACN,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACG,EAAM,WAAW,aAChB,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,WAAU;UACV,UAAU,MAAsB,EAAM;UACtC,eAAe,KAAK,EAAY,EAAM,IAAI,WAAW;oBAEpD,EAAE,8CAA8C,SAAS;UACnD,CAAA,EACT,kBAAC,GAAD;UACE,MAAK;UACL,WAAU;UACV,UAAU,MAAsB,EAAM;UACtC,eAAe,KAAK,EAAY,EAAM,IAAI,WAAW;oBAEpD,EAAE,+CAA+C,UAAU;UACrD,CAAA,CACL;;QAER,kBAAC,GAAD;SACE,SACE,EAAM,WAAW,aACb,YACA,EAAM,WAAW,YACf,cACA;mBAGP,EAAM;SACD,CAAA;QACR,kBAAC,GAAD;SAAO,SAAQ;mBAAW,EAAM;SAAa,CAAA;QACzC;SACF;QA/CI,EAAM,GA+CV,CACN,CACU;OACT,EAAA,CAAA,CACH;;GACF"}