@burdenoff/microfe-crewfoundry 2026.626.1 → 2026.703.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/crewfoundry/components/forms/ConfirmDialog.js +43 -0
  2. package/dist/crewfoundry/components/forms/ConfirmDialog.js.map +1 -0
  3. package/dist/crewfoundry/components/forms/FormModal.js +220 -0
  4. package/dist/crewfoundry/components/forms/FormModal.js.map +1 -0
  5. package/dist/crewfoundry/components/forms/formValues.js +20 -0
  6. package/dist/crewfoundry/components/forms/formValues.js.map +1 -0
  7. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +255 -65
  8. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
  9. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +28 -17
  10. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +1 -1
  11. package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js +57 -53
  12. package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js.map +1 -1
  13. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +32 -23
  14. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
  15. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +44 -29
  16. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +1 -1
  17. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +183 -57
  18. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
  19. package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js.map +1 -1
  20. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +214 -92
  21. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
  22. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +165 -131
  23. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
  24. package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +163 -133
  25. package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
  26. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +269 -54
  27. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
  28. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +225 -78
  29. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
  30. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +213 -59
  31. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
  32. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +287 -90
  33. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
  34. package/dist/crewfoundry/pages/HiringJobsPagePage.js +49 -47
  35. package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
  36. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +166 -59
  37. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
  38. package/dist/crewfoundry/pages/HrEmployeesPagePage.js +274 -83
  39. package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
  40. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +198 -88
  41. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
  42. package/dist/crewfoundry/pages/HrPayrollPagePage.js +216 -88
  43. package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
  44. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +216 -66
  45. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
  46. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +6 -7
  47. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
  48. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +83 -68
  49. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
  50. package/dist/crewfoundry/pages/LearningCoursesPagePage.js +167 -46
  51. package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
  52. package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
  53. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +75 -55
  54. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
  55. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +152 -79
  56. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
  57. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +75 -63
  58. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
  59. package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +3 -1
  60. package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
  61. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
  62. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +235 -87
  63. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
  64. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +199 -86
  65. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
  66. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
  67. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js +21 -40
  68. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js.map +1 -1
  69. package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +117 -45
  70. package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
  71. package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +249 -90
  72. package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
  73. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +47 -45
  74. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
  75. package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
  76. package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +262 -133
  77. package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
  78. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +144 -77
  79. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
  80. package/dist/crewfoundry/store/crewfoundryStore.js +306 -51
  81. package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
  82. package/package.json +1 -1
