@burdenoff/microfe-crewfoundry 2026.704.6 → 2026.707.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 (150) hide show
  1. package/dist/crewfoundry/CrewFoundryRoutes.js +51 -43
  2. package/dist/crewfoundry/CrewFoundryRoutes.js.map +1 -1
  3. package/dist/crewfoundry/components/forms/formValues.js +5 -2
  4. package/dist/crewfoundry/components/forms/formValues.js.map +1 -1
  5. package/dist/crewfoundry/components/viz/AllocationBar.js +68 -0
  6. package/dist/crewfoundry/components/viz/AllocationBar.js.map +1 -0
  7. package/dist/crewfoundry/components/viz/AreaChart.js +102 -0
  8. package/dist/crewfoundry/components/viz/AreaChart.js.map +1 -0
  9. package/dist/crewfoundry/components/viz/AvatarStack.js +36 -0
  10. package/dist/crewfoundry/components/viz/AvatarStack.js.map +1 -0
  11. package/dist/crewfoundry/components/viz/BarChart.js +83 -0
  12. package/dist/crewfoundry/components/viz/BarChart.js.map +1 -0
  13. package/dist/crewfoundry/components/viz/CertificateCard.js +118 -0
  14. package/dist/crewfoundry/components/viz/CertificateCard.js.map +1 -0
  15. package/dist/crewfoundry/components/viz/DonutChart.js +109 -0
  16. package/dist/crewfoundry/components/viz/DonutChart.js.map +1 -0
  17. package/dist/crewfoundry/components/viz/HBarFunnel.js +54 -0
  18. package/dist/crewfoundry/components/viz/HBarFunnel.js.map +1 -0
  19. package/dist/crewfoundry/components/viz/Heatmap.js +91 -0
  20. package/dist/crewfoundry/components/viz/Heatmap.js.map +1 -0
  21. package/dist/crewfoundry/components/viz/KanbanBoard.js +50 -0
  22. package/dist/crewfoundry/components/viz/KanbanBoard.js.map +1 -0
  23. package/dist/crewfoundry/components/viz/LineChart.js +123 -0
  24. package/dist/crewfoundry/components/viz/LineChart.js.map +1 -0
  25. package/dist/crewfoundry/components/viz/OrgTree.js +83 -0
  26. package/dist/crewfoundry/components/viz/OrgTree.js.map +1 -0
  27. package/dist/crewfoundry/components/viz/PathSteps.js +68 -0
  28. package/dist/crewfoundry/components/viz/PathSteps.js.map +1 -0
  29. package/dist/crewfoundry/components/viz/ProgressRing.js +68 -0
  30. package/dist/crewfoundry/components/viz/ProgressRing.js.map +1 -0
  31. package/dist/crewfoundry/components/viz/RatingStars.js +51 -0
  32. package/dist/crewfoundry/components/viz/RatingStars.js.map +1 -0
  33. package/dist/crewfoundry/components/viz/SegmentedTabs.js +69 -0
  34. package/dist/crewfoundry/components/viz/SegmentedTabs.js.map +1 -0
  35. package/dist/crewfoundry/components/viz/SkillBar.js +3 -0
  36. package/dist/crewfoundry/components/viz/Sparkline.js +74 -0
  37. package/dist/crewfoundry/components/viz/Sparkline.js.map +1 -0
  38. package/dist/crewfoundry/components/viz/StatCard.js +60 -0
  39. package/dist/crewfoundry/components/viz/StatCard.js.map +1 -0
  40. package/dist/crewfoundry/components/viz/StepProgress.js +3 -0
  41. package/dist/crewfoundry/components/viz/Timeline.js +66 -0
  42. package/dist/crewfoundry/components/viz/Timeline.js.map +1 -0
  43. package/dist/crewfoundry/components/viz/index.js +23 -0
  44. package/dist/crewfoundry/components/viz/lib/Avatar.js +30 -0
  45. package/dist/crewfoundry/components/viz/lib/Avatar.js.map +1 -0
  46. package/dist/crewfoundry/components/viz/lib/CartesianFrame.js +119 -0
  47. package/dist/crewfoundry/components/viz/lib/CartesianFrame.js.map +1 -0
  48. package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js +35 -0
  49. package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js.map +1 -0
  50. package/dist/crewfoundry/components/viz/lib/format.js +21 -0
  51. package/dist/crewfoundry/components/viz/lib/format.js.map +1 -0
  52. package/dist/crewfoundry/components/viz/lib/geometry.js +69 -0
  53. package/dist/crewfoundry/components/viz/lib/geometry.js.map +1 -0
  54. package/dist/crewfoundry/components/viz/lib/hooks.js +39 -0
  55. package/dist/crewfoundry/components/viz/lib/hooks.js.map +1 -0
  56. package/dist/crewfoundry/components/viz/lib/palette.js +27 -0
  57. package/dist/crewfoundry/components/viz/lib/palette.js.map +1 -0
  58. package/dist/crewfoundry/lib/analytics.js +323 -0
  59. package/dist/crewfoundry/lib/analytics.js.map +1 -0
  60. package/dist/crewfoundry/lib/companyFinance.js +16 -0
  61. package/dist/crewfoundry/lib/companyFinance.js.map +1 -0
  62. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +226 -283
  63. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  64. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +107 -120
  65. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
  66. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +122 -162
  67. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
  68. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +121 -158
  69. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
  70. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +316 -211
  71. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
  72. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +75 -27
  73. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
  74. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +167 -165
  75. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
  76. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +168 -109
  77. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
  78. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +401 -290
  79. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
  80. package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js +0 -41
  81. package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js.map +1 -1
  82. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +84 -75
  83. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
  84. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +368 -174
  85. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
  86. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +236 -201
  87. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
  88. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +369 -196
  89. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
  90. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +269 -270
  91. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
  92. package/dist/crewfoundry/pages/HiringJobsPagePage.js +210 -110
  93. package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
  94. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +216 -178
  95. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
  96. package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js +385 -0
  97. package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js.map +1 -0
  98. package/dist/crewfoundry/pages/HrEmployeesPagePage.js +189 -130
  99. package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
  100. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +397 -241
  101. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
  102. package/dist/crewfoundry/pages/HrPayrollPagePage.js +262 -147
  103. package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
  104. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +345 -167
  105. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
  106. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +98 -24
  107. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
  108. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +1 -1
  109. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
  110. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +289 -108
  111. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
  112. package/dist/crewfoundry/pages/LearningCoursesPagePage.js +221 -114
  113. package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
  114. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +134 -135
  115. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
  116. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +148 -97
  117. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
  118. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +264 -157
  119. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
  120. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +85 -93
  121. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
  122. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +211 -122
  123. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
  124. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +94 -54
  125. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
  126. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +289 -140
  127. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
  128. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +169 -79
  129. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
  130. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +296 -125
  131. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
  132. package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js +187 -0
  133. package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js.map +1 -0
  134. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +140 -78
  135. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
  136. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +93 -43
  137. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
  138. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +250 -98
  139. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
  140. package/dist/crewfoundry/store/crewfoundryStore.js +142 -184
  141. package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
  142. package/dist/crewfoundry/utils/cn.js +10 -0
  143. package/dist/crewfoundry/utils/cn.js.map +1 -0
  144. package/dist/crewfoundry/utils/courseProgress.js +46 -0
  145. package/dist/crewfoundry/utils/courseProgress.js.map +1 -0
  146. package/dist/node_modules/clsx/dist/clsx.js +18 -0
  147. package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
  148. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
  149. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  150. package/package.json +1 -1
