@burdenoff/microfe-crewfoundry 2026.625.2 → 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,41 +1,42 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
2
|
import { useMemo as t, useState as n } from "react";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { File as r, FileText as i, FolderInput as a, Image as o, Search as s, Upload as c } from "lucide-react";
|
|
4
|
+
import { useNavigate as l } from "react-router-dom";
|
|
5
|
+
import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
6
|
+
import { Badge as p, Button as m, CardContent as h, CardHeader as g, CardTitle as _, GlassCard as v, GradientText as y, IllustratedEmptyState as b, Input as x, PagePurpose as S } from "@burdenoff/fe-libs/ui";
|
|
6
7
|
//#region src/crewfoundry/pages/CommunicationsFilesPagePage.tsx
|
|
7
|
-
var
|
|
8
|
+
var C = "/files/browse", w = (e) => e === "image" ? /* @__PURE__ */ d(o, { className: "h-5 w-5 text-action-primary-bg" }) : e === "pdf" ? /* @__PURE__ */ d(i, { className: "h-5 w-5 text-status-error-text" }) : /* @__PURE__ */ d(r, { className: "h-5 w-5 text-status-info-text" }), T = (e) => {
|
|
8
9
|
let t = new Date(e);
|
|
9
10
|
return Number.isNaN(t.getTime()) ? "Unknown" : t.toISOString().split("T")[0];
|
|
10
11
|
};
|
|
11
|
-
function
|
|
12
|
-
let [
|
|
13
|
-
let e =
|
|
14
|
-
let n =
|
|
12
|
+
function E() {
|
|
13
|
+
let [r, i] = n(""), o = l(), { announcements: E, invoices: D, projects: O, employees: k } = e(), A = t(() => {
|
|
14
|
+
let e = E.slice(0, 8).map((e, t) => {
|
|
15
|
+
let n = k[t % Math.max(k.length, 1)];
|
|
15
16
|
return {
|
|
16
17
|
id: `announcement-${e.id}`,
|
|
17
18
|
name: `${e.title}.pdf`,
|
|
18
19
|
type: "pdf",
|
|
19
20
|
size: `${Math.max(1, Math.round(e.content.length / 300))}.${t % 9} MB`,
|
|
20
21
|
uploadedBy: n ? `${n.firstName} ${n.lastName}`.trim() : e.author,
|
|
21
|
-
date:
|
|
22
|
+
date: T(e.createdAt),
|
|
22
23
|
department: n?.department || "Operations"
|
|
23
24
|
};
|
|
24
|
-
}), t =
|
|
25
|
+
}), t = D.slice(0, 6).map((e, t) => ({
|
|
25
26
|
id: `invoice-${e.id}`,
|
|
26
27
|
name: `${e.number}-invoice.xlsx`,
|
|
27
28
|
type: "spreadsheet",
|
|
28
29
|
size: `${(e.amount / 1e3).toFixed(1)} MB`,
|
|
29
30
|
uploadedBy: e.clientName,
|
|
30
|
-
date:
|
|
31
|
+
date: T(e.issueDate),
|
|
31
32
|
department: t % 2 == 0 ? "Finance" : "Billing"
|
|
32
|
-
})), n =
|
|
33
|
+
})), n = O.slice(0, 6).map((e, t) => ({
|
|
33
34
|
id: `project-${e.id}`,
|
|
34
35
|
name: `${e.name}-brief.docx`,
|
|
35
36
|
type: t % 2 == 0 ? "doc" : "image",
|
|
36
37
|
size: `${(Math.max(e.tasks, 1) / 10).toFixed(1)} MB`,
|
|
37
38
|
uploadedBy: e.managerName,
|
|
38
|
-
date:
|
|
39
|
+
date: T(e.startDate),
|
|
39
40
|
department: "Projects"
|
|
40
41
|
}));
|
|
41
42
|
return [
|
|
@@ -44,104 +45,107 @@ function w() {
|
|
|
44
45
|
...n
|
|
45
46
|
];
|
|
46
47
|
}, [
|
|
47
|
-
o,
|
|
48
48
|
E,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
k,
|
|
50
|
+
D,
|
|
51
|
+
O
|
|
52
|
+
]), j = A.filter((e) => e.name.toLowerCase().includes(r.toLowerCase()));
|
|
53
|
+
return /* @__PURE__ */ f("div", {
|
|
53
54
|
className: "space-y-6 p-6",
|
|
54
55
|
children: [
|
|
55
|
-
/* @__PURE__ */
|
|
56
|
+
/* @__PURE__ */ f("div", {
|
|
56
57
|
className: "flex items-center justify-between",
|
|
57
|
-
children: [/* @__PURE__ */
|
|
58
|
-
/* @__PURE__ */
|
|
58
|
+
children: [/* @__PURE__ */ f("div", { children: [
|
|
59
|
+
/* @__PURE__ */ d("h1", {
|
|
59
60
|
className: "text-2xl font-semibold",
|
|
60
|
-
children: /* @__PURE__ */
|
|
61
|
+
children: /* @__PURE__ */ d(y, { children: "Shared Files" })
|
|
61
62
|
}),
|
|
62
|
-
/* @__PURE__ */
|
|
63
|
+
/* @__PURE__ */ f("p", {
|
|
63
64
|
className: "text-sm text-text-secondary",
|
|
64
|
-
children: [
|
|
65
|
+
children: [A.length, " files shared across teams"]
|
|
65
66
|
}),
|
|
66
|
-
/* @__PURE__ */
|
|
67
|
+
/* @__PURE__ */ d(S, {
|
|
67
68
|
className: "mt-1",
|
|
68
69
|
children: "A shared space for company documents and files — store, search, and share the resources your teams need to get work done."
|
|
69
70
|
})
|
|
70
|
-
] }), /* @__PURE__ */
|
|
71
|
+
] }), /* @__PURE__ */ f(m, {
|
|
71
72
|
size: "sm",
|
|
72
|
-
|
|
73
|
+
onClick: () => o(C),
|
|
74
|
+
children: [/* @__PURE__ */ d(c, { className: "mr-1 h-4 w-4" }), "Upload via Files"]
|
|
73
75
|
})]
|
|
74
76
|
}),
|
|
75
|
-
/* @__PURE__ */
|
|
77
|
+
/* @__PURE__ */ f("div", {
|
|
76
78
|
className: "relative max-w-sm",
|
|
77
|
-
children: [/* @__PURE__ */
|
|
79
|
+
children: [/* @__PURE__ */ d(s, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ d(x, {
|
|
78
80
|
placeholder: "Search files...",
|
|
79
81
|
className: "pl-9",
|
|
80
|
-
value:
|
|
81
|
-
onChange: (e) =>
|
|
82
|
+
value: r,
|
|
83
|
+
onChange: (e) => i(e.target.value)
|
|
82
84
|
})]
|
|
83
85
|
}),
|
|
84
|
-
/* @__PURE__ */
|
|
86
|
+
/* @__PURE__ */ f(v, {
|
|
85
87
|
treatment: "glass",
|
|
86
88
|
glow: !0,
|
|
87
89
|
className: "border-border-seam",
|
|
88
|
-
children: [/* @__PURE__ */
|
|
90
|
+
children: [/* @__PURE__ */ d(g, { children: /* @__PURE__ */ d(_, { children: "Workspace Files" }) }), /* @__PURE__ */ d(h, {
|
|
89
91
|
className: "p-0",
|
|
90
|
-
children:
|
|
92
|
+
children: j.length === 0 ? /* @__PURE__ */ d("div", {
|
|
91
93
|
className: "p-6",
|
|
92
|
-
children: /* @__PURE__ */
|
|
94
|
+
children: /* @__PURE__ */ d(b, {
|
|
93
95
|
illustration: "empty-files",
|
|
94
96
|
title: "No files found",
|
|
95
|
-
description: "Upload
|
|
97
|
+
description: "Upload files in the Files app or adjust your search to see results here."
|
|
96
98
|
})
|
|
97
|
-
}) : /* @__PURE__ */
|
|
99
|
+
}) : /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ f("div", {
|
|
98
100
|
className: "grid grid-cols-6 gap-2 border-b p-4 text-xs font-medium text-text-secondary",
|
|
99
101
|
children: [
|
|
100
|
-
/* @__PURE__ */
|
|
102
|
+
/* @__PURE__ */ d("span", {
|
|
101
103
|
className: "col-span-2",
|
|
102
104
|
children: "Name"
|
|
103
105
|
}),
|
|
104
|
-
/* @__PURE__ */
|
|
105
|
-
/* @__PURE__ */
|
|
106
|
-
/* @__PURE__ */
|
|
107
|
-
/* @__PURE__ */
|
|
106
|
+
/* @__PURE__ */ d("span", { children: "Uploaded By" }),
|
|
107
|
+
/* @__PURE__ */ d("span", { children: "Department" }),
|
|
108
|
+
/* @__PURE__ */ d("span", { children: "Date" }),
|
|
109
|
+
/* @__PURE__ */ d("span", {
|
|
108
110
|
className: "text-right",
|
|
109
111
|
children: "Size"
|
|
110
112
|
})
|
|
111
113
|
]
|
|
112
|
-
}),
|
|
114
|
+
}), j.map((e) => /* @__PURE__ */ f("div", {
|
|
113
115
|
className: "grid grid-cols-6 items-center gap-2 border-b px-4 py-3 text-sm last:border-0 hover:bg-bg-sunken/50",
|
|
114
116
|
children: [
|
|
115
|
-
/* @__PURE__ */
|
|
117
|
+
/* @__PURE__ */ f("div", {
|
|
116
118
|
className: "col-span-2 flex items-center gap-2",
|
|
117
|
-
children: [
|
|
119
|
+
children: [w(e.type), /* @__PURE__ */ d("span", {
|
|
118
120
|
className: "truncate font-medium",
|
|
119
121
|
children: e.name
|
|
120
122
|
})]
|
|
121
123
|
}),
|
|
122
|
-
/* @__PURE__ */
|
|
124
|
+
/* @__PURE__ */ d("span", {
|
|
123
125
|
className: "text-text-secondary",
|
|
124
126
|
children: e.uploadedBy
|
|
125
127
|
}),
|
|
126
|
-
/* @__PURE__ */
|
|
128
|
+
/* @__PURE__ */ d(p, {
|
|
127
129
|
variant: "outline",
|
|
128
130
|
className: "w-fit text-[10px]",
|
|
129
131
|
children: e.department
|
|
130
132
|
}),
|
|
131
|
-
/* @__PURE__ */
|
|
133
|
+
/* @__PURE__ */ d("span", {
|
|
132
134
|
className: "text-text-secondary",
|
|
133
135
|
children: e.date
|
|
134
136
|
}),
|
|
135
|
-
/* @__PURE__ */
|
|
137
|
+
/* @__PURE__ */ f("div", {
|
|
136
138
|
className: "flex items-center justify-end gap-2",
|
|
137
|
-
children: [/* @__PURE__ */
|
|
139
|
+
children: [/* @__PURE__ */ d("span", {
|
|
138
140
|
className: "text-text-secondary",
|
|
139
141
|
children: e.size
|
|
140
|
-
}), /* @__PURE__ */
|
|
142
|
+
}), /* @__PURE__ */ d(m, {
|
|
141
143
|
variant: "outline",
|
|
142
144
|
size: "sm",
|
|
143
145
|
className: "h-7",
|
|
144
|
-
|
|
146
|
+
"aria-label": `Open ${e.name} in Files`,
|
|
147
|
+
onClick: () => o(C),
|
|
148
|
+
children: /* @__PURE__ */ d(a, { className: "h-3 w-3" })
|
|
145
149
|
})]
|
|
146
150
|
})
|
|
147
151
|
]
|
|
@@ -152,6 +156,6 @@ function w() {
|
|
|
152
156
|
});
|
|
153
157
|
}
|
|
154
158
|
//#endregion
|
|
155
|
-
export {
|
|
159
|
+
export { E as CommunicationsFilesPagePage };
|
|
156
160
|
|
|
157
161
|
//# sourceMappingURL=CommunicationsFilesPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommunicationsFilesPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CommunicationsFilesPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Download, File, FileText, Image, Search, Upload } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype SharedFile = {\n id: string;\n name: string;\n type: 'pdf' | 'spreadsheet' | 'image' | 'doc';\n size: string;\n uploadedBy: string;\n date: string;\n department: string;\n};\n\nconst fileIcon = (type: SharedFile['type']) => {\n if (type === 'image') return <Image className=\"h-5 w-5 text-action-primary-bg\" />;\n if (type === 'pdf') return <FileText className=\"h-5 w-5 text-status-error-text\" />;\n return <File className=\"h-5 w-5 text-status-info-text\" />;\n};\n\nconst formatDate = (input: string): string => {\n const parsed = new Date(input);\n if (Number.isNaN(parsed.getTime())) {\n return 'Unknown';\n }\n return parsed.toISOString().split('T')[0];\n};\n\nexport function CommunicationsFilesPagePage() {\n const [search, setSearch] = useState('');\n const { announcements, invoices, projects, employees } = useCrewFoundryStore();\n\n const sharedFiles = useMemo<SharedFile[]>(() => {\n const announcementFiles = announcements.slice(0, 8).map((announcement, index) => {\n const uploader = employees[index % Math.max(employees.length, 1)];\n return {\n id: `announcement-${announcement.id}`,\n name: `${announcement.title}.pdf`,\n type: 'pdf' as const,\n size: `${Math.max(1, Math.round(announcement.content.length / 300))}.${index % 9} MB`,\n uploadedBy: uploader\n ? `${uploader.firstName} ${uploader.lastName}`.trim()\n : announcement.author,\n date: formatDate(announcement.createdAt),\n department: uploader?.department || 'Operations',\n };\n });\n\n const financeFiles = invoices.slice(0, 6).map((invoice, index) => ({\n id: `invoice-${invoice.id}`,\n name: `${invoice.number}-invoice.xlsx`,\n type: 'spreadsheet' as const,\n size: `${(invoice.amount / 1000).toFixed(1)} MB`,\n uploadedBy: invoice.clientName,\n date: formatDate(invoice.issueDate),\n department: index % 2 === 0 ? 'Finance' : 'Billing',\n }));\n\n const projectFiles = projects.slice(0, 6).map((project, index) => ({\n id: `project-${project.id}`,\n name: `${project.name}-brief.docx`,\n type: index % 2 === 0 ? ('doc' as const) : ('image' as const),\n size: `${(Math.max(project.tasks, 1) / 10).toFixed(1)} MB`,\n uploadedBy: project.managerName,\n date: formatDate(project.startDate),\n department: 'Projects',\n }));\n\n return [...announcementFiles, ...financeFiles, ...projectFiles];\n }, [announcements, employees, invoices, projects]);\n\n const filteredFiles = sharedFiles.filter((file) =>\n file.name.toLowerCase().includes(search.toLowerCase())\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>Shared Files</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {sharedFiles.length} files shared across teams\n </p>\n <PagePurpose className=\"mt-1\">A shared space for company documents and files — store, search, and share the resources your teams need to get work done.</PagePurpose>\n </div>\n <Button size=\"sm\">\n <Upload className=\"mr-1 h-4 w-4\" />\n Upload File\n </Button>\n </div>\n\n <div className=\"relative max-w-sm\">\n <Search className=\"absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <Input\n placeholder=\"Search files...\"\n className=\"pl-9\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n />\n </div>\n\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>Workspace Files</CardTitle>\n </CardHeader>\n <CardContent className=\"p-0\">\n {filteredFiles.length === 0 ? (\n <div className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"empty-files\"\n title=\"No files found\"\n description=\"Upload a file or adjust your search to see results here.\"\n />\n </div>\n ) : (\n <>\n <div className=\"grid grid-cols-6 gap-2 border-b p-4 text-xs font-medium text-text-secondary\">\n <span className=\"col-span-2\">Name</span>\n <span>Uploaded By</span>\n <span>Department</span>\n <span>Date</span>\n <span className=\"text-right\">Size</span>\n </div>\n {filteredFiles.map((file) => (\n <div\n key={file.id}\n className=\"grid grid-cols-6 items-center gap-2 border-b px-4 py-3 text-sm last:border-0 hover:bg-bg-sunken/50\"\n >\n <div className=\"col-span-2 flex items-center gap-2\">\n {fileIcon(file.type)}\n <span className=\"truncate font-medium\">{file.name}</span>\n </div>\n <span className=\"text-text-secondary\">{file.uploadedBy}</span>\n <Badge variant=\"outline\" className=\"w-fit text-[10px]\">\n {file.department}\n </Badge>\n <span className=\"text-text-secondary\">{file.date}</span>\n <div className=\"flex items-center justify-end gap-2\">\n <span className=\"text-text-secondary\">{file.size}</span>\n <Button variant=\"outline\" size=\"sm\" className=\"h-7\">\n <Download className=\"h-3 w-3\" />\n </Button>\n </div>\n </div>\n ))}\n </>\n )}\n </CardContent>\n </GlassCard>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommunicationsFilesPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CommunicationsFilesPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { useNavigate } from 'react-router-dom';\nimport { File, FileText, FolderInput, Image, Search, Upload } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\n// Files are owned by the platform Files service (wspace-files-svc), surfaced in\n// this app shell at the `/files` route. CrewFoundry does not keep a bespoke file\n// store — upload and per-file actions route into the real Files experience.\nconst FILES_BROWSE_ROUTE = '/files/browse';\n\ntype SharedFile = {\n id: string;\n name: string;\n type: 'pdf' | 'spreadsheet' | 'image' | 'doc';\n size: string;\n uploadedBy: string;\n date: string;\n department: string;\n};\n\nconst fileIcon = (type: SharedFile['type']) => {\n if (type === 'image') return <Image className=\"h-5 w-5 text-action-primary-bg\" />;\n if (type === 'pdf') return <FileText className=\"h-5 w-5 text-status-error-text\" />;\n return <File className=\"h-5 w-5 text-status-info-text\" />;\n};\n\nconst formatDate = (input: string): string => {\n const parsed = new Date(input);\n if (Number.isNaN(parsed.getTime())) {\n return 'Unknown';\n }\n return parsed.toISOString().split('T')[0];\n};\n\nexport function CommunicationsFilesPagePage() {\n const [search, setSearch] = useState('');\n const navigate = useNavigate();\n const { announcements, invoices, projects, employees } = useCrewFoundryStore();\n\n const sharedFiles = useMemo<SharedFile[]>(() => {\n const announcementFiles = announcements.slice(0, 8).map((announcement, index) => {\n const uploader = employees[index % Math.max(employees.length, 1)];\n return {\n id: `announcement-${announcement.id}`,\n name: `${announcement.title}.pdf`,\n type: 'pdf' as const,\n size: `${Math.max(1, Math.round(announcement.content.length / 300))}.${index % 9} MB`,\n uploadedBy: uploader\n ? `${uploader.firstName} ${uploader.lastName}`.trim()\n : announcement.author,\n date: formatDate(announcement.createdAt),\n department: uploader?.department || 'Operations',\n };\n });\n\n const financeFiles = invoices.slice(0, 6).map((invoice, index) => ({\n id: `invoice-${invoice.id}`,\n name: `${invoice.number}-invoice.xlsx`,\n type: 'spreadsheet' as const,\n size: `${(invoice.amount / 1000).toFixed(1)} MB`,\n uploadedBy: invoice.clientName,\n date: formatDate(invoice.issueDate),\n department: index % 2 === 0 ? 'Finance' : 'Billing',\n }));\n\n const projectFiles = projects.slice(0, 6).map((project, index) => ({\n id: `project-${project.id}`,\n name: `${project.name}-brief.docx`,\n type: index % 2 === 0 ? ('doc' as const) : ('image' as const),\n size: `${(Math.max(project.tasks, 1) / 10).toFixed(1)} MB`,\n uploadedBy: project.managerName,\n date: formatDate(project.startDate),\n department: 'Projects',\n }));\n\n return [...announcementFiles, ...financeFiles, ...projectFiles];\n }, [announcements, employees, invoices, projects]);\n\n const filteredFiles = sharedFiles.filter((file) =>\n file.name.toLowerCase().includes(search.toLowerCase())\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>Shared Files</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {sharedFiles.length} files shared across teams\n </p>\n <PagePurpose className=\"mt-1\">A shared space for company documents and files — store, search, and share the resources your teams need to get work done.</PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => navigate(FILES_BROWSE_ROUTE)}>\n <Upload className=\"mr-1 h-4 w-4\" />\n Upload via Files\n </Button>\n </div>\n\n <div className=\"relative max-w-sm\">\n <Search className=\"absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <Input\n placeholder=\"Search files...\"\n className=\"pl-9\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n />\n </div>\n\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>Workspace Files</CardTitle>\n </CardHeader>\n <CardContent className=\"p-0\">\n {filteredFiles.length === 0 ? (\n <div className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"empty-files\"\n title=\"No files found\"\n description=\"Upload files in the Files app or adjust your search to see results here.\"\n />\n </div>\n ) : (\n <>\n <div className=\"grid grid-cols-6 gap-2 border-b p-4 text-xs font-medium text-text-secondary\">\n <span className=\"col-span-2\">Name</span>\n <span>Uploaded By</span>\n <span>Department</span>\n <span>Date</span>\n <span className=\"text-right\">Size</span>\n </div>\n {filteredFiles.map((file) => (\n <div\n key={file.id}\n className=\"grid grid-cols-6 items-center gap-2 border-b px-4 py-3 text-sm last:border-0 hover:bg-bg-sunken/50\"\n >\n <div className=\"col-span-2 flex items-center gap-2\">\n {fileIcon(file.type)}\n <span className=\"truncate font-medium\">{file.name}</span>\n </div>\n <span className=\"text-text-secondary\">{file.uploadedBy}</span>\n <Badge variant=\"outline\" className=\"w-fit text-[10px]\">\n {file.department}\n </Badge>\n <span className=\"text-text-secondary\">{file.date}</span>\n <div className=\"flex items-center justify-end gap-2\">\n <span className=\"text-text-secondary\">{file.size}</span>\n <Button\n variant=\"outline\"\n size=\"sm\"\n className=\"h-7\"\n aria-label={`Open ${file.name} in Files`}\n onClick={() => navigate(FILES_BROWSE_ROUTE)}\n >\n <FolderInput className=\"h-3 w-3\" />\n </Button>\n </div>\n </div>\n ))}\n </>\n )}\n </CardContent>\n </GlassCard>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -3,45 +3,46 @@ import { useMemo as t, useState as n } from "react";
|
|
|
3
3
|
import { MessageSquare as r, Search as i } from "lucide-react";
|
|
4
4
|
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
5
5
|
import { Badge as s, Button as c, CardContent as l, CardHeader as u, CardTitle as d, GlassCard as f, GradientText as p, IllustratedEmptyState as m, Input as h, PagePurpose as g } from "@burdenoff/fe-libs/ui";
|
|
6
|
+
import { useGlobalUi as _ } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
6
7
|
//#region src/crewfoundry/pages/CommunicationsMessagesPagePage.tsx
|
|
7
|
-
var
|
|
8
|
+
var v = (e) => {
|
|
8
9
|
let t = new Date(e);
|
|
9
10
|
if (Number.isNaN(t.getTime())) return "Recently";
|
|
10
11
|
let n = Date.now() - t.getTime(), r = Math.max(0, Math.floor(n / (1e3 * 60 * 60)));
|
|
11
12
|
return r < 1 ? "Just now" : r < 24 ? `${r}h ago` : `${Math.floor(r / 24)}d ago`;
|
|
12
13
|
};
|
|
13
|
-
function
|
|
14
|
-
let [
|
|
15
|
-
let e =
|
|
16
|
-
let n =
|
|
14
|
+
function y() {
|
|
15
|
+
let [y, b] = n(""), { showToast: x } = _(), { teams: S, employees: C, announcements: w, notifications: T } = e(), E = () => x("Direct messaging is on the CrewFoundry roadmap — coming soon.", "info"), D = t(() => {
|
|
16
|
+
let e = C.slice(0, 8).map((e, t) => {
|
|
17
|
+
let n = w[t % Math.max(w.length, 1)], r = n?.content || `Status update for ${e.department} initiatives.`;
|
|
17
18
|
return {
|
|
18
19
|
id: `person-${e.id}`,
|
|
19
20
|
name: `${e.firstName} ${e.lastName}`.trim(),
|
|
20
21
|
role: e.position,
|
|
21
22
|
lastMessage: r,
|
|
22
|
-
time:
|
|
23
|
+
time: v(n?.createdAt || e.startDate),
|
|
23
24
|
unread: Math.min(3, Math.round(e.performanceScore) % 4),
|
|
24
25
|
online: e.status === "active" && t % 2 == 0
|
|
25
26
|
};
|
|
26
|
-
}), t =
|
|
27
|
-
let n =
|
|
27
|
+
}), t = S.slice(0, 5).map((e, t) => {
|
|
28
|
+
let n = T.slice(t, t + 3).filter((e) => !e.read).length;
|
|
28
29
|
return {
|
|
29
30
|
id: `team-${e.id}`,
|
|
30
31
|
name: `#${e.name.toLowerCase().replaceAll(" ", "-")}`,
|
|
31
32
|
role: `Channel · ${e.memberCount} members`,
|
|
32
|
-
lastMessage:
|
|
33
|
-
time:
|
|
33
|
+
lastMessage: w[t % Math.max(w.length, 1)]?.title || `${e.leadName} posted an update in ${e.name}.`,
|
|
34
|
+
time: v(e.createdAt),
|
|
34
35
|
unread: n,
|
|
35
36
|
online: !1
|
|
36
37
|
};
|
|
37
38
|
});
|
|
38
39
|
return [...e, ...t];
|
|
39
40
|
}, [
|
|
40
|
-
|
|
41
|
-
x,
|
|
41
|
+
w,
|
|
42
42
|
C,
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
T,
|
|
44
|
+
S
|
|
45
|
+
]).filter((e) => e.name.toLowerCase().includes(y.toLowerCase()));
|
|
45
46
|
return /* @__PURE__ */ o("div", {
|
|
46
47
|
className: "space-y-6 p-6",
|
|
47
48
|
children: [
|
|
@@ -60,9 +61,17 @@ function v() {
|
|
|
60
61
|
className: "mt-1",
|
|
61
62
|
children: "Chat directly with colleagues and keep conversations in one thread — use it for quick questions, follow-ups, and day-to-day coordination."
|
|
62
63
|
})
|
|
63
|
-
] }), /* @__PURE__ */ o(
|
|
64
|
-
|
|
65
|
-
children: [/* @__PURE__ */ a(
|
|
64
|
+
] }), /* @__PURE__ */ o("div", {
|
|
65
|
+
className: "flex items-center gap-2",
|
|
66
|
+
children: [/* @__PURE__ */ a(s, {
|
|
67
|
+
variant: "secondary",
|
|
68
|
+
className: "text-[10px]",
|
|
69
|
+
children: "Coming soon"
|
|
70
|
+
}), /* @__PURE__ */ o(c, {
|
|
71
|
+
size: "sm",
|
|
72
|
+
onClick: E,
|
|
73
|
+
children: [/* @__PURE__ */ a(r, { className: "mr-1 h-4 w-4" }), "New Message"]
|
|
74
|
+
})]
|
|
66
75
|
})]
|
|
67
76
|
}),
|
|
68
77
|
/* @__PURE__ */ o("div", {
|
|
@@ -70,8 +79,8 @@ function v() {
|
|
|
70
79
|
children: [/* @__PURE__ */ a(i, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ a(h, {
|
|
71
80
|
placeholder: "Search conversations...",
|
|
72
81
|
className: "pl-9",
|
|
73
|
-
value:
|
|
74
|
-
onChange: (e) =>
|
|
82
|
+
value: y,
|
|
83
|
+
onChange: (e) => b(e.target.value)
|
|
75
84
|
})]
|
|
76
85
|
}),
|
|
77
86
|
/* @__PURE__ */ o(f, {
|
|
@@ -80,15 +89,15 @@ function v() {
|
|
|
80
89
|
className: "border-border-seam",
|
|
81
90
|
children: [/* @__PURE__ */ a(u, { children: /* @__PURE__ */ a(d, { children: "Conversation Inbox" }) }), /* @__PURE__ */ a(l, {
|
|
82
91
|
className: "p-0",
|
|
83
|
-
children:
|
|
92
|
+
children: D.length === 0 ? /* @__PURE__ */ a("div", {
|
|
84
93
|
className: "p-6",
|
|
85
94
|
children: /* @__PURE__ */ a(m, {
|
|
86
95
|
illustration: "empty-notifications",
|
|
87
96
|
title: "No conversations",
|
|
88
97
|
description: "Messages with your colleagues will show up here."
|
|
89
98
|
})
|
|
90
|
-
}) :
|
|
91
|
-
className: "flex
|
|
99
|
+
}) : D.map((e) => /* @__PURE__ */ o("div", {
|
|
100
|
+
className: "flex items-center gap-3 border-b p-4 last:border-0",
|
|
92
101
|
children: [
|
|
93
102
|
/* @__PURE__ */ o("div", {
|
|
94
103
|
className: "relative",
|
|
@@ -132,6 +141,6 @@ function v() {
|
|
|
132
141
|
});
|
|
133
142
|
}
|
|
134
143
|
//#endregion
|
|
135
|
-
export {
|
|
144
|
+
export { y as CommunicationsMessagesPagePage };
|
|
136
145
|
|
|
137
146
|
//# sourceMappingURL=CommunicationsMessagesPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommunicationsMessagesPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CommunicationsMessagesPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { MessageSquare, Search } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype Conversation = {\n id: string;\n name: string;\n role: string;\n lastMessage: string;\n time: string;\n unread: number;\n online: boolean;\n};\n\nconst formatRelativeDate = (value: string): string => {\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n return 'Recently';\n }\n const diffMs = Date.now() - parsed.getTime();\n const diffHours = Math.max(0, Math.floor(diffMs / (1000 * 60 * 60)));\n if (diffHours < 1) return 'Just now';\n if (diffHours < 24) return `${diffHours}h ago`;\n const diffDays = Math.floor(diffHours / 24);\n return `${diffDays}d ago`;\n};\n\nexport function CommunicationsMessagesPagePage() {\n const [search, setSearch] = useState('');\n const { teams, employees, announcements, notifications } = useCrewFoundryStore();\n\n const conversations = useMemo<Conversation[]>(() => {\n const peopleConversations = employees.slice(0, 8).map((employee, index) => {\n const announcement = announcements[index % Math.max(announcements.length, 1)];\n const message =\n announcement?.content || `Status update for ${employee.department} initiatives.`;\n return {\n id: `person-${employee.id}`,\n name: `${employee.firstName} ${employee.lastName}`.trim(),\n role: employee.position,\n lastMessage: message,\n time: formatRelativeDate(announcement?.createdAt || employee.startDate),\n unread: Math.min(3, Math.round(employee.performanceScore) % 4),\n online: employee.status === 'active' && index % 2 === 0,\n };\n });\n\n const teamConversations = teams.slice(0, 5).map((team, index) => {\n const unread = notifications\n .slice(index, index + 3)\n .filter((notification) => !notification.read).length;\n return {\n id: `team-${team.id}`,\n name: `#${team.name.toLowerCase().replaceAll(' ', '-')}`,\n role: `Channel · ${team.memberCount} members`,\n lastMessage:\n announcements[index % Math.max(announcements.length, 1)]?.title ||\n `${team.leadName} posted an update in ${team.name}.`,\n time: formatRelativeDate(team.createdAt),\n unread,\n online: false,\n };\n });\n\n return [...peopleConversations, ...teamConversations];\n }, [announcements, employees, notifications, teams]);\n\n const filteredConversations = conversations.filter((conversation) =>\n conversation.name.toLowerCase().includes(search.toLowerCase())\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>Messages</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Team conversations and channels</p>\n <PagePurpose className=\"mt-1\">Chat directly with colleagues and keep conversations in one thread — use it for quick questions, follow-ups, and day-to-day coordination.</PagePurpose>\n </div>\n <Button size=\"sm\">\n <MessageSquare className=\"mr-1 h-4 w-4\" />\n New Message\n </Button>\n </div>\n\n <div className=\"relative max-w-sm\">\n <Search className=\"absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <Input\n placeholder=\"Search conversations...\"\n className=\"pl-9\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n />\n </div>\n\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>Conversation Inbox</CardTitle>\n </CardHeader>\n <CardContent className=\"p-0\">\n {filteredConversations.length === 0 ? (\n <div className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title=\"No conversations\"\n description=\"Messages with your colleagues will show up here.\"\n />\n </div>\n ) : (\n filteredConversations.map((conversation) => (\n <div\n key={conversation.id}\n className=\"flex cursor-pointer items-center gap-3 border-b p-4 last:border-0 hover:bg-bg-sunken/50\"\n >\n <div className=\"relative\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-full bg-action-primary-bg/10 text-sm font-medium\">\n {conversation.name.startsWith('#')\n ? '#'\n : conversation.name\n .split(' ')\n .map((part) => part[0])\n .join('')}\n </div>\n {conversation.online && (\n <div className=\"absolute right-0 bottom-0 h-3 w-3 rounded-full border-2 border-background bg-status-success-text\" />\n )}\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between\">\n <p className=\"text-sm font-medium\">{conversation.name}</p>\n <span className=\"text-xs text-text-secondary\">{conversation.time}</span>\n </div>\n <p className=\"text-xs text-text-secondary\">{conversation.role}</p>\n <p className=\"mt-0.5 truncate text-xs text-text-secondary\">\n {conversation.lastMessage}\n </p>\n </div>\n\n {conversation.unread > 0 && (\n <Badge className=\"flex h-5 w-5 items-center justify-center rounded-full p-0 text-[10px]\">\n {conversation.unread}\n </Badge>\n )}\n </div>\n ))\n )}\n </CardContent>\n </GlassCard>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommunicationsMessagesPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CommunicationsMessagesPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { MessageSquare, Search } from 'lucide-react';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype Conversation = {\n id: string;\n name: string;\n role: string;\n lastMessage: string;\n time: string;\n unread: number;\n online: boolean;\n};\n\nconst formatRelativeDate = (value: string): string => {\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n return 'Recently';\n }\n const diffMs = Date.now() - parsed.getTime();\n const diffHours = Math.max(0, Math.floor(diffMs / (1000 * 60 * 60)));\n if (diffHours < 1) return 'Just now';\n if (diffHours < 24) return `${diffHours}h ago`;\n const diffDays = Math.floor(diffHours / 24);\n return `${diffDays}d ago`;\n};\n\nexport function CommunicationsMessagesPagePage() {\n const [search, setSearch] = useState('');\n const { showToast } = useGlobalUi();\n const { teams, employees, announcements, notifications } = useCrewFoundryStore();\n\n // Real-time direct messaging is a planned surface — there is no chat backend\n // yet, so this control honestly signals its roadmap status instead of failing\n // silently.\n const notifyComingSoon = () =>\n showToast('Direct messaging is on the CrewFoundry roadmap — coming soon.', 'info');\n\n const conversations = useMemo<Conversation[]>(() => {\n const peopleConversations = employees.slice(0, 8).map((employee, index) => {\n const announcement = announcements[index % Math.max(announcements.length, 1)];\n const message =\n announcement?.content || `Status update for ${employee.department} initiatives.`;\n return {\n id: `person-${employee.id}`,\n name: `${employee.firstName} ${employee.lastName}`.trim(),\n role: employee.position,\n lastMessage: message,\n time: formatRelativeDate(announcement?.createdAt || employee.startDate),\n unread: Math.min(3, Math.round(employee.performanceScore) % 4),\n online: employee.status === 'active' && index % 2 === 0,\n };\n });\n\n const teamConversations = teams.slice(0, 5).map((team, index) => {\n const unread = notifications\n .slice(index, index + 3)\n .filter((notification) => !notification.read).length;\n return {\n id: `team-${team.id}`,\n name: `#${team.name.toLowerCase().replaceAll(' ', '-')}`,\n role: `Channel · ${team.memberCount} members`,\n lastMessage:\n announcements[index % Math.max(announcements.length, 1)]?.title ||\n `${team.leadName} posted an update in ${team.name}.`,\n time: formatRelativeDate(team.createdAt),\n unread,\n online: false,\n };\n });\n\n return [...peopleConversations, ...teamConversations];\n }, [announcements, employees, notifications, teams]);\n\n const filteredConversations = conversations.filter((conversation) =>\n conversation.name.toLowerCase().includes(search.toLowerCase())\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>Messages</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Team conversations and channels</p>\n <PagePurpose className=\"mt-1\">Chat directly with colleagues and keep conversations in one thread — use it for quick questions, follow-ups, and day-to-day coordination.</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 <MessageSquare className=\"mr-1 h-4 w-4\" />\n New Message\n </Button>\n </div>\n </div>\n\n <div className=\"relative max-w-sm\">\n <Search className=\"absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <Input\n placeholder=\"Search conversations...\"\n className=\"pl-9\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n />\n </div>\n\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>Conversation Inbox</CardTitle>\n </CardHeader>\n <CardContent className=\"p-0\">\n {filteredConversations.length === 0 ? (\n <div className=\"p-6\">\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title=\"No conversations\"\n description=\"Messages with your colleagues will show up here.\"\n />\n </div>\n ) : (\n filteredConversations.map((conversation) => (\n <div\n key={conversation.id}\n className=\"flex items-center gap-3 border-b p-4 last:border-0\"\n >\n <div className=\"relative\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-full bg-action-primary-bg/10 text-sm font-medium\">\n {conversation.name.startsWith('#')\n ? '#'\n : conversation.name\n .split(' ')\n .map((part) => part[0])\n .join('')}\n </div>\n {conversation.online && (\n <div className=\"absolute right-0 bottom-0 h-3 w-3 rounded-full border-2 border-background bg-status-success-text\" />\n )}\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center justify-between\">\n <p className=\"text-sm font-medium\">{conversation.name}</p>\n <span className=\"text-xs text-text-secondary\">{conversation.time}</span>\n </div>\n <p className=\"text-xs text-text-secondary\">{conversation.role}</p>\n <p className=\"mt-0.5 truncate text-xs text-text-secondary\">\n {conversation.lastMessage}\n </p>\n </div>\n\n {conversation.unread > 0 && (\n <Badge className=\"flex h-5 w-5 items-center justify-center rounded-full p-0 text-[10px]\">\n {conversation.unread}\n </Badge>\n )}\n </div>\n ))\n )}\n </CardContent>\n </GlassCard>\n </div>\n );\n}\n"],"mappings":";;;;;;;AA2BA,IAAM,KAAsB,MAA0B;CACpD,IAAM,IAAS,IAAI,KAAK,EAAM;AAC9B,KAAI,OAAO,MAAM,EAAO,SAAS,CAAC,CAChC,QAAO;CAET,IAAM,IAAS,KAAK,KAAK,GAAG,EAAO,SAAS,EACtC,IAAY,KAAK,IAAI,GAAG,KAAK,MAAM,KAAU,MAAO,KAAK,IAAI,CAAC;AAIpE,QAHI,IAAY,IAAU,aACtB,IAAY,KAAW,GAAG,EAAU,SAEjC,GADU,KAAK,MAAM,IAAY,GAAG,CACxB;;AAGrB,SAAgB,IAAiC;CAC/C,IAAM,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,EAAE,iBAAc,GAAa,EAC7B,EAAE,UAAO,cAAW,kBAAe,qBAAkB,GAAqB,EAK1E,UACJ,EAAU,iEAAiE,OAAO,EAsC9E,IApCgB,QAA8B;EAClD,IAAM,IAAsB,EAAU,MAAM,GAAG,EAAE,CAAC,KAAK,GAAU,MAAU;GACzE,IAAM,IAAe,EAAc,IAAQ,KAAK,IAAI,EAAc,QAAQ,EAAE,GACtE,IACJ,GAAc,WAAW,qBAAqB,EAAS,WAAW;AACpE,UAAO;IACL,IAAI,UAAU,EAAS;IACvB,MAAM,GAAG,EAAS,UAAU,GAAG,EAAS,WAAW,MAAM;IACzD,MAAM,EAAS;IACf,aAAa;IACb,MAAM,EAAmB,GAAc,aAAa,EAAS,UAAU;IACvE,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,EAAS,iBAAiB,GAAG,EAAE;IAC9D,QAAQ,EAAS,WAAW,YAAY,IAAQ,KAAM;IACvD;IACD,EAEI,IAAoB,EAAM,MAAM,GAAG,EAAE,CAAC,KAAK,GAAM,MAAU;GAC/D,IAAM,IAAS,EACZ,MAAM,GAAO,IAAQ,EAAE,CACvB,QAAQ,MAAiB,CAAC,EAAa,KAAK,CAAC;AAChD,UAAO;IACL,IAAI,QAAQ,EAAK;IACjB,MAAM,IAAI,EAAK,KAAK,aAAa,CAAC,WAAW,KAAK,IAAI;IACtD,MAAM,aAAa,EAAK,YAAY;IACpC,aACE,EAAc,IAAQ,KAAK,IAAI,EAAc,QAAQ,EAAE,GAAG,SAC1D,GAAG,EAAK,SAAS,uBAAuB,EAAK,KAAK;IACpD,MAAM,EAAmB,EAAK,UAAU;IACxC;IACA,QAAQ;IACT;IACD;AAEF,SAAO,CAAC,GAAG,GAAqB,GAAG,EAAkB;IACpD;EAAC;EAAe;EAAW;EAAe;EAAM,CAAC,CAER,QAAQ,MAClD,EAAa,KAAK,aAAa,CAAC,SAAS,EAAO,aAAa,CAAC,CAC/D;AAED,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,YAAuB,CAAA;MAClC,CAAA;KACL,kBAAC,KAAD;MAAG,WAAU;gBAA8B;MAAmC,CAAA;KAC9E,kBAAC,GAAD;MAAa,WAAU;gBAAO;MAAuJ,CAAA;KACjL,EAAA,CAAA,EACN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAO,SAAQ;MAAY,WAAU;gBAAc;MAE3C,CAAA,EACR,kBAAC,GAAD;MAAQ,MAAK;MAAK,SAAS;gBAA3B,CACE,kBAAC,GAAD,EAAe,WAAU,gBAAiB,CAAA,EAAA,cAEnC;QACL;OACF;;GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAQ,WAAU,wEAAyE,CAAA,EAC3F,kBAAC,GAAD;KACE,aAAY;KACZ,WAAU;KACV,OAAO;KACP,WAAW,MAAU,EAAU,EAAM,OAAO,MAAM;KAClD,CAAA,CACE;;GAEN,kBAAC,GAAD;IAAW,WAAU;IAAQ,MAAA;IAAK,WAAU;cAA5C,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAW,sBAA8B,CAAA,EAC9B,CAAA,EACb,kBAAC,GAAD;KAAa,WAAU;eACpB,EAAsB,WAAW,IAChC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OACE,cAAa;OACb,OAAM;OACN,aAAY;OACZ,CAAA;MACE,CAAA,GAEN,EAAsB,KAAK,MAC3B,kBAAC,OAAD;MAEE,WAAU;gBAFZ;OAIE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAa,KAAK,WAAW,IAAI,GAC9B,MACA,EAAa,KACV,MAAM,IAAI,CACV,KAAK,MAAS,EAAK,GAAG,CACtB,KAAK,GAAG;SACX,CAAA,EACL,EAAa,UACZ,kBAAC,OAAD,EAAK,WAAU,oGAAqG,CAAA,CAElH;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,KAAD;WAAG,WAAU;qBAAuB,EAAa;WAAS,CAAA,EAC1D,kBAAC,QAAD;WAAM,WAAU;qBAA+B,EAAa;WAAY,CAAA,CACpE;;SACN,kBAAC,KAAD;UAAG,WAAU;oBAA+B,EAAa;UAAS,CAAA;SAClE,kBAAC,KAAD;UAAG,WAAU;oBACV,EAAa;UACZ,CAAA;SACA;;OAEL,EAAa,SAAS,KACrB,kBAAC,GAAD;QAAO,WAAU;kBACd,EAAa;QACR,CAAA;OAEN;QAjCC,EAAa,GAiCd,CACJ;KAEQ,CAAA,CACJ;;GACR"}
|
|
@@ -3,44 +3,45 @@ import { useMemo as t } from "react";
|
|
|
3
3
|
import { Calendar as n, Clock as r, Monitor as i, Users as a, Video 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/CommunicationsVideoCallsPagePage.tsx
|
|
7
|
-
var
|
|
8
|
+
var y = (e) => `${Math.max(e, 15)} min`, b = (e) => {
|
|
8
9
|
let t = Math.max(e, 1);
|
|
9
10
|
return `${String(t).padStart(2, "0")}:${String(t * 7 % 60).padStart(2, "0")}`;
|
|
10
|
-
},
|
|
11
|
+
}, x = (e) => {
|
|
11
12
|
let t = new Date(e);
|
|
12
13
|
return Number.isNaN(t.getTime()) ? "Upcoming" : t.toLocaleDateString();
|
|
13
14
|
};
|
|
14
|
-
function
|
|
15
|
-
let { teams:
|
|
16
|
-
let e =
|
|
15
|
+
function S() {
|
|
16
|
+
let { showToast: S } = v(), { teams: C, interviews: w, announcements: T } = e(), E = () => S("Video meetings are on the CrewFoundry roadmap — coming soon.", "info"), D = t(() => {
|
|
17
|
+
let e = C.slice(0, 6).map((e, t) => ({
|
|
17
18
|
id: `team-${e.id}`,
|
|
18
19
|
title: `${e.name} Sync`,
|
|
19
20
|
host: e.leadName,
|
|
20
|
-
time:
|
|
21
|
-
duration:
|
|
21
|
+
time: x(e.createdAt),
|
|
22
|
+
duration: y(15 + t * 10),
|
|
22
23
|
participants: Math.max(e.memberCount, 2),
|
|
23
24
|
recurring: t % 2 == 0
|
|
24
|
-
})), t =
|
|
25
|
+
})), t = w.slice(0, 4).map((e) => ({
|
|
25
26
|
id: `interview-${e.id}`,
|
|
26
27
|
title: `Interview · ${e.candidateName}`,
|
|
27
28
|
host: e.interviewerName,
|
|
28
|
-
time:
|
|
29
|
-
duration:
|
|
29
|
+
time: x(e.date),
|
|
30
|
+
duration: y(Number.parseInt(e.time.split(":")[0] || "30", 10)),
|
|
30
31
|
participants: 3,
|
|
31
32
|
recurring: !1
|
|
32
33
|
}));
|
|
33
34
|
return [...e, ...t];
|
|
34
|
-
}, [
|
|
35
|
+
}, [w, C]), O = t(() => T.slice(0, 6).map((e) => {
|
|
35
36
|
let t = Math.max(12, Math.round(e.content.length / 40));
|
|
36
37
|
return {
|
|
37
38
|
id: `recording-${e.id}`,
|
|
38
39
|
title: `${e.title} recording`,
|
|
39
|
-
date:
|
|
40
|
-
duration:
|
|
40
|
+
date: x(e.createdAt),
|
|
41
|
+
duration: b(t),
|
|
41
42
|
size: `${(t / 10).toFixed(1)} GB`
|
|
42
43
|
};
|
|
43
|
-
}), [
|
|
44
|
+
}), [T]), k = D.length ? Math.round(D.map((e) => Number.parseInt(e.duration.split(" ")[0], 10)).reduce((e, t) => e + t, 0) / D.length) : 0;
|
|
44
45
|
return /* @__PURE__ */ c("div", {
|
|
45
46
|
className: "space-y-6 p-6",
|
|
46
47
|
children: [
|
|
@@ -60,15 +61,25 @@ function x() {
|
|
|
60
61
|
children: "Host and join video meetings with your teams — schedule a call or start one instantly for face-to-face collaboration."
|
|
61
62
|
})
|
|
62
63
|
] }), /* @__PURE__ */ c("div", {
|
|
63
|
-
className: "flex gap-2",
|
|
64
|
-
children: [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
className: "flex items-center gap-2",
|
|
65
|
+
children: [
|
|
66
|
+
/* @__PURE__ */ s(l, {
|
|
67
|
+
variant: "secondary",
|
|
68
|
+
className: "text-[10px]",
|
|
69
|
+
children: "Coming soon"
|
|
70
|
+
}),
|
|
71
|
+
/* @__PURE__ */ c(u, {
|
|
72
|
+
variant: "outline",
|
|
73
|
+
size: "sm",
|
|
74
|
+
onClick: E,
|
|
75
|
+
children: [/* @__PURE__ */ s(n, { className: "mr-1 h-4 w-4" }), "Schedule"]
|
|
76
|
+
}),
|
|
77
|
+
/* @__PURE__ */ c(u, {
|
|
78
|
+
size: "sm",
|
|
79
|
+
onClick: E,
|
|
80
|
+
children: [/* @__PURE__ */ s(o, { className: "mr-1 h-4 w-4" }), "Start Meeting"]
|
|
81
|
+
})
|
|
82
|
+
]
|
|
72
83
|
})]
|
|
73
84
|
}),
|
|
74
85
|
/* @__PURE__ */ c("div", {
|
|
@@ -86,7 +97,7 @@ function x() {
|
|
|
86
97
|
}), /* @__PURE__ */ s(n, { className: "h-4 w-4 text-status-info-text" })]
|
|
87
98
|
}), /* @__PURE__ */ c(f, { children: [/* @__PURE__ */ s("div", {
|
|
88
99
|
className: "text-2xl font-bold tabular-nums",
|
|
89
|
-
children:
|
|
100
|
+
children: D.length
|
|
90
101
|
}), /* @__PURE__ */ s("p", {
|
|
91
102
|
className: "text-xs text-text-secondary",
|
|
92
103
|
children: "meetings scheduled"
|
|
@@ -103,7 +114,7 @@ function x() {
|
|
|
103
114
|
}), /* @__PURE__ */ s(i, { className: "h-4 w-4 text-text-secondary" })]
|
|
104
115
|
}), /* @__PURE__ */ c(f, { children: [/* @__PURE__ */ s("div", {
|
|
105
116
|
className: "text-2xl font-bold tabular-nums",
|
|
106
|
-
children:
|
|
117
|
+
children: O.length
|
|
107
118
|
}), /* @__PURE__ */ s("p", {
|
|
108
119
|
className: "text-xs text-text-secondary",
|
|
109
120
|
children: "available"
|
|
@@ -120,14 +131,14 @@ function x() {
|
|
|
120
131
|
}), /* @__PURE__ */ s(r, { className: "h-4 w-4 text-text-secondary" })]
|
|
121
132
|
}), /* @__PURE__ */ s(f, { children: /* @__PURE__ */ c("div", {
|
|
122
133
|
className: "text-2xl font-bold tabular-nums",
|
|
123
|
-
children: [
|
|
134
|
+
children: [k, " min"]
|
|
124
135
|
}) })]
|
|
125
136
|
})
|
|
126
137
|
]
|
|
127
138
|
}),
|
|
128
139
|
/* @__PURE__ */ c(d, { children: [/* @__PURE__ */ s(p, { children: /* @__PURE__ */ s(m, { children: "Upcoming Meetings" }) }), /* @__PURE__ */ s(f, {
|
|
129
140
|
className: "space-y-3",
|
|
130
|
-
children:
|
|
141
|
+
children: D.map((e) => /* @__PURE__ */ c("div", {
|
|
131
142
|
className: "flex items-center justify-between rounded border p-3",
|
|
132
143
|
children: [/* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("p", {
|
|
133
144
|
className: "text-sm font-medium",
|
|
@@ -159,6 +170,8 @@ function x() {
|
|
|
159
170
|
/* @__PURE__ */ c(u, {
|
|
160
171
|
size: "sm",
|
|
161
172
|
className: "h-7 text-xs",
|
|
173
|
+
"aria-label": `Join ${e.title} (coming soon)`,
|
|
174
|
+
onClick: E,
|
|
162
175
|
children: [/* @__PURE__ */ s(o, { className: "mr-1 h-3 w-3" }), "Join"]
|
|
163
176
|
})
|
|
164
177
|
]
|
|
@@ -167,7 +180,7 @@ function x() {
|
|
|
167
180
|
})] }),
|
|
168
181
|
/* @__PURE__ */ c(d, { children: [/* @__PURE__ */ s(p, { children: /* @__PURE__ */ s(m, { children: "Recent Recordings" }) }), /* @__PURE__ */ s(f, {
|
|
169
182
|
className: "space-y-3",
|
|
170
|
-
children:
|
|
183
|
+
children: O.map((e) => /* @__PURE__ */ c("div", {
|
|
171
184
|
className: "flex items-center justify-between rounded border p-3",
|
|
172
185
|
children: [/* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("p", {
|
|
173
186
|
className: "text-sm font-medium",
|
|
@@ -185,6 +198,8 @@ function x() {
|
|
|
185
198
|
variant: "outline",
|
|
186
199
|
size: "sm",
|
|
187
200
|
className: "h-7 text-xs",
|
|
201
|
+
"aria-label": `Watch ${e.title} (coming soon)`,
|
|
202
|
+
onClick: E,
|
|
188
203
|
children: "Watch"
|
|
189
204
|
})]
|
|
190
205
|
}, e.id))
|
|
@@ -193,6 +208,6 @@ function x() {
|
|
|
193
208
|
});
|
|
194
209
|
}
|
|
195
210
|
//#endregion
|
|
196
|
-
export {
|
|
211
|
+
export { S as CommunicationsVideoCallsPagePage };
|
|
197
212
|
|
|
198
213
|
//# sourceMappingURL=CommunicationsVideoCallsPagePage.js.map
|