@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,134 +1,324 @@
1
1
  import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
- import { Eye as t, Pin as n, Plus as r } from "lucide-react";
3
- import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
- import { Badge as o, Button as s, Card as c, CardContent as l, CardHeader as u, CardTitle as d, GlassCard as f, GradientText as p, IllustratedEmptyState as m, PagePurpose as h } from "@burdenoff/fe-libs/ui";
2
+ import { FormModal as t, useFormModal as n } from "../components/forms/FormModal.js";
3
+ import { useState as r } from "react";
4
+ import { Eye as i, Pencil as a, Pin as o, Plus as s, Trash2 as c } from "lucide-react";
5
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
6
+ import { AlertDialog as d, AlertDialogAction as f, AlertDialogCancel as p, AlertDialogContent as m, AlertDialogDescription as h, AlertDialogFooter as g, AlertDialogHeader as _, AlertDialogTitle as v, Badge as y, Button as b, Card as x, CardContent as S, CardHeader as C, CardTitle as w, GlassCard as T, GradientText as E, IllustratedEmptyState as D, PagePurpose as O } from "@burdenoff/fe-libs/ui";
7
+ import { useGlobalUi as k } from "@burdenoff/fe-libs/shared/providers/shell";
5
8
  //#region src/crewfoundry/pages/CommunicationsAnnouncementsPagePage.tsx