@@ -1,14 +1,19 @@
1
1
  import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
2
  import { formatEnumLabel as t } from "../utils/formatEnumLabel.js";
3
- import { FormModal as n, useFormModal as r } from "../components/forms/FormModal.js";
4
- import { getNumber as i, getText as a, newClientId as o } from "../components/forms/formValues.js";
5
- import { useMemo as s } from "react";
6
- import { CheckCircle as c, Clock as l, LogIn as u, LogOut as d, Timer as f } from "lucide-react";
7
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
8
- import { Badge as h, Button as g, Card as _, CardContent as v, CardDescription as y, CardHeader as b, CardTitle as x, GlassCard as S, GradientText as C, PagePurpose as w, Pagination as T } from "@burdenoff/fe-libs/ui";
9
- import { usePagination as E } from "@burdenoff/fe-libs/shared/hooks";
3
+ import { DonutChart as n } from "../components/viz/DonutChart.js";
4
+ import { StatCard as r } from "../components/viz/StatCard.js";
5
+ import { AvatarStack as i } from "../components/viz/AvatarStack.js";
6
+ import "../components/viz/index.js";
7
+ import { billableSplit as ee } from "../lib/analytics.js";
8
+ import { FormModal as a, useFormModal as o } from "../components/forms/FormModal.js";
9
+ import { getBool as te, getNumber as s, getText as c, newClientId as ne } from "../components/forms/formValues.js";
10
+ import { useMemo as l, useState as u } from "react";
11
+ import { CheckCircle as re, ChevronLeft as ie, ChevronRight as d, Clock as f, LogIn as ae, LogOut as p, Timer as m } from "lucide-react";
12
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
13
+ import { Badge as _, Button as v, Card as y, CardContent as b, CardDescription as x, CardHeader as S, CardTitle as C, GradientText as oe, PagePurpose as se, Pagination as w } from "@burdenoff/fe-libs/ui";
14
+ import { usePagination as ce } from "@burdenoff/fe-libs/shared/hooks";
10
15
  //#region src/crewfoundry/pages/HrTimeTrackingPagePage.tsx
