@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.
- package/dist/crewfoundry/components/forms/ConfirmDialog.js +43 -0
- package/dist/crewfoundry/components/forms/ConfirmDialog.js.map +1 -0
- package/dist/crewfoundry/components/forms/FormModal.js +220 -0
- package/dist/crewfoundry/components/forms/FormModal.js.map +1 -0
- package/dist/crewfoundry/components/forms/formValues.js +20 -0
- package/dist/crewfoundry/components/forms/formValues.js.map +1 -0
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +255 -65
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +28 -17
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js +57 -53
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +32 -23
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +44 -29
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +183 -57
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +214 -92
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +165 -131
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +163 -133
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +269 -54
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +225 -78
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +213 -59
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +287 -90
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +49 -47
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +166 -59
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js +274 -83
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +198 -88
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +216 -88
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +216 -66
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +6 -7
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +83 -68
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +167 -46
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +75 -55
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +152 -79
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +75 -63
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +3 -1
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +235 -87
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +199 -86
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js +21 -40
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +117 -45
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +249 -90
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +47 -45
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +262 -133
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +144 -77
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js +306 -51
- package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,134 +1,324 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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__ */
|
|
168
|
+
/* @__PURE__ */ u("div", {
|
|
12
169
|
className: "flex items-center justify-between",
|
|
13
|
-
children: [/* @__PURE__ */
|
|
14
|
-
/* @__PURE__ */
|
|
170
|
+
children: [/* @__PURE__ */ u("div", { children: [
|
|
171
|
+
/* @__PURE__ */ l("h1", {
|
|
15
172
|
className: "text-2xl font-semibold",
|
|
16
|
-
children: /* @__PURE__ */
|
|
173
|
+
children: /* @__PURE__ */ l(E, { children: "Announcements" })
|
|
17
174
|
}),
|
|
18
|
-
/* @__PURE__ */
|
|
175
|
+
/* @__PURE__ */ u("p", {
|
|
19
176
|
className: "text-sm text-text-secondary",
|
|
20
|
-
children: [
|
|
177
|
+
children: [M.length, " company announcements"]
|
|
21
178
|
}),
|
|
22
|
-
/* @__PURE__ */
|
|
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__ */
|
|
183
|
+
] }), /* @__PURE__ */ u(b, {
|
|
27
184
|
size: "sm",
|
|
28
|
-
|
|
185
|
+
onClick: () => L.openModal(),
|
|
186
|
+
children: [/* @__PURE__ */ l(s, { className: "h-4 w-4 mr-1" }), "New Announcement"]
|
|
29
187
|
})]
|
|
30
188
|
}),
|
|
31
|
-
|
|
189
|
+
U.length > 0 && /* @__PURE__ */ u("div", {
|
|
32
190
|
className: "space-y-3",
|
|
33
|
-
children: [/* @__PURE__ */
|
|
191
|
+
children: [/* @__PURE__ */ u("h2", {
|
|
34
192
|
className: "text-sm font-medium flex items-center gap-1",
|
|
35
|
-
children: [/* @__PURE__ */
|
|
36
|
-
}),
|
|
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__ */
|
|
197
|
+
children: [/* @__PURE__ */ l(C, { children: /* @__PURE__ */ u("div", {
|
|
40
198
|
className: "flex items-center justify-between",
|
|
41
|
-
children: [/* @__PURE__ */
|
|
199
|
+
children: [/* @__PURE__ */ l(w, {
|
|
42
200
|
className: "text-base",
|
|
43
201
|
children: e.title
|
|
44
|
-
}), /* @__PURE__ */
|
|
45
|
-
className: "flex gap-
|
|
46
|
-
children: [/* @__PURE__ */
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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__ */
|
|
217
|
+
}) }), /* @__PURE__ */ u(S, { children: [/* @__PURE__ */ l("p", {
|
|
57
218
|
className: "text-sm text-text-secondary",
|
|
58
219
|
children: e.content
|
|
59
|
-
}), /* @__PURE__ */
|
|
220
|
+
}), /* @__PURE__ */ u("div", {
|
|
60
221
|
className: "flex items-center justify-between mt-3 text-xs text-text-secondary",
|
|
61
|
-
children: [/* @__PURE__ */
|
|
222
|
+
children: [/* @__PURE__ */ u("span", { children: [
|
|
62
223
|
e.author,
|
|
63
224
|
" · ",
|
|
64
225
|
e.authorRole
|
|
65
|
-
] }), /* @__PURE__ */
|
|
226
|
+
] }), /* @__PURE__ */ u("div", {
|
|
66
227
|
className: "flex items-center gap-3",
|
|
67
|
-
children: [/* @__PURE__ */
|
|
228
|
+
children: [/* @__PURE__ */ u("span", {
|
|
68
229
|
className: "flex items-center gap-1",
|
|
69
|
-
children: [/* @__PURE__ */ i
|
|
70
|
-
}), /* @__PURE__ */
|
|
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
|
-
|
|
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__ */
|
|
241
|
+
/* @__PURE__ */ l("div", {
|
|
81
242
|
className: "space-y-3",
|
|
82
|
-
children:
|
|
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__ */
|
|
245
|
+
children: [/* @__PURE__ */ l(w, {
|
|
85
246
|
className: "text-base",
|
|
86
247
|
children: e.title
|
|
87
|
-
}), /* @__PURE__ */
|
|
88
|
-
className: "flex gap-
|
|
89
|
-
children: [/* @__PURE__ */
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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__ */
|
|
100
|
-
/* @__PURE__ */
|
|
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__ */
|
|
268
|
+
/* @__PURE__ */ u("div", {
|
|
105
269
|
className: "flex items-center justify-between mt-3 text-xs text-text-secondary",
|
|
106
|
-
children: [/* @__PURE__ */
|
|
270
|
+
children: [/* @__PURE__ */ u("span", { children: [
|
|
107
271
|
e.author,
|
|
108
272
|
" · ",
|
|
109
273
|
e.authorRole
|
|
110
|
-
] }), /* @__PURE__ */
|
|
274
|
+
] }), /* @__PURE__ */ u("div", {
|
|
111
275
|
className: "flex items-center gap-3",
|
|
112
|
-
children: [/* @__PURE__ */
|
|
276
|
+
children: [/* @__PURE__ */ u("span", {
|
|
113
277
|
className: "flex items-center gap-1",
|
|
114
|
-
children: [/* @__PURE__ */ i
|
|
115
|
-
}), /* @__PURE__ */
|
|
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__ */
|
|
282
|
+
/* @__PURE__ */ l("div", {
|
|
119
283
|
className: "flex gap-1 mt-2",
|
|
120
|
-
children: e.tags.map((e) => /* @__PURE__ */
|
|
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 {
|
|
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":";;;;;AAeA,SAAgB,IAAsC;CACpD,IAAM,EAAE,qBAAkB,GAAqB,EACzC,IAAS,EAAc,QAAQ,MAAM,EAAE,SAAS,EAChD,IAAU,EAAc,QAAQ,MAAM,CAAC,EAAE,SAAS;AAExD,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA;KACE,kBAAC,MAAD;MAAI,WAAU;gBACZ,kBAAC,GAAD,EAAA,UAAc,iBAA4B,CAAA;MACvC,CAAA;KACL,kBAAC,KAAD;MAAG,WAAU;gBAAb,CACG,EAAc,QAAO,yBACpB;;KACJ,kBAAC,GAAD;MAAa,WAAU;gBAAO;MAA+J,CAAA;KACzL,EAAA,CAAA,EACN,kBAAC,GAAD;KAAQ,MAAK;eAAb,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAAA,mBAE1B;OACL;;GACL,EAAO,SAAS,KACf,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,MAAD;KAAI,WAAU;eAAd,CACE,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA,EAAA,SAExB;QACJ,EAAO,KAAK,MACX,kBAAC,GAAD;KAAwB,WAAU;KAAQ,MAAA;eAA1C,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OAAW,WAAU;iBAAa,EAAI;OAAkB,CAAA,EACxD,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QACE,SACE,EAAI,aAAa,WACb,gBACA,EAAI,aAAa,SACf,YACA;QAER,WAAU;kBAET,EAAI;QACC,CAAA,EACR,kBAAC,GAAD;QAAO,SAAQ;QAAU,WAAU;kBAChC,EAAI;QACC,CAAA,CACJ;SACF;SACK,CAAA,EACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,KAAD;MAAG,WAAU;gBAA+B,EAAI;MAAY,CAAA,EAC5D,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD,EAAA,UAAA;OACG,EAAI;OAAO;OAAI,EAAI;OACf,EAAA,CAAA,EACP,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CACE,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA,EAC1B,EAAI,UACA;WACP,kBAAC,QAAD,EAAA,UAAO,EAAI,WAAiB,CAAA,CACxB;SACF;QACM,EAAA,CAAA,CACJ;OAtCI,EAAI,GAsCR,CACZ,CACE;;GAEP,EAAc,WAAW,KACxB,kBAAC,GAAD;IACE,cAAa;IACb,OAAM;IACN,aAAY;IACZ,CAAA;GAEJ,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAQ,KAAK,MACZ,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAW,WAAU;gBAAa,EAAI;MAAkB,CAAA,EACxD,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OACE,SACE,EAAI,aAAa,WACb,gBACA,EAAI,aAAa,SACf,YACA;OAER,WAAU;iBAET,EAAI;OACC,CAAA,EACR,kBAAC,GAAD;OAAO,SAAQ;OAAU,WAAU;iBAChC,EAAI;OACC,CAAA,CACJ;QACF;QACK,CAAA,EACb,kBAAC,GAAD,EAAA,UAAA;KACE,kBAAC,KAAD;MAAG,WAAU;gBAA+B,EAAI;MAAY,CAAA;KAC5D,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD,EAAA,UAAA;OACG,EAAI;OAAO;OAAI,EAAI;OACf,EAAA,CAAA,EACP,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CACE,kBAAC,GAAD,EAAK,WAAU,WAAY,CAAA,EAC1B,EAAI,UACA;WACP,kBAAC,QAAD,EAAA,UAAO,EAAI,WAAiB,CAAA,CACxB;SACF;;KACN,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAI,KAAK,KAAK,MACb,kBAAC,GAAD;OAAe,SAAQ;OAAU,WAAU;iBACxC;OACK,EAFI,EAEJ,CACR;MACE,CAAA;KACM,EAAA,CAAA,CACT,EAAA,EA7CI,EAAI,GA6CR,CACP;IACE,CAAA;GACF"}
|
|
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
|
|
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
|
-
},
|
|
11
|
-
function
|
|
12
|
-
let {
|
|
13
|
-
let n = t % 5 == 0 ? "missed" : t % 2 == 0 ? "outgoing" : "incoming", r =
|
|
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" ? "-" :
|
|
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
|
-
}), [
|
|
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) /
|
|
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(
|
|
45
|
-
|
|
46
|
-
children: [/* @__PURE__ */ s(
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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 {
|
|
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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"}
|