6
- function g() {
7
- let { announcements: g } = e(), _ = g.filter((e) => e.isPinned), v = g.filter((e) => !e.isPinned);
8
- return /* @__PURE__ */ a("div", {
9
+ var A = [
10
+ {
11
+ name: "title",
12
+ label: "Title",
13
+ type: "text",
14
+ required: !0,
15
+ colSpan: 2
16
+ },
17
+ {
18
+ name: "content",
19
+ label: "Content",
20
+ type: "textarea",
21
+ required: !0,
22
+ colSpan: 2
23
+ },
24
+ {
25
+ name: "author",
26
+ label: "Author",
27
+ type: "text",
28
+ required: !0
29
+ },
30
+ {
31
+ name: "authorRole",
32
+ label: "Author Role",
33
+ type: "text",
34
+ required: !0
35
+ },
36
+ {
37
+ name: "category",
38
+ label: "Category",
39
+ type: "select",
40
+ required: !0,
41
+ options: [
42
+ {
43
+ label: "General",
44
+ value: "general"
45
+ },
46
+ {
47
+ label: "HR",
48
+ value: "hr"
49
+ },
50
+ {
51
+ label: "IT",
52
+ value: "it"
53
+ },
54
+ {
55
+ label: "Emergency",
56
+ value: "emergency"
57
+ },
58
+ {
59
+ label: "Event",
60
+ value: "event"
61
+ }
62
+ ],
63
+ placeholder: "Select a category"
64
+ },
65
+ {
66
+ name: "priority",
67
+ label: "Priority",
68
+ type: "select",
69
+ required: !0,
70
+ options: [
71
+ {
72
+ label: "Low",
73
+ value: "low"
74
+ },
75
+ {
76
+ label: "Medium",
77
+ value: "medium"
78
+ },
79
+ {
80
+ label: "High",
81
+ value: "high"
82
+ },
83
+ {
84
+ label: "Urgent",
85
+ value: "urgent"
86
+ }
87
+ ],
88
+ placeholder: "Select a priority"
89
+ },
90
+ {
91
+ name: "tags",
92
+ label: "Tags",
93
+ type: "tags",
94
+ placeholder: "Add a tag and press Enter"
95
+ },
96
+ {
97
+ name: "isPinned",
98
+ label: "Pin to top",
99
+ type: "switch"
100
+ }
101
+ ], j = A.filter((e) => e.name !== "author" && e.name !== "authorRole");
102
+ function M() {
103
+ let { announcements: M, addAnnouncement: N, updateAnnouncement: P, removeAnnouncement: F } = e(), { showToast: I } = k(), L = n(), [R, z] = r(null), [B, V] = r(!1), H = L.context, U = M.filter((e) => e.isPinned), W = M.filter((e) => !e.isPinned), G = async (e) => {
104
+ let t = Array.isArray(e.tags) ? e.tags : [];
105
+ if (H) {
106
+ await P(H.id, {
107
+ title: String(e.title),
108
+ content: String(e.content),
109
+ category: String(e.category),
110
+ priority: String(e.priority),
111
+ isPinned: !!e.isPinned,
112
+ tags: t
113
+ }), I("Announcement updated", "success");
114
+ return;
115
+ }
116
+ await N({
117
+ id: crypto.randomUUID(),
118
+ title: String(e.title),
119
+ content: String(e.content),
120
+ author: String(e.author),
121
+ authorRole: String(e.authorRole),
122
+ category: String(e.category),
123
+ priority: String(e.priority),
124
+ isPinned: !!e.isPinned,
125
+ createdAt: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
126
+ viewCount: 0,
127
+ tags: t
128
+ }), I("Announcement published", "success");
129
+ }, K = async () => {
130
+ if (R) {
131
+ V(!0);
132
+ try {
133
+ await F(R.id), I("Announcement deleted", "success"), z(null);
134
+ } catch (e) {
135
+ I(e instanceof Error ? e.message : "Unable to delete announcement", "error");
136
+ } finally {
137
+ V(!1);
138
+ }
139
+ }
140
+ }, q = H ? {
141
+ title: H.title,
142
+ content: H.content,
143
+ category: H.category,
144
+ priority: H.priority,
145
+ tags: H.tags,
146
+ isPinned: H.isPinned
147
+ } : void 0, J = (e) => /* @__PURE__ */ u("div", {
148
+ className: "flex gap-1",
149
+ children: [/* @__PURE__ */ l(b, {
150
+ variant: "ghost",
151
+ size: "icon",
152
+ className: "h-7 w-7",
153
+ "aria-label": `Edit announcement ${e.title}`,
154
+ onClick: () => L.openModal(e),
155
+ children: /* @__PURE__ */ l(a, { className: "h-3.5 w-3.5" })
156
+ }), /* @__PURE__ */ l(b, {
157
+ variant: "ghost",
158
+ size: "icon",
159
+ className: "h-7 w-7 text-status-error-text",
160
+ "aria-label": `Delete announcement ${e.title}`,
161
+ onClick: () => z(e),
162
+ children: /* @__PURE__ */ l(c, { className: "h-3.5 w-3.5" })
163
+ })]
164
+ });
165
+ return /* @__PURE__ */ u("div", {
9
166
  className: "space-y-6 p-6",
10
167
  children: [
11
- /* @__PURE__ */ a("div", {
168
+ /* @__PURE__ */ u("div", {
12
169
  className: "flex items-center justify-between",
13
- children: [/* @__PURE__ */ a("div", { children: [
14
- /* @__PURE__ */ i("h1", {
170
+ children: [/* @__PURE__ */ u("div", { children: [
171
+ /* @__PURE__ */ l("h1", {
15
172
  className: "text-2xl font-semibold",
16
- children: /* @__PURE__ */ i(p, { children: "Announcements" })
173
+ children: /* @__PURE__ */ l(E, { children: "Announcements" })
17
174
  }),
18
- /* @__PURE__ */ a("p", {
175
+ /* @__PURE__ */ u("p", {
19
176
  className: "text-sm text-text-secondary",
20
- children: [g.length, " company announcements"]
177
+ children: [M.length, " company announcements"]
21
178
  }),
22
- /* @__PURE__ */ i(h, {
179
+ /* @__PURE__ */ l(O, {
23
180
  className: "mt-1",
24
181
  children: "Broadcast company-wide news and updates so everyone stays informed — post announcements here when you have something the whole team needs to see."
25
182
  })
26
- ] }), /* @__PURE__ */ a(s, {
183
+ ] }), /* @__PURE__ */ u(b, {
27
184
  size: "sm",
28
- children: [/* @__PURE__ */ i(r, { className: "h-4 w-4 mr-1" }), "New Announcement"]
185
+ onClick: () => L.openModal(),
186
+ children: [/* @__PURE__ */ l(s, { className: "h-4 w-4 mr-1" }), "New Announcement"]
29
187
  })]
30
188
  }),
31
- _.length > 0 && /* @__PURE__ */ a("div", {
189
+ U.length > 0 && /* @__PURE__ */ u("div", {
32
190
  className: "space-y-3",
33
- children: [/* @__PURE__ */ a("h2", {
191
+ children: [/* @__PURE__ */ u("h2", {
34
192
  className: "text-sm font-medium flex items-center gap-1",
35
- children: [/* @__PURE__ */ i(n, { className: "h-4 w-4" }), "Pinned"]
36
- }), _.map((e) => /* @__PURE__ */ a(f, {
193
+ children: [/* @__PURE__ */ l(o, { className: "h-4 w-4" }), "Pinned"]
194
+ }), U.map((e) => /* @__PURE__ */ u(T, {
37
195
  treatment: "glass",
38
196
  glow: !0,
39
- children: [/* @__PURE__ */ i(u, { children: /* @__PURE__ */ a("div", {
197
+ children: [/* @__PURE__ */ l(C, { children: /* @__PURE__ */ u("div", {
40
198
  className: "flex items-center justify-between",
41
- children: [/* @__PURE__ */ i(d, {
199
+ children: [/* @__PURE__ */ l(w, {
42
200
  className: "text-base",
43
201
  children: e.title
44
- }), /* @__PURE__ */ a("div", {
45
- className: "flex gap-1",
46
- children: [/* @__PURE__ */ i(o, {
47
- variant: e.priority === "urgent" ? "destructive" : e.priority === "high" ? "default" : "secondary",
48
- className: "text-[10px]",
49
- children: e.priority
50
- }), /* @__PURE__ */ i(o, {
51
- variant: "outline",
52
- className: "text-[10px]",
53
- children: e.category
54
- })]
202
+ }), /* @__PURE__ */ u("div", {
203
+ className: "flex items-center gap-2",
204
+ children: [/* @__PURE__ */ u("div", {
205
+ className: "flex gap-1",
206
+ children: [/* @__PURE__ */ l(y, {
207
+ variant: e.priority === "urgent" ? "destructive" : e.priority === "high" ? "default" : "secondary",
208
+ className: "text-[10px]",
209
+ children: e.priority
210
+ }), /* @__PURE__ */ l(y, {
211
+ variant: "outline",
212
+ className: "text-[10px]",
213
+ children: e.category
214
+ })]
215
+ }), J(e)]
55
216
  })]
56
- }) }), /* @__PURE__ */ a(l, { children: [/* @__PURE__ */ i("p", {
217
+ }) }), /* @__PURE__ */ u(S, { children: [/* @__PURE__ */ l("p", {
57
218
  className: "text-sm text-text-secondary",
58
219
  children: e.content
59
- }), /* @__PURE__ */ a("div", {
220
+ }), /* @__PURE__ */ u("div", {
60
221
  className: "flex items-center justify-between mt-3 text-xs text-text-secondary",
61
- children: [/* @__PURE__ */ a("span", { children: [
222
+ children: [/* @__PURE__ */ u("span", { children: [
62
223
  e.author,
63
224
  " · ",
64
225
  e.authorRole
65
- ] }), /* @__PURE__ */ a("div", {
226
+ ] }), /* @__PURE__ */ u("div", {
66
227
  className: "flex items-center gap-3",
67
- children: [/* @__PURE__ */ a("span", {
228
+ children: [/* @__PURE__ */ u("span", {
68
229
  className: "flex items-center gap-1",
69
- children: [/* @__PURE__ */ i(t, { className: "h-3 w-3" }), e.viewCount]
70
- }), /* @__PURE__ */ i("span", { children: e.createdAt })]
230
+ children: [/* @__PURE__ */ l(i, { className: "h-3 w-3" }), e.viewCount]
231
+ }), /* @__PURE__ */ l("span", { children: e.createdAt })]
71
232
  })]
72
233
  })] })]
73
234
  }, e.id))]
74
235
  }),
75
- g.length === 0 && /* @__PURE__ */ i(m, {
236
+ M.length === 0 && /* @__PURE__ */ l(D, {
76
237
  illustration: "empty-notifications",
77
238
  title: "No announcements yet",
78
239
  description: "Post an announcement to share news with the whole team."
79
240
  }),
80
- /* @__PURE__ */ i("div", {
241
+ /* @__PURE__ */ l("div", {
81
242
  className: "space-y-3",
82
- children: v.map((e) => /* @__PURE__ */ a(c, { children: [/* @__PURE__ */ i(u, { children: /* @__PURE__ */ a("div", {
243
+ children: W.map((e) => /* @__PURE__ */ u(x, { children: [/* @__PURE__ */ l(C, { children: /* @__PURE__ */ u("div", {
83
244
  className: "flex items-center justify-between",
84
- children: [/* @__PURE__ */ i(d, {
245
+ children: [/* @__PURE__ */ l(w, {
85
246
  className: "text-base",
86
247
  children: e.title
87
- }), /* @__PURE__ */ a("div", {
88
- className: "flex gap-1",
89
- children: [/* @__PURE__ */ i(o, {
90
- variant: e.priority === "urgent" ? "destructive" : e.priority === "high" ? "default" : "secondary",
91
- className: "text-[10px]",
92
- children: e.priority
93
- }), /* @__PURE__ */ i(o, {
94
- variant: "outline",
95
- className: "text-[10px]",
96
- children: e.category
97
- })]
248
+ }), /* @__PURE__ */ u("div", {
249
+ className: "flex items-center gap-2",
250
+ children: [/* @__PURE__ */ u("div", {
251
+ className: "flex gap-1",
252
+ children: [/* @__PURE__ */ l(y, {
253
+ variant: e.priority === "urgent" ? "destructive" : e.priority === "high" ? "default" : "secondary",
254
+ className: "text-[10px]",
255
+ children: e.priority
256
+ }), /* @__PURE__ */ l(y, {
257
+ variant: "outline",
258
+ className: "text-[10px]",
259
+ children: e.category
260
+ })]
261
+ }), J(e)]
98
262
  })]
99
- }) }), /* @__PURE__ */ a(l, { children: [
100
- /* @__PURE__ */ i("p", {
263
+ }) }), /* @__PURE__ */ u(S, { children: [
264
+ /* @__PURE__ */ l("p", {
101
265
  className: "text-sm text-text-secondary",
102
266
  children: e.content
103
267
  }),
104
- /* @__PURE__ */ a("div", {
268
+ /* @__PURE__ */ u("div", {
105
269
  className: "flex items-center justify-between mt-3 text-xs text-text-secondary",
106
- children: [/* @__PURE__ */ a("span", { children: [
270
+ children: [/* @__PURE__ */ u("span", { children: [
107
271
  e.author,
108
272
  " · ",
109
273
  e.authorRole
110
- ] }), /* @__PURE__ */ a("div", {
274
+ ] }), /* @__PURE__ */ u("div", {
111
275
  className: "flex items-center gap-3",
112
- children: [/* @__PURE__ */ a("span", {
276
+ children: [/* @__PURE__ */ u("span", {
113
277
  className: "flex items-center gap-1",
114
- children: [/* @__PURE__ */ i(t, { className: "h-3 w-3" }), e.viewCount]
115
- }), /* @__PURE__ */ i("span", { children: e.createdAt })]
278
+ children: [/* @__PURE__ */ l(i, { className: "h-3 w-3" }), e.viewCount]
279
+ }), /* @__PURE__ */ l("span", { children: e.createdAt })]
116
280
  })]
117
281
  }),
118
- /* @__PURE__ */ i("div", {
282
+ /* @__PURE__ */ l("div", {
119
283
  className: "flex gap-1 mt-2",
120
- children: e.tags.map((e) => /* @__PURE__ */ i(o, {
284
+ children: e.tags.map((e) => /* @__PURE__ */ l(y, {
121
285
  variant: "outline",
122
286
  className: "text-[9px]",
123
287
  children: e
124
288
  }, e))
125
289
  })
126
290
  ] })] }, e.id))
291
+ }),
292
+ /* @__PURE__ */ l(t, {
293
+ open: L.open,
294
+ onOpenChange: L.onOpenChange,
295
+ title: H ? "Edit Announcement" : "New Announcement",
296
+ description: H ? "Update this announcement for the whole team." : "Share news and updates across the company.",
297
+ fields: H ? j : A,
298
+ initialValues: q,
299
+ submitLabel: H ? "Save changes" : "Publish",
300
+ onSubmit: G
301
+ }),
302
+ /* @__PURE__ */ l(d, {
303
+ open: R !== null,
304
+ onOpenChange: (e) => {
305
+ e || z(null);
306
+ },
307
+ children: /* @__PURE__ */ u(m, { children: [/* @__PURE__ */ u(_, { children: [/* @__PURE__ */ l(v, { children: "Delete announcement?" }), /* @__PURE__ */ l(h, { children: R ? `"${R.title}" will be permanently removed. This cannot be undone.` : "" })] }), /* @__PURE__ */ u(g, { children: [/* @__PURE__ */ l(p, {
308
+ disabled: B,
309
+ children: "Cancel"
310
+ }), /* @__PURE__ */ l(f, {
311
+ onClick: (e) => {
312
+ e.preventDefault(), K();
313
+ },
314
+ disabled: B,
315
+ children: B ? "Deleting…" : "Delete"
316
+ })] })] })
127
317
  })
128
318
  ]
129
319
  });
130
320
  }
131
321
  //#endregion
132
- export { g as CommunicationsAnnouncementsPagePage };
322
+ export { M as CommunicationsAnnouncementsPagePage };
133
323
 
134
324
  //# sourceMappingURL=CommunicationsAnnouncementsPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CommunicationsAnnouncementsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CommunicationsAnnouncementsPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Eye, Pin, Plus } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function CommunicationsAnnouncementsPagePage() {\n const { announcements } = useCrewFoundryStore();\n const pinned = announcements.filter((a) => a.isPinned);\n const regular = announcements.filter((a) => !a.isPinned);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Announcements</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {announcements.length} company announcements\n </p>\n <PagePurpose className=\"mt-1\">Broadcast company-wide news and updates so everyone stays informed — post announcements here when you have something the whole team needs to see.</PagePurpose>\n </div>\n <Button size=\"sm\">\n <Plus className=\"h-4 w-4 mr-1\" />\n New Announcement\n </Button>\n </div>\n {pinned.length > 0 && (\n <div className=\"space-y-3\">\n <h2 className=\"text-sm font-medium flex items-center gap-1\">\n <Pin className=\"h-4 w-4\" />\n Pinned\n </h2>\n {pinned.map((ann) => (\n <GlassCard key={ann.id} treatment=\"glass\" glow>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{ann.title}</CardTitle>\n <div className=\"flex gap-1\">\n <Badge\n variant={\n ann.priority === 'urgent'\n ? 'destructive'\n : ann.priority === 'high'\n ? 'default'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {ann.priority}\n </Badge>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {ann.category}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-text-secondary\">{ann.content}</p>\n <div className=\"flex items-center justify-between mt-3 text-xs text-text-secondary\">\n <span>\n {ann.author} · {ann.authorRole}\n </span>\n <div className=\"flex items-center gap-3\">\n <span className=\"flex items-center gap-1\">\n <Eye className=\"h-3 w-3\" />\n {ann.viewCount}\n </span>\n <span>{ann.createdAt}</span>\n </div>\n </div>\n </CardContent>\n </GlassCard>\n ))}\n </div>\n )}\n {announcements.length === 0 && (\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title=\"No announcements yet\"\n description=\"Post an announcement to share news with the whole team.\"\n />\n )}\n <div className=\"space-y-3\">\n {regular.map((ann) => (\n <Card key={ann.id}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{ann.title}</CardTitle>\n <div className=\"flex gap-1\">\n <Badge\n variant={\n ann.priority === 'urgent'\n ? 'destructive'\n : ann.priority === 'high'\n ? 'default'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {ann.priority}\n </Badge>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {ann.category}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-text-secondary\">{ann.content}</p>\n <div className=\"flex items-center justify-between mt-3 text-xs text-text-secondary\">\n <span>\n {ann.author} · {ann.authorRole}\n </span>\n <div className=\"flex items-center gap-3\">\n <span className=\"flex items-center gap-1\">\n <Eye className=\"h-3 w-3\" />\n {ann.viewCount}\n </span>\n <span>{ann.createdAt}</span>\n </div>\n </div>\n <div className=\"flex gap-1 mt-2\">\n {ann.tags.map((t) => (\n <Badge key={t} variant=\"outline\" className=\"text-[9px]\">\n {t}\n </Badge>\n ))}\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CommunicationsAnnouncementsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CommunicationsAnnouncementsPagePage.tsx"],"sourcesContent":["import {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { Eye, Pencil, Pin, Plus, Trash2 } from 'lucide-react';\nimport { useState } from 'react';\nimport { useCrewFoundryStore, type Announcement } from '../store/crewfoundryStore';\nimport { FormModal, useFormModal, type FieldConfig, type FormValues } from '../components/forms/FormModal';\n\nconst CATEGORY_OPTIONS = [\n { label: 'General', value: 'general' },\n { label: 'HR', value: 'hr' },\n { label: 'IT', value: 'it' },\n { label: 'Emergency', value: 'emergency' },\n { label: 'Event', value: 'event' },\n];\n\nconst PRIORITY_OPTIONS = [\n { label: 'Low', value: 'low' },\n { label: 'Medium', value: 'medium' },\n { label: 'High', value: 'high' },\n { label: 'Urgent', value: 'urgent' },\n];\n\nconst CREATE_FIELDS: FieldConfig[] = [\n { name: 'title', label: 'Title', type: 'text', required: true, colSpan: 2 },\n { name: 'content', label: 'Content', type: 'textarea', required: true, colSpan: 2 },\n { name: 'author', label: 'Author', type: 'text', required: true },\n { name: 'authorRole', label: 'Author Role', type: 'text', required: true },\n {\n name: 'category',\n label: 'Category',\n type: 'select',\n required: true,\n options: CATEGORY_OPTIONS,\n placeholder: 'Select a category',\n },\n {\n name: 'priority',\n label: 'Priority',\n type: 'select',\n required: true,\n options: PRIORITY_OPTIONS,\n placeholder: 'Select a priority',\n },\n { name: 'tags', label: 'Tags', type: 'tags', placeholder: 'Add a tag and press Enter' },\n { name: 'isPinned', label: 'Pin to top', type: 'switch' },\n];\n\n// Author/role are immutable after creation (they are not part of the update\n// input), so the edit form omits them.\nconst EDIT_FIELDS: FieldConfig[] = CREATE_FIELDS.filter(\n (field) => field.name !== 'author' && field.name !== 'authorRole'\n);\n\nexport function CommunicationsAnnouncementsPagePage() {\n const { announcements, addAnnouncement, updateAnnouncement, removeAnnouncement } =\n useCrewFoundryStore();\n const { showToast } = useGlobalUi();\n const form = useFormModal<Announcement>();\n const [deleteTarget, setDeleteTarget] = useState<Announcement | null>(null);\n const [deleting, setDeleting] = useState(false);\n\n const editing = form.context;\n const pinned = announcements.filter((a) => a.isPinned);\n const regular = announcements.filter((a) => !a.isPinned);\n\n const handleSubmit = async (values: FormValues) => {\n const tags = Array.isArray(values.tags) ? values.tags : [];\n if (editing) {\n await updateAnnouncement(editing.id, {\n title: String(values.title),\n content: String(values.content),\n category: String(values.category) as Announcement['category'],\n priority: String(values.priority) as Announcement['priority'],\n isPinned: Boolean(values.isPinned),\n tags,\n });\n showToast('Announcement updated', 'success');\n return;\n }\n await addAnnouncement({\n id: crypto.randomUUID(),\n title: String(values.title),\n content: String(values.content),\n author: String(values.author),\n authorRole: String(values.authorRole),\n category: String(values.category) as Announcement['category'],\n priority: String(values.priority) as Announcement['priority'],\n isPinned: Boolean(values.isPinned),\n createdAt: new Date().toISOString().slice(0, 10),\n viewCount: 0,\n tags,\n });\n showToast('Announcement published', 'success');\n };\n\n const confirmDelete = async () => {\n if (!deleteTarget) {\n return;\n }\n setDeleting(true);\n try {\n await removeAnnouncement(deleteTarget.id);\n showToast('Announcement deleted', 'success');\n setDeleteTarget(null);\n } catch (error) {\n showToast(error instanceof Error ? error.message : 'Unable to delete announcement', 'error');\n } finally {\n setDeleting(false);\n }\n };\n\n const initialValues: FormValues | undefined = editing\n ? {\n title: editing.title,\n content: editing.content,\n category: editing.category,\n priority: editing.priority,\n tags: editing.tags,\n isPinned: editing.isPinned,\n }\n : undefined;\n\n const renderActions = (announcement: Announcement) => (\n <div className=\"flex gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7\"\n aria-label={`Edit announcement ${announcement.title}`}\n onClick={() => form.openModal(announcement)}\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-7 w-7 text-status-error-text\"\n aria-label={`Delete announcement ${announcement.title}`}\n onClick={() => setDeleteTarget(announcement)}\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n );\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Announcements</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {announcements.length} company announcements\n </p>\n <PagePurpose className=\"mt-1\">Broadcast company-wide news and updates so everyone stays informed — post announcements here when you have something the whole team needs to see.</PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => form.openModal()}>\n <Plus className=\"h-4 w-4 mr-1\" />\n New Announcement\n </Button>\n </div>\n {pinned.length > 0 && (\n <div className=\"space-y-3\">\n <h2 className=\"text-sm font-medium flex items-center gap-1\">\n <Pin className=\"h-4 w-4\" />\n Pinned\n </h2>\n {pinned.map((ann) => (\n <GlassCard key={ann.id} treatment=\"glass\" glow>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{ann.title}</CardTitle>\n <div className=\"flex items-center gap-2\">\n <div className=\"flex gap-1\">\n <Badge\n variant={\n ann.priority === 'urgent'\n ? 'destructive'\n : ann.priority === 'high'\n ? 'default'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {ann.priority}\n </Badge>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {ann.category}\n </Badge>\n </div>\n {renderActions(ann)}\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-text-secondary\">{ann.content}</p>\n <div className=\"flex items-center justify-between mt-3 text-xs text-text-secondary\">\n <span>\n {ann.author} · {ann.authorRole}\n </span>\n <div className=\"flex items-center gap-3\">\n <span className=\"flex items-center gap-1\">\n <Eye className=\"h-3 w-3\" />\n {ann.viewCount}\n </span>\n <span>{ann.createdAt}</span>\n </div>\n </div>\n </CardContent>\n </GlassCard>\n ))}\n </div>\n )}\n {announcements.length === 0 && (\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title=\"No announcements yet\"\n description=\"Post an announcement to share news with the whole team.\"\n />\n )}\n <div className=\"space-y-3\">\n {regular.map((ann) => (\n <Card key={ann.id}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{ann.title}</CardTitle>\n <div className=\"flex items-center gap-2\">\n <div className=\"flex gap-1\">\n <Badge\n variant={\n ann.priority === 'urgent'\n ? 'destructive'\n : ann.priority === 'high'\n ? 'default'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {ann.priority}\n </Badge>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {ann.category}\n </Badge>\n </div>\n {renderActions(ann)}\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-text-secondary\">{ann.content}</p>\n <div className=\"flex items-center justify-between mt-3 text-xs text-text-secondary\">\n <span>\n {ann.author} · {ann.authorRole}\n </span>\n <div className=\"flex items-center gap-3\">\n <span className=\"flex items-center gap-1\">\n <Eye className=\"h-3 w-3\" />\n {ann.viewCount}\n </span>\n <span>{ann.createdAt}</span>\n </div>\n </div>\n <div className=\"flex gap-1 mt-2\">\n {ann.tags.map((t) => (\n <Badge key={t} variant=\"outline\" className=\"text-[9px]\">\n {t}\n </Badge>\n ))}\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n\n <FormModal\n open={form.open}\n onOpenChange={form.onOpenChange}\n title={editing ? 'Edit Announcement' : 'New Announcement'}\n description={\n editing\n ? 'Update this announcement for the whole team.'\n : 'Share news and updates across the company.'\n }\n fields={editing ? EDIT_FIELDS : CREATE_FIELDS}\n initialValues={initialValues}\n submitLabel={editing ? 'Save changes' : 'Publish'}\n onSubmit={handleSubmit}\n />\n\n <AlertDialog\n open={deleteTarget !== null}\n onOpenChange={(open) => {\n if (!open) {\n setDeleteTarget(null);\n }\n }}\n >\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete announcement?</AlertDialogTitle>\n <AlertDialogDescription>\n {deleteTarget\n ? `\"${deleteTarget.title}\" will be permanently removed. This cannot be undone.`\n : ''}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={deleting}>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={(event) => {\n event.preventDefault();\n void confirmDelete();\n }}\n disabled={deleting}\n >\n {deleting ? 'Deleting…' : 'Delete'}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -3,26 +3,27 @@ import { useMemo as t } from "react";
3
3
  import { Clock as n, Phone as r, PhoneIncoming as i, PhoneMissed as a, PhoneOutgoing as o } from "lucide-react";
4
4
  import { jsx as s, jsxs as c } from "react/jsx-runtime";
5
5
  import { Badge as l, Button as u, Card as d, CardContent as f, CardHeader as p, CardTitle as m, GlassCard as h, GradientText as g, PagePurpose as _ } from "@burdenoff/fe-libs/ui";
6
+ import { useGlobalUi as v } from "@burdenoff/fe-libs/shared/providers/shell";
6
7
  //#region src/crewfoundry/pages/CommunicationsCallsPagePage.tsx
7
- var v = (e) => {
8
+ var y = (e) => {
8
9
  let t = Math.max(e, 0), n = Math.floor(t / 60), r = t % 60;
9
10
  return n > 0 ? `${String(n).padStart(2, "0")}:${String(r).padStart(2, "0")}` : `00:${String(r).padStart(2, "0")}`;
10
- }, y = ({ type: e }) => e === "incoming" ? /* @__PURE__ */ s(i, { className: "h-4 w-4 text-status-success-text" }) : e === "outgoing" ? /* @__PURE__ */ s(o, { className: "h-4 w-4 text-status-info-text" }) : /* @__PURE__ */ s(a, { className: "h-4 w-4 text-status-error-text" });
11
- function b() {
12
- let { employees: i, teams: o } = e(), b = t(() => i.slice(0, 10).map((e, t) => {
13
- let n = t % 5 == 0 ? "missed" : t % 2 == 0 ? "outgoing" : "incoming", r = o[t % Math.max(o.length, 1)], i = Math.round((e.performanceScore + t) * 3);
11
+ }, b = ({ type: e }) => e === "incoming" ? /* @__PURE__ */ s(i, { className: "h-4 w-4 text-status-success-text" }) : e === "outgoing" ? /* @__PURE__ */ s(o, { className: "h-4 w-4 text-status-info-text" }) : /* @__PURE__ */ s(a, { className: "h-4 w-4 text-status-error-text" });
12
+ function x() {
13
+ let { showToast: i } = v(), { employees: o, teams: x } = e(), S = () => i("Voice calling is on the CrewFoundry roadmap — coming soon.", "info"), C = t(() => o.slice(0, 10).map((e, t) => {
14
+ let n = t % 5 == 0 ? "missed" : t % 2 == 0 ? "outgoing" : "incoming", r = x[t % Math.max(x.length, 1)], i = Math.round((e.performanceScore + t) * 3);
14
15
  return {
15
16
  id: `call-${e.id}`,
16
17
  name: `${e.firstName} ${e.lastName}`.trim(),
17
18
  type: n,
18
- duration: n === "missed" ? "-" : v(i),
19
+ duration: n === "missed" ? "-" : y(i),
19
20
  time: new Date(e.startDate).toLocaleDateString(),
20
21
  topic: r ? `${r.name} check-in` : `${e.department} operations update`
21
22
  };
22
- }), [i, o]), x = b.filter((e) => e.duration !== "-"), S = x.length ? Math.round(x.map((e) => {
23
+ }), [o, x]), w = C.filter((e) => e.duration !== "-"), T = w.length ? Math.round(w.map((e) => {
23
24
  let [t, n] = e.duration.split(":").map(Number);
24
25
  return t * 60 + n;
25
- }).reduce((e, t) => e + t, 0) / x.length) : 0;
26
+ }).reduce((e, t) => e + t, 0) / w.length) : 0;
26
27
  return /* @__PURE__ */ c("div", {
27
28
  className: "space-y-6 p-6",
28
29
  children: [
@@ -41,9 +42,17 @@ function b() {
41
42
  className: "mt-1",
42
43
  children: "Review your call history and start new voice calls with colleagues — a quick way to reach teammates without leaving CrewFoundry."
43
44
  })
44
- ] }), /* @__PURE__ */ c(u, {
45
- size: "sm",
46
- children: [/* @__PURE__ */ s(r, { className: "mr-1 h-4 w-4" }), "New Call"]
45
+ ] }), /* @__PURE__ */ c("div", {
46
+ className: "flex items-center gap-2",
47
+ children: [/* @__PURE__ */ s(l, {
48
+ variant: "secondary",
49
+ className: "text-[10px]",
50
+ children: "Coming soon"
51
+ }), /* @__PURE__ */ c(u, {
52
+ size: "sm",
53
+ onClick: S,
54
+ children: [/* @__PURE__ */ s(r, { className: "mr-1 h-4 w-4" }), "New Call"]
55
+ })]
47
56
  })]
48
57
  }),
49
58
  /* @__PURE__ */ c("div", {
@@ -61,7 +70,7 @@ function b() {
61
70
  }), /* @__PURE__ */ s(r, { className: "h-4 w-4 text-text-secondary" })]
62
71
  }), /* @__PURE__ */ c(f, { children: [/* @__PURE__ */ s("div", {
63
72
  className: "text-2xl font-bold tabular-nums",
64
- children: b.length
73
+ children: C.length
65
74
  }), /* @__PURE__ */ s("p", {
66
75
  className: "text-xs text-text-secondary",
67
76
  children: "Live call activity"
@@ -78,7 +87,7 @@ function b() {
78
87
  }), /* @__PURE__ */ s(a, { className: "h-4 w-4 text-status-error-text" })]
79
88
  }), /* @__PURE__ */ s(f, { children: /* @__PURE__ */ s("div", {
80
89
  className: "text-2xl font-bold tabular-nums",
81
- children: b.filter((e) => e.type === "missed").length
90
+ children: C.filter((e) => e.type === "missed").length
82
91
  }) })]
83
92
  }),
84
93
  /* @__PURE__ */ c(h, {
@@ -92,7 +101,7 @@ function b() {
92
101
  }), /* @__PURE__ */ s(n, { className: "h-4 w-4 text-text-secondary" })]
93
102
  }), /* @__PURE__ */ c(f, { children: [/* @__PURE__ */ s("div", {
94
103
  className: "text-2xl font-bold tabular-nums",
95
- children: v(S)
104
+ children: y(T)
96
105
  }), /* @__PURE__ */ s("p", {
97
106
  className: "text-xs text-text-secondary",
98
107
  children: "minutes"
@@ -102,11 +111,11 @@ function b() {
102
111
  }),
103
112
  /* @__PURE__ */ c(d, { children: [/* @__PURE__ */ s(p, { children: /* @__PURE__ */ s(m, { children: "Call History" }) }), /* @__PURE__ */ s(f, {
104
113
  className: "space-y-3",
105
- children: b.map((e) => /* @__PURE__ */ c("div", {
114
+ children: C.map((e) => /* @__PURE__ */ c("div", {
106
115
  className: "flex items-center justify-between rounded border p-3",
107
116
  children: [/* @__PURE__ */ c("div", {
108
117
  className: "flex items-center gap-3",
109
- children: [/* @__PURE__ */ s(y, { type: e.type }), /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("p", {
118
+ children: [/* @__PURE__ */ s(b, { type: e.type }), /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("p", {
110
119
  className: "text-sm font-medium",
111
120
  children: e.name
112
121
  }), /* @__PURE__ */ s("p", {
@@ -129,6 +138,8 @@ function b() {
129
138
  variant: "outline",
130
139
  size: "sm",
131
140
  className: "h-7",
141
+ "aria-label": `Call ${e.name} (coming soon)`,
142
+ onClick: S,
132
143
  children: /* @__PURE__ */ s(r, { className: "h-3 w-3" })
133
144
  })
134
145
  ]
@@ -139,6 +150,6 @@ function b() {
139
150
  });
140
151
  }
141
152
  //#endregion
142
- export { b as CommunicationsCallsPagePage };
153
+ export { x as CommunicationsCallsPagePage };
143
154
 
144
155
  //# sourceMappingURL=CommunicationsCallsPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CommunicationsCallsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CommunicationsCallsPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Clock, Phone, PhoneIncoming, PhoneMissed, PhoneOutgoing } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype CallType = 'incoming' | 'outgoing' | 'missed';\n\ntype CallRecord = {\n id: string;\n name: string;\n type: CallType;\n duration: string;\n time: string;\n topic: string;\n};\n\nconst formatDuration = (minutes: number): string => {\n const safeMinutes = Math.max(minutes, 0);\n const hours = Math.floor(safeMinutes / 60);\n const mins = safeMinutes % 60;\n if (hours > 0) {\n return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`;\n }\n return `00:${String(mins).padStart(2, '0')}`;\n};\n\nconst CallIcon = ({ type }: { type: CallType }) => {\n if (type === 'incoming') return <PhoneIncoming className=\"h-4 w-4 text-status-success-text\" />;\n if (type === 'outgoing') return <PhoneOutgoing className=\"h-4 w-4 text-status-info-text\" />;\n return <PhoneMissed className=\"h-4 w-4 text-status-error-text\" />;\n};\n\nexport function CommunicationsCallsPagePage() {\n const { employees, teams } = useCrewFoundryStore();\n\n const callHistory = useMemo<CallRecord[]>(() => {\n const seed = employees.slice(0, 10);\n return seed.map((employee, index) => {\n const callType: CallType =\n index % 5 === 0 ? 'missed' : index % 2 === 0 ? 'outgoing' : 'incoming';\n const topicSource = teams[index % Math.max(teams.length, 1)];\n const durationMinutes = Math.round((employee.performanceScore + index) * 3);\n return {\n id: `call-${employee.id}`,\n name: `${employee.firstName} ${employee.lastName}`.trim(),\n type: callType,\n duration: callType === 'missed' ? '-' : formatDuration(durationMinutes),\n time: new Date(employee.startDate).toLocaleDateString(),\n topic: topicSource\n ? `${topicSource.name} check-in`\n : `${employee.department} operations update`,\n };\n });\n }, [employees, teams]);\n\n const connectedCalls = callHistory.filter((call) => call.duration !== '-');\n const averageMinutes = connectedCalls.length\n ? Math.round(\n connectedCalls\n .map((call) => {\n const [hours, minutes] = call.duration.split(':').map(Number);\n return hours * 60 + minutes;\n })\n .reduce((total, value) => total + value, 0) / connectedCalls.length\n )\n : 0;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Calls</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Voice call history and quick dial</p>\n <PagePurpose className=\"mt-1\">Review your call history and start new voice calls with colleagues — a quick way to reach teammates without leaving CrewFoundry.</PagePurpose>\n </div>\n <Button size=\"sm\">\n <Phone className=\"mr-1 h-4 w-4\" />\n New Call\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\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\">Total Calls</CardTitle>\n <Phone className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{callHistory.length}</div>\n <p className=\"text-xs text-text-secondary\">Live call activity</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\">Missed</CardTitle>\n <PhoneMissed className=\"h-4 w-4 text-status-error-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {callHistory.filter((call) => call.type === 'missed').length}\n </div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Avg Duration</CardTitle>\n <Clock className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{formatDuration(averageMinutes)}</div>\n <p className=\"text-xs text-text-secondary\">minutes</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Call History</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {callHistory.map((call) => (\n <div key={call.id} className=\"flex items-center justify-between rounded border p-3\">\n <div className=\"flex items-center gap-3\">\n <CallIcon type={call.type} />\n <div>\n <p className=\"text-sm font-medium\">{call.name}</p>\n <p className=\"text-xs text-text-secondary\">{call.topic}</p>\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n <span className=\"text-xs text-text-secondary\">{call.time}</span>\n <Badge\n variant={call.type === 'missed' ? 'destructive' : 'outline'}\n className=\"text-[10px]\"\n >\n {call.duration === '-' ? 'missed' : call.duration}\n </Badge>\n <Button variant=\"outline\" size=\"sm\" className=\"h-7\">\n <Phone className=\"h-3 w-3\" />\n </Button>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CommunicationsCallsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CommunicationsCallsPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Clock, Phone, PhoneIncoming, PhoneMissed, PhoneOutgoing } from 'lucide-react';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype CallType = 'incoming' | 'outgoing' | 'missed';\n\ntype CallRecord = {\n id: string;\n name: string;\n type: CallType;\n duration: string;\n time: string;\n topic: string;\n};\n\nconst formatDuration = (minutes: number): string => {\n const safeMinutes = Math.max(minutes, 0);\n const hours = Math.floor(safeMinutes / 60);\n const mins = safeMinutes % 60;\n if (hours > 0) {\n return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`;\n }\n return `00:${String(mins).padStart(2, '0')}`;\n};\n\nconst CallIcon = ({ type }: { type: CallType }) => {\n if (type === 'incoming') return <PhoneIncoming className=\"h-4 w-4 text-status-success-text\" />;\n if (type === 'outgoing') return <PhoneOutgoing className=\"h-4 w-4 text-status-info-text\" />;\n return <PhoneMissed className=\"h-4 w-4 text-status-error-text\" />;\n};\n\nexport function CommunicationsCallsPagePage() {\n const { showToast } = useGlobalUi();\n const { employees, teams } = useCrewFoundryStore();\n\n // Voice calling is a planned surface — no telephony backend exists yet, so the\n // dial controls honestly signal their roadmap status.\n const notifyComingSoon = () =>\n showToast('Voice calling is on the CrewFoundry roadmap — coming soon.', 'info');\n\n const callHistory = useMemo<CallRecord[]>(() => {\n const seed = employees.slice(0, 10);\n return seed.map((employee, index) => {\n const callType: CallType =\n index % 5 === 0 ? 'missed' : index % 2 === 0 ? 'outgoing' : 'incoming';\n const topicSource = teams[index % Math.max(teams.length, 1)];\n const durationMinutes = Math.round((employee.performanceScore + index) * 3);\n return {\n id: `call-${employee.id}`,\n name: `${employee.firstName} ${employee.lastName}`.trim(),\n type: callType,\n duration: callType === 'missed' ? '-' : formatDuration(durationMinutes),\n time: new Date(employee.startDate).toLocaleDateString(),\n topic: topicSource\n ? `${topicSource.name} check-in`\n : `${employee.department} operations update`,\n };\n });\n }, [employees, teams]);\n\n const connectedCalls = callHistory.filter((call) => call.duration !== '-');\n const averageMinutes = connectedCalls.length\n ? Math.round(\n connectedCalls\n .map((call) => {\n const [hours, minutes] = call.duration.split(':').map(Number);\n return hours * 60 + minutes;\n })\n .reduce((total, value) => total + value, 0) / connectedCalls.length\n )\n : 0;\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Calls</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Voice call history and quick dial</p>\n <PagePurpose className=\"mt-1\">Review your call history and start new voice calls with colleagues — a quick way to reach teammates without leaving CrewFoundry.</PagePurpose>\n </div>\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n Coming soon\n </Badge>\n <Button size=\"sm\" onClick={notifyComingSoon}>\n <Phone className=\"mr-1 h-4 w-4\" />\n New Call\n </Button>\n </div>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\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\">Total Calls</CardTitle>\n <Phone className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{callHistory.length}</div>\n <p className=\"text-xs text-text-secondary\">Live call activity</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\">Missed</CardTitle>\n <PhoneMissed className=\"h-4 w-4 text-status-error-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {callHistory.filter((call) => call.type === 'missed').length}\n </div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Avg Duration</CardTitle>\n <Clock className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{formatDuration(averageMinutes)}</div>\n <p className=\"text-xs text-text-secondary\">minutes</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Call History</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {callHistory.map((call) => (\n <div key={call.id} className=\"flex items-center justify-between rounded border p-3\">\n <div className=\"flex items-center gap-3\">\n <CallIcon type={call.type} />\n <div>\n <p className=\"text-sm font-medium\">{call.name}</p>\n <p className=\"text-xs text-text-secondary\">{call.topic}</p>\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n <span className=\"text-xs text-text-secondary\">{call.time}</span>\n <Badge\n variant={call.type === 'missed' ? 'destructive' : 'outline'}\n className=\"text-[10px]\"\n >\n {call.duration === '-' ? 'missed' : call.duration}\n </Badge>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-7\"\n aria-label={`Call ${call.name} (coming soon)`}\n onClick={notifyComingSoon}\n >\n <Phone className=\"h-3 w-3\" />\n </Button>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}