11
- var D = [
16
+ var T = [
12
17
  {
13
18
  label: "Pending",
14
19
  value: "pending"
@@ -21,7 +26,7 @@ var D = [
21
26
  label: "Rejected",
22
27
  value: "rejected"
23
28
  }
24
- ], O = [
29
+ ], le = [
25
30
  {
26
31
  name: "clockOut",
27
32
  label: "Clock-out time",
@@ -44,14 +49,41 @@ var D = [
44
49
  name: "status",
45
50
  label: "Status",
46
51
  type: "select",
47
- options: D
52
+ options: T
48
53
  }
49
- ];
54
+ ], E = [
55
+ "Jan",
56
+ "Feb",
57
+ "Mar",
58
+ "Apr",
59
+ "May",
60
+ "Jun",
61
+ "Jul",
62
+ "Aug",
63
+ "Sep",
64
+ "Oct",
65
+ "Nov",
66
+ "Dec"
67
+ ], ue = [
68
+ "Mon",
69
+ "Tue",
70
+ "Wed",
71
+ "Thu",
72
+ "Fri",
73
+ "Sat",
74
+ "Sun"
75
+ ], de = (e) => `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`, D = (e) => {
76
+ let t = new Date(e.getFullYear(), e.getMonth(), e.getDate()), n = (t.getDay() + 6) % 7;
77
+ return t.setDate(t.getDate() - n), t;
78
+ }, O = (e) => {
79
+ let [t, n, r] = e.slice(0, 10).split("-").map(Number);
80
+ return new Date(t, (n || 1) - 1, r || 1);
81
+ };
50
82
  function k() {
51
- let { timeEntries: k, employees: A, addTimeEntry: j, updateTimeEntry: M } = e(), N = r(), P = r(), F = s(() => A.map((e) => ({
83
+ let { timeEntries: k, employees: A, addTimeEntry: fe, updateTimeEntry: pe } = e(), j = o(), M = o(), [N, me] = u(null), P = l(() => new Map(A.map((e) => [e.id, e])), [A]), F = l(() => A.map((e) => ({
52
84
  label: `${e.firstName} ${e.lastName}`,
53
85
  value: e.id
54
- })), [A]), I = s(() => [
86
+ })), [A]), I = l(() => [
55
87
  {
56
88
  name: "employeeId",
57
89
  label: "Employee",
@@ -99,188 +131,333 @@ function k() {
99
131
  name: "status",
100
132
  label: "Status",
101
133
  type: "select",
102
- options: D
134
+ options: T
135
+ },
136
+ {
137
+ name: "billable",
138
+ label: "Billable to client",
139
+ type: "switch",
140
+ colSpan: 2
103
141
  }
104
- ], [F]), L = k.reduce((e, t) => e + t.totalHours, 0), R = k.reduce((e, t) => e + t.overtime, 0), z = k.filter((e) => e.status === "approved").length, B = k.filter((e) => e.status === "pending").length, V = k.reduce((e, t) => (e[t.project] = (e[t.project] || 0) + t.totalHours, e), {}), H = Math.max(...Object.values(V), 1), U = s(() => [...k].sort((e, t) => t.date.localeCompare(e.date)), [k]), { page: W, pageSize: G, offset: K, setPage: q } = E({ initialPageSize: 8 }), J = U.slice(K, K + G), Y = async (e) => {
105
- let t = a(e, "employeeId"), n = A.find((e) => e.id === t);
106
- await j({
107
- id: o(),
142
+ ], [F]), [L, R] = u(0), z = l(() => {
143
+ let e = k.map((e) => e.date.slice(0, 10)).filter(Boolean).sort().slice(-1)[0];
144
+ return D(e ? O(e) : /* @__PURE__ */ new Date());
145
+ }, [k]), B = l(() => {
146
+ let e = new Date(z);
147
+ return e.setDate(e.getDate() + L * 7), e;
148
+ }, [z, L]), V = l(() => Array.from({ length: 7 }, (e, t) => {
149
+ let n = new Date(B);
150
+ return n.setDate(B.getDate() + t), {
151
+ iso: de(n),
152
+ label: `${ue[t]} ${n.getDate()}`
153
+ };
154
+ }), [B]), H = l(() => new Set(V.map((e) => e.iso)), [V]), U = V[6], W = `${E[B.getMonth()]} ${B.getDate()} – ${E[O(U.iso).getMonth()]} ${O(U.iso).getDate()}`, G = l(() => k.filter((e) => H.has(e.date.slice(0, 10))), [k, H]), he = G.reduce((e, t) => e + t.totalHours, 0), ge = G.reduce((e, t) => e + t.overtime, 0), _e = G.filter((e) => e.status === "approved").length, ve = G.filter((e) => e.status === "pending").length, K = l(() => {
155
+ let e = /* @__PURE__ */ new Map();
156
+ for (let t of G) {
157
+ let n = e.get(t.employeeId);
158
+ n || (n = {
159
+ name: t.employeeName || P.get(t.employeeId)?.firstName || "Unknown",
160
+ avatar: P.get(t.employeeId)?.avatar,
161
+ perDay: /* @__PURE__ */ new Map(),
162
+ total: 0,
163
+ statuses: /* @__PURE__ */ new Set()
164
+ }, e.set(t.employeeId, n));
165
+ let r = t.date.slice(0, 10);
166
+ n.perDay.set(r, (n.perDay.get(r) ?? 0) + t.totalHours), n.total += t.totalHours, n.statuses.add(t.status);
167
+ }
168
+ return [...e.entries()].map(([e, t]) => ({
169
+ employeeId: e,
170
+ name: t.name,
171
+ avatar: t.avatar,
172
+ perDay: t.perDay,
173
+ total: t.total,
174
+ status: t.statuses.has("pending") ? "pending" : t.statuses.has("rejected") ? "rejected" : "approved"
175
+ })).sort((e, t) => t.total - e.total);
176
+ }, [G, P]), q = l(() => {
177
+ let e = ee(G);
178
+ if (!e) return null;
179
+ let t = e.reduce((e, t) => e + t.value, 0), n = e.find((e) => e.label === "Billable")?.value ?? 0;
180
+ return {
181
+ segments: e,
182
+ centerValue: `${t > 0 ? Math.round(n / t * 100) : 0}%`,
183
+ caption: "Billable"
184
+ };
185
+ }, [G]), J = G.reduce((e, t) => (e[t.project] = (e[t.project] || 0) + t.totalHours, e), {}), ye = Math.max(...Object.values(J), 1), Y = l(() => [...k].sort((e, t) => t.date.localeCompare(e.date)), [k]), { page: be, pageSize: X, offset: Z, setPage: Q } = ce({ initialPageSize: 8 }), xe = Y.slice(Z, Z + X), $ = (e) => {
186
+ me(e ?? null), j.openModal();
187
+ }, Se = async (e) => {
188
+ let t = c(e, "employeeId"), n = A.find((e) => e.id === t);
189
+ await fe({
190
+ id: ne(),
108
191
  employeeId: t,
109
192
  employeeName: n ? `${n.firstName} ${n.lastName}` : "",
110
- date: a(e, "date"),
111
- clockIn: a(e, "clockIn"),
112
- clockOut: a(e, "clockOut"),
113
- totalHours: i(e, "totalHours"),
114
- overtime: i(e, "overtime"),
115
- project: a(e, "project"),
116
- status: a(e, "status") || "pending"
193
+ date: c(e, "date"),
194
+ clockIn: c(e, "clockIn"),
195
+ clockOut: c(e, "clockOut"),
196
+ totalHours: s(e, "totalHours"),
197
+ overtime: s(e, "overtime"),
198
+ project: c(e, "project"),
199
+ status: c(e, "status") || "pending",
200
+ billable: te(e, "billable")
117
201
  });
118
- }, X = async (e) => {
119
- let t = P.context;
120
- t && await M(t.id, {
121
- clockOut: a(e, "clockOut"),
122
- totalHours: i(e, "totalHours"),
123
- overtime: i(e, "overtime"),
124
- status: a(e, "status") || t.status
202
+ }, Ce = async (e) => {
203
+ let t = M.context;
204
+ t && await pe(t.id, {
205
+ clockOut: c(e, "clockOut"),
206
+ totalHours: s(e, "totalHours"),
207
+ overtime: s(e, "overtime"),
208
+ status: c(e, "status") || t.status
125
209
  });
126
- }, Z = P.context ? {
127
- clockOut: P.context.clockOut,
128
- totalHours: P.context.totalHours,
129
- overtime: P.context.overtime,
130
- status: P.context.status
210
+ }, we = {
211
+ billable: !0,
212
+ ...N ? {
213
+ employeeId: N.employeeId,
214
+ date: N.date
215
+ } : {}
216
+ }, Te = M.context ? {
217
+ clockOut: M.context.clockOut,
218
+ totalHours: M.context.totalHours,
219
+ overtime: M.context.overtime,
220
+ status: M.context.status
131
221
  } : void 0;
132
- return /* @__PURE__ */ m("div", {
222
+ return /* @__PURE__ */ g("div", {
133
223
  className: "space-y-6 p-6",
134
224
  children: [
135
- /* @__PURE__ */ m("div", {
136
- className: "flex items-center justify-between",
137
- children: [/* @__PURE__ */ m("div", { children: [
138
- /* @__PURE__ */ p("h1", {
225
+ /* @__PURE__ */ g("div", {
226
+ className: "flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between",
227
+ children: [/* @__PURE__ */ g("div", { children: [
228
+ /* @__PURE__ */ h("h1", {
139
229
  className: "text-2xl font-semibold",
140
- children: /* @__PURE__ */ p(C, { children: "Time Tracking" })
230
+ children: /* @__PURE__ */ h(oe, { children: "Time Tracking" })
141
231
  }),
142
- /* @__PURE__ */ p("p", {
232
+ /* @__PURE__ */ h("p", {
143
233
  className: "text-sm text-text-secondary",
144
234
  children: "Monitor employee work hours and overtime"
145
235
  }),
146
- /* @__PURE__ */ p(w, {
236
+ /* @__PURE__ */ h(se, {
147
237
  className: "mt-1",
148
238
  children: "Track hours and attendance across your team — use it to monitor logged time, overtime, and timesheet approvals."
149
239
  })
150
- ] }), /* @__PURE__ */ m(g, {
151
- size: "sm",
152
- onClick: () => N.openModal(),
153
- children: [/* @__PURE__ */ p(f, { className: "h-4 w-4 mr-1" }), "Add Entry"]
240
+ ] }), /* @__PURE__ */ g("div", {
241
+ className: "flex items-center gap-2",
242
+ children: [/* @__PURE__ */ g("div", {
243
+ className: "flex items-center gap-1 rounded-lg border border-border-subtle p-1",
244
+ children: [
245
+ /* @__PURE__ */ h(v, {
246
+ variant: "ghost",
247
+ size: "sm",
248
+ className: "h-8 w-8 p-0",
249
+ "aria-label": "Previous week",
250
+ onClick: () => R((e) => e - 1),
251
+ children: /* @__PURE__ */ h(ie, { className: "h-4 w-4" })
252
+ }),
253
+ /* @__PURE__ */ h("span", {
254
+ className: "min-w-[8.5rem] text-center text-sm font-medium tabular-nums",
255
+ children: W
256
+ }),
257
+ /* @__PURE__ */ h(v, {
258
+ variant: "ghost",
259
+ size: "sm",
260
+ className: "h-8 w-8 p-0",
261
+ "aria-label": "Next week",
262
+ onClick: () => R((e) => e + 1),
263
+ children: /* @__PURE__ */ h(d, { className: "h-4 w-4" })
264
+ })
265
+ ]
266
+ }), /* @__PURE__ */ g(v, {
267
+ size: "sm",
268
+ onClick: () => $(),
269
+ children: [/* @__PURE__ */ h(m, { className: "h-4 w-4 mr-1" }), "Log Time"]
270
+ })]
154
271
  })]
155
272
  }),
156
- /* @__PURE__ */ m("div", {
273
+ /* @__PURE__ */ g("div", {
157
274
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
158
275
  children: [
159
- /* @__PURE__ */ m(S, {
160
- treatment: "glass",
161
- glow: !0,
162
- className: "border-border-seam",
163
- children: [/* @__PURE__ */ m(b, {
164
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
165
- children: [/* @__PURE__ */ p(x, {
166
- className: "text-sm font-medium",
167
- children: "Total Hours"
168
- }), /* @__PURE__ */ p(l, { className: "h-4 w-4 text-text-secondary" })]
169
- }), /* @__PURE__ */ m(v, { children: [/* @__PURE__ */ p("div", {
170
- className: "text-2xl font-bold tabular-nums",
171
- children: L.toFixed(1)
172
- }), /* @__PURE__ */ p("p", {
173
- className: "text-xs text-text-secondary",
174
- children: "All logged hours"
175
- })] })]
276
+ /* @__PURE__ */ h(r, {
277
+ label: "Total Hours",
278
+ value: he.toFixed(1),
279
+ icon: /* @__PURE__ */ h(f, { className: "h-4 w-4" })
176
280
  }),
177
- /* @__PURE__ */ m(S, {
178
- treatment: "metric",
179
- className: "border-border-seam",
180
- children: [/* @__PURE__ */ m(b, {
181
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
182
- children: [/* @__PURE__ */ p(x, {
183
- className: "text-sm font-medium",
184
- children: "Overtime"
185
- }), /* @__PURE__ */ p(f, { className: "h-4 w-4 text-status-warning-text" })]
186
- }), /* @__PURE__ */ m(v, { children: [/* @__PURE__ */ m("div", {
187
- className: "text-2xl font-bold tabular-nums",
188
- children: [R.toFixed(1), "h"]
189
- }), /* @__PURE__ */ p("p", {
190
- className: "text-xs text-text-secondary",
191
- children: "Extra hours logged"
192
- })] })]
281
+ /* @__PURE__ */ h(r, {
282
+ label: "Overtime",
283
+ value: `${ge.toFixed(1)}h`,
284
+ icon: /* @__PURE__ */ h(m, { className: "h-4 w-4" })
193
285
  }),
194
- /* @__PURE__ */ m(S, {
195
- treatment: "metric",
196
- className: "border-border-seam",
197
- children: [/* @__PURE__ */ m(b, {
198
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
199
- children: [/* @__PURE__ */ p(x, {
200
- className: "text-sm font-medium",
201
- children: "Approved"
202
- }), /* @__PURE__ */ p(c, { className: "h-4 w-4 text-status-success-text" })]
203
- }), /* @__PURE__ */ m(v, { children: [/* @__PURE__ */ p("div", {
204
- className: "text-2xl font-bold tabular-nums",
205
- children: z
206
- }), /* @__PURE__ */ p("p", {
207
- className: "text-xs text-text-secondary",
208
- children: "time entries"
209
- })] })]
286
+ /* @__PURE__ */ h(r, {
287
+ label: "Approved",
288
+ value: _e,
289
+ icon: /* @__PURE__ */ h(re, { className: "h-4 w-4" })
210
290
  }),
211
- /* @__PURE__ */ m(S, {
212
- treatment: "metric",
213
- className: "border-border-seam",
214
- children: [/* @__PURE__ */ m(b, {
215
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
216
- children: [/* @__PURE__ */ p(x, {
217
- className: "text-sm font-medium",
218
- children: "Pending"
219
- }), /* @__PURE__ */ p(l, { className: "h-4 w-4 text-status-warning-text" })]
220
- }), /* @__PURE__ */ m(v, { children: [/* @__PURE__ */ p("div", {
221
- className: "text-2xl font-bold tabular-nums",
222
- children: B
223
- }), /* @__PURE__ */ p("p", {
224
- className: "text-xs text-text-secondary",
225
- children: "awaiting approval"
226
- })] })]
291
+ /* @__PURE__ */ h(r, {
292
+ label: "Pending",
293
+ value: ve,
294
+ icon: /* @__PURE__ */ h(f, { className: "h-4 w-4" })
227
295
  })
228
296
  ]
229
297
  }),
230
- /* @__PURE__ */ m("div", {
298
+ /* @__PURE__ */ g("div", {
299
+ className: "grid gap-4 xl:grid-cols-[minmax(0,2.2fr)_minmax(0,1fr)]",
300
+ children: [/* @__PURE__ */ g(y, { children: [/* @__PURE__ */ g(S, { children: [/* @__PURE__ */ h(C, { children: "Timesheet" }), /* @__PURE__ */ g(x, { children: [W, " · tap a day cell to log time for that person"] })] }), /* @__PURE__ */ g(b, { children: [/* @__PURE__ */ h("div", {
301
+ className: "overflow-x-auto",
302
+ children: /* @__PURE__ */ g("table", {
303
+ className: "w-full min-w-[46rem] border-collapse text-sm",
304
+ children: [/* @__PURE__ */ h("thead", { children: /* @__PURE__ */ g("tr", {
305
+ className: "border-b border-border-subtle text-xs text-text-secondary",
306
+ children: [
307
+ /* @__PURE__ */ h("th", {
308
+ className: "px-2 py-2 text-left font-medium",
309
+ children: "Employee"
310
+ }),
311
+ V.map((e) => /* @__PURE__ */ h("th", {
312
+ className: "px-1 py-2 text-center font-medium",
313
+ children: e.label
314
+ }, e.iso)),
315
+ /* @__PURE__ */ h("th", {
316
+ className: "px-2 py-2 text-right font-medium",
317
+ children: "Total"
318
+ }),
319
+ /* @__PURE__ */ h("th", {
320
+ className: "px-2 py-2 text-center font-medium",
321
+ children: "Status"
322
+ })
323
+ ]
324
+ }) }), /* @__PURE__ */ h("tbody", { children: K.map((e) => /* @__PURE__ */ g("tr", {
325
+ className: "border-b border-border-subtle/60",
326
+ children: [
327
+ /* @__PURE__ */ h("td", {
328
+ className: "px-2 py-2",
329
+ children: /* @__PURE__ */ g("div", {
330
+ className: "flex items-center gap-2",
331
+ children: [/* @__PURE__ */ h(i, {
332
+ people: [{
333
+ name: e.name,
334
+ avatarUrl: e.avatar
335
+ }],
336
+ size: 28
337
+ }), /* @__PURE__ */ h("span", {
338
+ className: "truncate font-medium",
339
+ children: e.name
340
+ })]
341
+ })
342
+ }),
343
+ V.map((t) => {
344
+ let n = e.perDay.get(t.iso) ?? 0;
345
+ return /* @__PURE__ */ h("td", {
346
+ className: "px-1 py-2 text-center",
347
+ children: /* @__PURE__ */ h("button", {
348
+ type: "button",
349
+ onClick: () => $({
350
+ employeeId: e.employeeId,
351
+ date: t.iso
352
+ }),
353
+ className: `w-full rounded-md border px-1 py-1.5 text-xs tabular-nums transition-colors ${n > 0 ? "border-border-subtle text-text-primary hover:bg-bg-sunken" : "border-transparent text-text-muted hover:border-border-subtle hover:bg-bg-sunken"}`,
354
+ "aria-label": `Log time for ${e.name} on ${t.label}`,
355
+ children: n.toFixed(1)
356
+ })
357
+ }, t.iso);
358
+ }),
359
+ /* @__PURE__ */ h("td", {
360
+ className: "px-2 py-2 text-right font-semibold tabular-nums",
361
+ children: e.total.toFixed(1)
362
+ }),
363
+ /* @__PURE__ */ h("td", {
364
+ className: "px-2 py-2 text-center",
365
+ children: /* @__PURE__ */ h(_, {
366
+ variant: e.status === "approved" ? "default" : e.status === "pending" ? "secondary" : "destructive",
367
+ className: "text-[10px]",
368
+ children: t(e.status)
369
+ })
370
+ })
371
+ ]
372
+ }, e.employeeId)) })]
373
+ })
374
+ }), K.length === 0 && /* @__PURE__ */ g("p", {
375
+ className: "py-8 text-center text-sm text-text-secondary",
376
+ children: [
377
+ "No time logged for ",
378
+ W,
379
+ "."
380
+ ]
381
+ })] })] }), /* @__PURE__ */ g(y, { children: [/* @__PURE__ */ g(S, { children: [/* @__PURE__ */ h(C, { children: "Billable split" }), /* @__PURE__ */ g(x, { children: ["Billable vs non-billable hours for ", W] })] }), /* @__PURE__ */ h(b, {
382
+ className: "flex flex-col items-center",
383
+ children: q ? /* @__PURE__ */ h(n, {
384
+ segments: q.segments,
385
+ centerLabel: q.centerValue,
386
+ centerCaption: q.caption,
387
+ valueFormatter: (e) => `${e.toFixed(1)}h`,
388
+ title: "Billable vs non-billable hours"
389
+ }) : /* @__PURE__ */ h("p", {
390
+ className: "py-10 text-center text-sm text-text-secondary",
391
+ children: "No hours logged this week."
392
+ })
393
+ })] })]
394
+ }),
395
+ /* @__PURE__ */ g("div", {
231
396
  className: "grid gap-4 md:grid-cols-2",
232
- children: [/* @__PURE__ */ m(_, { children: [/* @__PURE__ */ m(b, { children: [/* @__PURE__ */ p(x, { children: "Hours by Project" }), /* @__PURE__ */ p(y, { children: "Time allocation across active projects" })] }), /* @__PURE__ */ p(v, {
397
+ children: [/* @__PURE__ */ g(y, { children: [/* @__PURE__ */ g(S, { children: [/* @__PURE__ */ h(C, { children: "Hours by Project" }), /* @__PURE__ */ g(x, { children: ["Time allocation for ", W] })] }), /* @__PURE__ */ g(b, {
233
398
  className: "space-y-3",
234
- children: Object.entries(V).sort(([, e], [, t]) => t - e).map(([e, t]) => /* @__PURE__ */ m("div", {
399
+ children: [Object.entries(J).sort(([, e], [, t]) => t - e).map(([e, t]) => /* @__PURE__ */ g("div", {
235
400
  className: "flex items-center gap-3",
236
401
  children: [
237
- /* @__PURE__ */ p("span", {
238
- className: "w-48 text-sm truncate",
402
+ /* @__PURE__ */ h("span", {
403
+ className: "w-40 truncate text-sm",
239
404
  children: e
240
405
  }),
241
- /* @__PURE__ */ p("div", {
242
- className: "flex-1 h-4 bg-bg-sunken rounded overflow-hidden",
243
- children: /* @__PURE__ */ p("div", {
244
- className: "h-4 bg-action-primary-bg rounded",
245
- style: { width: `${Math.round(t / H * 100)}%` }
406
+ /* @__PURE__ */ h("div", {
407
+ className: "h-4 flex-1 overflow-hidden rounded bg-bg-sunken",
408
+ children: /* @__PURE__ */ h("div", {
409
+ className: "h-4 rounded bg-action-primary-bg",
410
+ style: { width: `${Math.round(t / ye * 100)}%` }
246
411
  })
247
412
  }),
248
- /* @__PURE__ */ m("span", {
249
- className: "text-sm font-medium w-14 text-right",
413
+ /* @__PURE__ */ g("span", {
414
+ className: "w-14 text-right text-sm font-medium tabular-nums",
250
415
  children: [t.toFixed(1), "h"]
251
416
  })
252
417
  ]
253
- }, e))
254
- })] }), /* @__PURE__ */ m(_, { children: [/* @__PURE__ */ m(b, { children: [/* @__PURE__ */ p(x, { children: "Recent Activity" }), /* @__PURE__ */ p(y, { children: "Latest employee clock-in/out entries" })] }), /* @__PURE__ */ m(v, {
418
+ }, e)), Object.keys(J).length === 0 && /* @__PURE__ */ h("p", {
419
+ className: "py-6 text-center text-sm text-text-secondary",
420
+ children: "No project hours this week."
421
+ })]
422
+ })] }), /* @__PURE__ */ g(y, { children: [/* @__PURE__ */ g(S, { children: [/* @__PURE__ */ h(C, { children: "Recent Activity" }), /* @__PURE__ */ h(x, { children: "Latest employee clock-in/out entries" })] }), /* @__PURE__ */ g(b, {
255
423
  className: "space-y-3",
256
424
  children: [
257
- J.map((e) => /* @__PURE__ */ m("div", {
425
+ xe.map((e) => /* @__PURE__ */ g("div", {
258
426
  className: "flex items-center justify-between rounded border p-3",
259
- children: [/* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
260
- className: "text-sm font-medium",
261
- children: e.employeeName
262
- }), /* @__PURE__ */ p("p", {
263
- className: "text-xs text-text-secondary",
264
- children: e.project
265
- })] }), /* @__PURE__ */ m("div", {
427
+ children: [/* @__PURE__ */ g("div", {
428
+ className: "flex items-center gap-2.5",
429
+ children: [/* @__PURE__ */ h(i, {
430
+ people: [{
431
+ name: e.employeeName,
432
+ avatarUrl: P.get(e.employeeId)?.avatar
433
+ }],
434
+ size: 30
435
+ }), /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("p", {
436
+ className: "text-sm font-medium",
437
+ children: e.employeeName
438
+ }), /* @__PURE__ */ h("p", {
439
+ className: "text-xs text-text-secondary",
440
+ children: e.project
441
+ })] })]
442
+ }), /* @__PURE__ */ g("div", {
266
443
  className: "flex items-center gap-3",
267
444
  children: [
268
- /* @__PURE__ */ m("div", {
445
+ /* @__PURE__ */ g("div", {
269
446
  className: "text-right text-xs",
270
- children: [/* @__PURE__ */ m("div", {
447
+ children: [/* @__PURE__ */ g("div", {
271
448
  className: "flex items-center gap-1",
272
- children: [/* @__PURE__ */ p(u, { className: "h-3 w-3 text-status-success-text" }), e.clockIn]
273
- }), /* @__PURE__ */ m("div", {
449
+ children: [/* @__PURE__ */ h(ae, { className: "h-3 w-3 text-status-success-text" }), e.clockIn]
450
+ }), /* @__PURE__ */ g("div", {
274
451
  className: "flex items-center gap-1",
275
- children: [/* @__PURE__ */ p(d, { className: "h-3 w-3 text-status-error-text" }), e.clockOut]
452
+ children: [/* @__PURE__ */ h(p, { className: "h-3 w-3 text-status-error-text" }), e.clockOut]
276
453
  })]
277
454
  }),
278
- /* @__PURE__ */ m("div", {
455
+ /* @__PURE__ */ g("div", {
279
456
  className: "text-right",
280
- children: [/* @__PURE__ */ m("p", {
457
+ children: [/* @__PURE__ */ g("p", {
281
458
  className: "text-sm font-medium",
282
459
  children: [e.totalHours, "h"]
283
- }), e.overtime > 0 && /* @__PURE__ */ m("p", {
460
+ }), e.overtime > 0 && /* @__PURE__ */ g("p", {
284
461
  className: "text-xs text-status-warning-text",
285
462
  children: [
286
463
  "+",
@@ -289,53 +466,54 @@ function k() {
289
466
  ]
290
467
  })]
291
468
  }),
292
- /* @__PURE__ */ p(h, {
469
+ /* @__PURE__ */ h(_, {
293
470
  variant: e.status === "approved" ? "default" : "secondary",
294
471
  className: "text-[10px]",
295
472
  children: t(e.status)
296
473
  }),
297
- /* @__PURE__ */ p(g, {
474
+ /* @__PURE__ */ h(v, {
298
475
  variant: "ghost",
299
476
  size: "sm",
300
477
  className: "h-8 w-8 p-0",
301
478
  "aria-label": `Clock out ${e.employeeName}`,
302
- onClick: () => P.openModal(e),
303
- children: /* @__PURE__ */ p(d, { className: "h-4 w-4" })
479
+ onClick: () => M.openModal(e),
480
+ children: /* @__PURE__ */ h(p, { className: "h-4 w-4" })
304
481
  })
305
482
  ]
306
483
  })]
307
484
  }, e.id)),
308
- U.length === 0 && /* @__PURE__ */ p("p", {
485
+ Y.length === 0 && /* @__PURE__ */ h("p", {
309
486
  className: "py-6 text-center text-sm text-text-secondary",
310
487
  children: "No time entries logged yet."
311
488
  }),
312
- U.length > G && /* @__PURE__ */ p(T, {
313
- page: W,
314
- pageSize: G,
315
- totalItems: U.length,
316
- onPageChange: q
489
+ Y.length > X && /* @__PURE__ */ h(w, {
490
+ page: be,
491
+ pageSize: X,
492
+ totalItems: Y.length,
493
+ onPageChange: Q
317
494
  })
318
495
  ]
319
496
  })] })]
320
497
  }),
321
- /* @__PURE__ */ p(n, {
322
- open: N.open,
323
- onOpenChange: N.onOpenChange,
324
- title: "Add time entry",
498
+ /* @__PURE__ */ h(a, {
499
+ open: j.open,
500
+ onOpenChange: j.onOpenChange,
501
+ title: "Log time",
325
502
  description: "Log a work session for a team member.",
326
503
  fields: I,
504
+ initialValues: we,
327
505
  submitLabel: "Add entry",
328
- onSubmit: Y
506
+ onSubmit: Se
329
507
  }),
330
- /* @__PURE__ */ p(n, {
331
- open: P.open,
332
- onOpenChange: P.onOpenChange,
508
+ /* @__PURE__ */ h(a, {
509
+ open: M.open,
510
+ onOpenChange: M.onOpenChange,
333
511
  title: "Clock out",
334
- description: P.context ? `Record clock-out for ${P.context.employeeName}.` : void 0,
335
- fields: O,
336
- initialValues: Z,
512
+ description: M.context ? `Record clock-out for ${M.context.employeeName}.` : void 0,
513
+ fields: le,
514
+ initialValues: Te,
337
515
  submitLabel: "Save",
338
- onSubmit: X
516
+ onSubmit: Ce
339
517
  })
340
518
  ]
341
519
  });