@@ -1,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 { Download as r, File as i, FileText as a, Image as o, Search as s, Upload as c } from "lucide-react";
4
- import { Fragment as l, jsx as u, jsxs as d } from "react/jsx-runtime";
5
- import { Badge as f, Button as p, CardContent as m, CardHeader as h, CardTitle as g, GlassCard as _, GradientText as v, IllustratedEmptyState as y, Input as b, PagePurpose as x } from "@burdenoff/fe-libs/ui";
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 S = (e) => e === "image" ? /* @__PURE__ */ u(o, { className: "h-5 w-5 text-action-primary-bg" }) : e === "pdf" ? /* @__PURE__ */ u(a, { className: "h-5 w-5 text-status-error-text" }) : /* @__PURE__ */ u(i, { className: "h-5 w-5 text-status-info-text" }), C = (e) => {
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 w() {
12
- let [i, a] = n(""), { announcements: o, invoices: w, projects: T, employees: E } = e(), D = t(() => {
13
- let e = o.slice(0, 8).map((e, t) => {
14
- let n = E[t % Math.max(E.length, 1)];
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: C(e.createdAt),
22
+ date: T(e.createdAt),
22
23
  department: n?.department || "Operations"
23
24
  };
24
- }), t = w.slice(0, 6).map((e, 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: C(e.issueDate),
31
+ date: T(e.issueDate),
31
32
  department: t % 2 == 0 ? "Finance" : "Billing"
32
- })), n = T.slice(0, 6).map((e, t) => ({
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: C(e.startDate),
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
- w,
50
- T
51
- ]), O = D.filter((e) => e.name.toLowerCase().includes(i.toLowerCase()));
52
- return /* @__PURE__ */ d("div", {
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__ */ d("div", {
56
+ /* @__PURE__ */ f("div", {
56
57
  className: "flex items-center justify-between",
57
- children: [/* @__PURE__ */ d("div", { children: [
58
- /* @__PURE__ */ u("h1", {
58
+ children: [/* @__PURE__ */ f("div", { children: [
59
+ /* @__PURE__ */ d("h1", {
59
60
  className: "text-2xl font-semibold",
60
- children: /* @__PURE__ */ u(v, { children: "Shared Files" })
61
+ children: /* @__PURE__ */ d(y, { children: "Shared Files" })
61
62
  }),
62
- /* @__PURE__ */ d("p", {
63
+ /* @__PURE__ */ f("p", {
63
64
  className: "text-sm text-text-secondary",
64
- children: [D.length, " files shared across teams"]
65
+ children: [A.length, " files shared across teams"]
65
66
  }),
66
- /* @__PURE__ */ u(x, {
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__ */ d(p, {
71
+ ] }), /* @__PURE__ */ f(m, {
71
72
  size: "sm",
72
- children: [/* @__PURE__ */ u(c, { className: "mr-1 h-4 w-4" }), "Upload File"]
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__ */ d("div", {
77
+ /* @__PURE__ */ f("div", {
76
78
  className: "relative max-w-sm",
77
- children: [/* @__PURE__ */ u(s, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ u(b, {
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: i,
81
- onChange: (e) => a(e.target.value)
82
+ value: r,
83
+ onChange: (e) => i(e.target.value)
82
84
  })]
83
85
  }),
84
- /* @__PURE__ */ d(_, {
86
+ /* @__PURE__ */ f(v, {
85
87
  treatment: "glass",
86
88
  glow: !0,
87
89
  className: "border-border-seam",
88
- children: [/* @__PURE__ */ u(h, { children: /* @__PURE__ */ u(g, { children: "Workspace Files" }) }), /* @__PURE__ */ u(m, {
90
+ children: [/* @__PURE__ */ d(g, { children: /* @__PURE__ */ d(_, { children: "Workspace Files" }) }), /* @__PURE__ */ d(h, {
89
91
  className: "p-0",
90
- children: O.length === 0 ? /* @__PURE__ */ u("div", {
92
+ children: j.length === 0 ? /* @__PURE__ */ d("div", {
91
93
  className: "p-6",
92
- children: /* @__PURE__ */ u(y, {
94
+ children: /* @__PURE__ */ d(b, {
93
95
  illustration: "empty-files",
94
96
  title: "No files found",
95
- description: "Upload a file or adjust your search to see results here."
97
+ description: "Upload files in the Files app or adjust your search to see results here."
96
98
  })
97
- }) : /* @__PURE__ */ d(l, { children: [/* @__PURE__ */ d("div", {
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__ */ u("span", {
102
+ /* @__PURE__ */ d("span", {
101
103
  className: "col-span-2",
102
104
  children: "Name"
103
105
  }),
104
- /* @__PURE__ */ u("span", { children: "Uploaded By" }),
105
- /* @__PURE__ */ u("span", { children: "Department" }),
106
- /* @__PURE__ */ u("span", { children: "Date" }),
107
- /* @__PURE__ */ u("span", {
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
- }), O.map((e) => /* @__PURE__ */ d("div", {
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__ */ d("div", {
117
+ /* @__PURE__ */ f("div", {
116
118
  className: "col-span-2 flex items-center gap-2",
117
- children: [S(e.type), /* @__PURE__ */ u("span", {
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__ */ u("span", {
124
+ /* @__PURE__ */ d("span", {
123
125
  className: "text-text-secondary",
124
126
  children: e.uploadedBy
125
127
  }),
126
- /* @__PURE__ */ u(f, {
128
+ /* @__PURE__ */ d(p, {
127
129
  variant: "outline",
128
130
  className: "w-fit text-[10px]",
129
131
  children: e.department
130
132
  }),
131
- /* @__PURE__ */ u("span", {
133
+ /* @__PURE__ */ d("span", {
132
134
  className: "text-text-secondary",
133
135
  children: e.date
134
136
  }),
135
- /* @__PURE__ */ d("div", {
137
+ /* @__PURE__ */ f("div", {
136
138
  className: "flex items-center justify-end gap-2",
137
- children: [/* @__PURE__ */ u("span", {
139
+ children: [/* @__PURE__ */ d("span", {
138
140
  className: "text-text-secondary",
139
141
  children: e.size
140
- }), /* @__PURE__ */ u(p, {
142
+ }), /* @__PURE__ */ d(m, {
141
143
  variant: "outline",
142
144
  size: "sm",
143
145
  className: "h-7",
144
- children: /* @__PURE__ */ u(r, { className: "h-3 w-3" })
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 { w as CommunicationsFilesPagePage };
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 _ = (e) => {
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 v() {
14
- let [v, y] = n(""), { teams: b, employees: x, announcements: S, notifications: C } = e(), w = t(() => {
15
- let e = x.slice(0, 8).map((e, t) => {
16
- let n = S[t % Math.max(S.length, 1)], r = n?.content || `Status update for ${e.department} initiatives.`;
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: _(n?.createdAt || e.startDate),
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 = b.slice(0, 5).map((e, t) => {
27
- let n = C.slice(t, t + 3).filter((e) => !e.read).length;
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: S[t % Math.max(S.length, 1)]?.title || `${e.leadName} posted an update in ${e.name}.`,
33
- time: _(e.createdAt),
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
- S,
41
- x,
41
+ w,
42
42
  C,
43
- b
44
- ]).filter((e) => e.name.toLowerCase().includes(v.toLowerCase()));
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(c, {
64
- size: "sm",
65
- children: [/* @__PURE__ */ a(r, { className: "mr-1 h-4 w-4" }), "New Message"]
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: v,
74
- onChange: (e) => y(e.target.value)
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: w.length === 0 ? /* @__PURE__ */ a("div", {
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
- }) : w.map((e) => /* @__PURE__ */ o("div", {
91
- className: "flex cursor-pointer items-center gap-3 border-b p-4 last:border-0 hover:bg-bg-sunken/50",
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 { v as CommunicationsMessagesPagePage };
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":"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"}
@@ -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 v = (e) => `${Math.max(e, 15)} min`, y = (e) => {
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
- }, b = (e) => {
11
+ }, x = (e) => {
11
12
  let t = new Date(e);
12
13
  return Number.isNaN(t.getTime()) ? "Upcoming" : t.toLocaleDateString();
13
14
  };
14
- function x() {
15
- let { teams: x, interviews: S, announcements: C } = e(), w = t(() => {
16
- let e = x.slice(0, 6).map((e, t) => ({
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: b(e.createdAt),
21
- duration: v(15 + t * 10),
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 = S.slice(0, 4).map((e) => ({
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: b(e.date),
29
- duration: v(Number.parseInt(e.time.split(":")[0] || "30", 10)),
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
- }, [S, x]), T = t(() => C.slice(0, 6).map((e) => {
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: b(e.createdAt),
40
- duration: y(t),
40
+ date: x(e.createdAt),
41
+ duration: b(t),
41
42
  size: `${(t / 10).toFixed(1)} GB`
42
43
  };
43
- }), [C]), E = w.length ? Math.round(w.map((e) => Number.parseInt(e.duration.split(" ")[0], 10)).reduce((e, t) => e + t, 0) / w.length) : 0;
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: [/* @__PURE__ */ c(u, {
65
- variant: "outline",
66
- size: "sm",
67
- children: [/* @__PURE__ */ s(n, { className: "mr-1 h-4 w-4" }), "Schedule"]
68
- }), /* @__PURE__ */ c(u, {
69
- size: "sm",
70
- children: [/* @__PURE__ */ s(o, { className: "mr-1 h-4 w-4" }), "Start Meeting"]
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: w.length
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: T.length
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: [E, " min"]
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: w.map((e) => /* @__PURE__ */ c("div", {
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: T.map((e) => /* @__PURE__ */ c("div", {
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 { x as CommunicationsVideoCallsPagePage };
211
+ export { S as CommunicationsVideoCallsPagePage };
197
212
 
198
213
  //# sourceMappingURL=CommunicationsVideoCallsPagePage.js.map