@burdenoff/microfe-crewfoundry 2026.703.2 → 2026.704.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 (127) hide show
  1. package/dist/crewfoundry/pages/AdminAdminPagePage.js +117 -164
  2. package/dist/crewfoundry/pages/AdminAdminPagePage.js.map +1 -1
  3. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +99 -82
  4. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  5. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +160 -192
  6. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
  7. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +238 -231
  8. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
  9. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +196 -166
  10. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
  11. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +45 -147
  12. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +1 -1
  13. package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js +20 -11
  14. package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js.map +1 -1
  15. package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js +45 -152
  16. package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js.map +1 -1
  17. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +50 -138
  18. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
  19. package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js +149 -67
  20. package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js.map +1 -1
  21. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +50 -201
  22. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +1 -1
  23. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +205 -136
  24. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
  25. package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js +25 -31
  26. package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js.map +1 -1
  27. package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js +118 -104
  28. package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js.map +1 -1
  29. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +117 -58
  30. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
  31. package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js +90 -94
  32. package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js.map +1 -1
  33. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +210 -191
  34. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
  35. package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +213 -180
  36. package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
  37. package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js +133 -264
  38. package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js.map +1 -1
  39. package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js +279 -212
  40. package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js.map +1 -1
  41. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +131 -105
  42. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
  43. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +167 -148
  44. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
  45. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +3 -3
  46. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
  47. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +13 -5
  48. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
  49. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +151 -152
  50. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
  51. package/dist/crewfoundry/pages/HiringJobsPagePage.js +38 -21
  52. package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
  53. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +3 -3
  54. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
  55. package/dist/crewfoundry/pages/HrEmployeesPagePage.js +134 -127
  56. package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
  57. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +163 -132
  58. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
  59. package/dist/crewfoundry/pages/HrPayrollPagePage.js +202 -160
  60. package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
  61. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +104 -91
  62. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
  63. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +29 -147
  64. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
  65. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +22 -106
  66. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
  67. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +74 -74
  68. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
  69. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +101 -97
  70. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
  71. package/dist/crewfoundry/pages/LearningCoursesPagePage.js +64 -47
  72. package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
  73. package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js +111 -121
  74. package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js.map +1 -1
  75. package/dist/crewfoundry/pages/LearningLearningPagePage.js +131 -110
  76. package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
  77. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +65 -64
  78. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
  79. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +58 -43
  80. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
  81. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +66 -82
  82. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
  83. package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +38 -88
  84. package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
  85. package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +59 -65
  86. package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +1 -1
  87. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +209 -323
  88. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +1 -1
  89. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +175 -220
  90. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
  91. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +74 -59
  92. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
  93. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +96 -80
  94. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
  95. package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js +28 -100
  96. package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js.map +1 -1
  97. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +27 -20
  98. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
  99. package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +73 -73
  100. package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +1 -1
  101. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +62 -56
  102. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
  103. package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js +40 -138
  104. package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js.map +1 -1
  105. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +126 -93
  106. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
  107. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +99 -77
  108. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
  109. package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js +73 -74
  110. package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js.map +1 -1
  111. package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +1 -1
  112. package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
  113. package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +122 -122
  114. package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
  115. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +130 -113
  116. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
  117. package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js +68 -59
  118. package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
  119. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +73 -62
  120. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
  121. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +82 -58
  122. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
  123. package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +153 -153
  124. package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
  125. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +63 -48
  126. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
  127. package/package.json +1 -1
@@ -2,65 +2,52 @@ import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
2
  import { useMemo as t } from "react";
3
3
  import { AlertTriangle as n, CheckCircle as r, Shield as i, ShieldCheck as a } from "lucide-react";
4
4
  import { jsx as o, jsxs as s } from "react/jsx-runtime";
5
- import { Badge as c, Button as l, Card as u, CardContent as d, CardHeader as f, CardTitle as p, GlassCard as m, GradientText as h, PagePurpose as g } from "@burdenoff/fe-libs/ui";
5
+ import { Badge as c, Button as l, Card as u, CardContent as d, CardDescription as f, CardHeader as p, CardTitle as m, GlassCard as h, GradientText as g, IllustratedEmptyState as _, PagePurpose as v } from "@burdenoff/fe-libs/ui";
6
6
  //#region src/crewfoundry/pages/PaymentsSecurityPagePage.tsx
7
- var _ = (e) => {
8
- let t = new Date(e);
9
- return Number.isNaN(t.getTime()) ? "Unknown" : t.toISOString().split("T")[0];
10
- }, v = (e) => {
7
+ var y = (e) => {
11
8
  let t = new Date(e);
12
9
  if (Number.isNaN(t.getTime())) return "recently";
13
10
  let n = Math.max(1, Math.floor((Date.now() - t.getTime()) / (1e3 * 60 * 60)));
14
11
  return n < 24 ? `${n}h ago` : `${Math.floor(n / 24)}d ago`;
15
12
  };
16
- function y() {
17
- let { notifications: y, invoices: b, payrollRecords: x } = e(), S = t(() => {
18
- let e = b.filter((e) => e.status === "overdue").length, t = x.filter((e) => e.status === "failed").length, n = e > 0 || t > 0;
13
+ function b() {
14
+ let { notifications: b, invoices: x, payrollRecords: S } = e(), C = t(() => {
15
+ let e = x.filter((e) => e.status === "overdue").length, t = S.filter((e) => e.status === "failed").length, n = b.filter((e) => e.type === "error").length, r = b.filter((e) => e.type === "warning").length;
19
16
  return [
20
17
  {
21
- name: "PCI DSS Compliance",
22
- status: "passed",
23
- lastChecked: _((/* @__PURE__ */ new Date()).toISOString())
24
- },
25
- {
26
- name: "SSL/TLS Encryption",
27
- status: "passed",
28
- lastChecked: _((/* @__PURE__ */ new Date()).toISOString())
29
- },
30
- {
31
- name: "Two-Factor Authentication",
32
- status: "passed",
33
- lastChecked: _((/* @__PURE__ */ new Date()).toISOString())
18
+ name: "Overdue invoices",
19
+ detail: e > 0 ? `${e} invoice${e === 1 ? "" : "s"} past due` : "No overdue invoices",
20
+ status: e > 0 ? "warning" : "ok"
34
21
  },
35
22
  {
36
- name: "Data Encryption at Rest",
37
- status: "passed",
38
- lastChecked: _((/* @__PURE__ */ new Date()).toISOString())
23
+ name: "Payroll runs",
24
+ detail: t > 0 ? `${t} failed payroll run${t === 1 ? "" : "s"}` : "All payroll runs healthy",
25
+ status: t > 0 ? "warning" : "ok"
39
26
  },
40
27
  {
41
- name: "Payment Processing Audit",
42
- status: n ? "warning" : "passed",
43
- lastChecked: _((/* @__PURE__ */ new Date()).toISOString())
28
+ name: "Critical alerts",
29
+ detail: n > 0 ? `${n} unresolved critical alert${n === 1 ? "" : "s"}` : "No critical alerts",
30
+ status: n > 0 ? "warning" : "ok"
44
31
  },
45
32
  {
46
- name: "Access Control Review",
47
- status: y.some((e) => e.type === "error") ? "warning" : "passed",
48
- lastChecked: _((/* @__PURE__ */ new Date()).toISOString())
33
+ name: "Open warnings",
34
+ detail: r > 0 ? `${r} open warning${r === 1 ? "" : "s"}` : "No open warnings",
35
+ status: r > 0 ? "warning" : "ok"
49
36
  }
50
37
  ];
51
38
  }, [
39
+ x,
52
40
  b,
53
- y,
54
- x
55
- ]), C = t(() => y.slice(0, 6).map((e) => {
41
+ S
42
+ ]), w = t(() => b.slice(0, 6).map((e) => {
56
43
  let t = e.type === "error" ? "medium" : e.type === "warning" ? "low" : "info";
57
44
  return {
58
45
  id: e.id,
59
46
  message: e.message,
60
47
  severity: t,
61
- time: v(e.createdAt)
48
+ time: y(e.createdAt)
62
49
  };
63
- }), [y]), w = S.filter((e) => e.status === "passed").length, T = Math.round(w / Math.max(S.length, 1) * 100);
50
+ }), [b]), T = C.filter((e) => e.status === "warning").length, E = C.filter((e) => e.status === "ok").length;
64
51
  return /* @__PURE__ */ s("div", {
65
52
  className: "space-y-6 p-6",
66
53
  children: [
@@ -69,100 +56,112 @@ function y() {
69
56
  children: [/* @__PURE__ */ s("div", { children: [
70
57
  /* @__PURE__ */ o("h1", {
71
58
  className: "text-2xl font-semibold",
72
- children: /* @__PURE__ */ o(h, { children: "Payment Security" })
59
+ children: /* @__PURE__ */ o(g, { children: "Payment Security" })
73
60
  }),
74
61
  /* @__PURE__ */ o("p", {
75
62
  className: "text-sm text-text-secondary",
76
- children: "Security controls and compliance status"
63
+ children: "Account health and payment alerts"
77
64
  }),
78
- /* @__PURE__ */ o(g, {
65
+ /* @__PURE__ */ o(v, {
79
66
  className: "mt-1",
80
- children: "Protect your account and payments — review security settings, activity, and safeguards that keep your money and data safe."
67
+ children: "Protect your account and payments — review live health signals and alerts derived from your invoices, payroll, and activity."
81
68
  })
82
69
  ] }), /* @__PURE__ */ s(l, {
83
70
  variant: "outline",
84
71
  size: "sm",
85
- children: [/* @__PURE__ */ o(i, { className: "mr-1 h-4 w-4" }), "Run Audit"]
72
+ disabled: !0,
73
+ "aria-label": "Run external security audit (coming soon)",
74
+ title: "External security audit is coming soon",
75
+ children: [
76
+ /* @__PURE__ */ o(i, { className: "mr-1 h-4 w-4" }),
77
+ "Run Audit",
78
+ /* @__PURE__ */ o(c, {
79
+ variant: "secondary",
80
+ className: "ml-1 text-[9px]",
81
+ children: "Soon"
82
+ })
83
+ ]
86
84
  })]
87
85
  }),
88
86
  /* @__PURE__ */ s("div", {
89
87
  className: "grid gap-4 md:grid-cols-3",
90
88
  children: [
91
- /* @__PURE__ */ s(m, {
89
+ /* @__PURE__ */ s(h, {
92
90
  treatment: "glass",
93
91
  glow: !0,
94
92
  className: "border-border-seam",
95
- children: [/* @__PURE__ */ s(f, {
93
+ children: [/* @__PURE__ */ s(p, {
96
94
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
97
- children: [/* @__PURE__ */ o(p, {
95
+ children: [/* @__PURE__ */ o(m, {
98
96
  className: "text-sm font-medium",
99
- children: "Security Score"
100
- }), /* @__PURE__ */ o(a, { className: "h-4 w-4 text-status-success-text" })]
101
- }), /* @__PURE__ */ o(d, { children: /* @__PURE__ */ s("div", {
97
+ children: "Needs Attention"
98
+ }), /* @__PURE__ */ o(n, { className: "h-4 w-4 text-status-warning-text" })]
99
+ }), /* @__PURE__ */ o(d, { children: /* @__PURE__ */ o("div", {
102
100
  className: "text-2xl font-bold tabular-nums",
103
- children: [T, "/100"]
101
+ children: T
104
102
  }) })]
105
103
  }),
106
- /* @__PURE__ */ s(m, {
104
+ /* @__PURE__ */ s(h, {
107
105
  treatment: "metric",
108
106
  className: "border-border-seam",
109
- children: [/* @__PURE__ */ s(f, {
107
+ children: [/* @__PURE__ */ s(p, {
110
108
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
111
- children: [/* @__PURE__ */ o(p, {
109
+ children: [/* @__PURE__ */ o(m, {
112
110
  className: "text-sm font-medium",
113
- children: "Checks Passing"
114
- }), /* @__PURE__ */ o(r, { className: "h-4 w-4 text-status-success-text" })]
111
+ children: "All Clear"
112
+ }), /* @__PURE__ */ o(a, { className: "h-4 w-4 text-status-success-text" })]
115
113
  }), /* @__PURE__ */ o(d, { children: /* @__PURE__ */ s("div", {
116
114
  className: "text-2xl font-bold tabular-nums",
117
115
  children: [
118
- w,
116
+ E,
119
117
  "/",
120
- S.length
118
+ C.length
121
119
  ]
122
120
  }) })]
123
121
  }),
124
- /* @__PURE__ */ s(m, {
122
+ /* @__PURE__ */ s(h, {
125
123
  treatment: "metric",
126
124
  className: "border-border-seam",
127
- children: [/* @__PURE__ */ s(f, {
125
+ children: [/* @__PURE__ */ s(p, {
128
126
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
129
- children: [/* @__PURE__ */ o(p, {
127
+ children: [/* @__PURE__ */ o(m, {
130
128
  className: "text-sm font-medium",
131
129
  children: "Active Alerts"
132
130
  }), /* @__PURE__ */ o(n, { className: "h-4 w-4 text-status-warning-text" })]
133
131
  }), /* @__PURE__ */ o(d, { children: /* @__PURE__ */ o("div", {
134
132
  className: "text-2xl font-bold tabular-nums",
135
- children: C.length
133
+ children: w.length
136
134
  }) })]
137
135
  })
138
136
  ]
139
137
  }),
140
- /* @__PURE__ */ s(u, { children: [/* @__PURE__ */ o(f, { children: /* @__PURE__ */ o(p, { children: "Security Checks" }) }), /* @__PURE__ */ o(d, {
138
+ /* @__PURE__ */ s(u, { children: [/* @__PURE__ */ s(p, { children: [/* @__PURE__ */ o(m, { children: "Account & Payment Health" }), /* @__PURE__ */ o(f, { children: "Live checks derived from your invoices, payroll, and alerts — not compliance certifications." })] }), /* @__PURE__ */ o(d, {
141
139
  className: "space-y-3",
142
- children: S.map((e) => /* @__PURE__ */ s("div", {
140
+ children: C.map((e) => /* @__PURE__ */ s("div", {
143
141
  className: "flex items-center justify-between rounded border p-3",
144
142
  children: [/* @__PURE__ */ s("div", {
145
143
  className: "flex items-center gap-2",
146
- children: [e.status === "passed" ? /* @__PURE__ */ o(r, { className: "h-4 w-4 text-status-success-text" }) : /* @__PURE__ */ o(n, { className: "h-4 w-4 text-status-warning-text" }), /* @__PURE__ */ o("span", {
144
+ children: [e.status === "ok" ? /* @__PURE__ */ o(r, { className: "h-4 w-4 text-status-success-text" }) : /* @__PURE__ */ o(n, { className: "h-4 w-4 text-status-warning-text" }), /* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("p", {
147
145
  className: "text-sm font-medium",
148
146
  children: e.name
149
- })]
150
- }), /* @__PURE__ */ s("div", {
151
- className: "flex items-center gap-2",
152
- children: [/* @__PURE__ */ s("span", {
147
+ }), /* @__PURE__ */ o("p", {
153
148
  className: "text-xs text-text-secondary",
154
- children: ["Last: ", e.lastChecked]
155
- }), /* @__PURE__ */ o(c, {
156
- variant: e.status === "passed" ? "default" : "secondary",
157
- className: "text-[10px]",
158
- children: e.status
159
- })]
149
+ children: e.detail
150
+ })] })]
151
+ }), /* @__PURE__ */ o(c, {
152
+ variant: e.status === "ok" ? "default" : "secondary",
153
+ className: "text-[10px]",
154
+ children: e.status === "ok" ? "clear" : "attention"
160
155
  })]
161
156
  }, e.name))
162
157
  })] }),
163
- /* @__PURE__ */ s(u, { children: [/* @__PURE__ */ o(f, { children: /* @__PURE__ */ o(p, { children: "Security Alerts" }) }), /* @__PURE__ */ o(d, {
158
+ /* @__PURE__ */ s(u, { children: [/* @__PURE__ */ o(p, { children: /* @__PURE__ */ o(m, { children: "Recent Alerts" }) }), /* @__PURE__ */ o(d, {
164
159
  className: "space-y-3",
165
- children: C.map((e) => /* @__PURE__ */ s("div", {
160
+ children: w.length === 0 ? /* @__PURE__ */ o(_, {
161
+ illustration: "empty-notifications",
162
+ title: "No alerts",
163
+ description: "Payment and account alerts will show up here."
164
+ }) : w.map((e) => /* @__PURE__ */ s("div", {
166
165
  className: "flex items-center justify-between rounded border p-3",
167
166
  children: [/* @__PURE__ */ s("div", {
168
167
  className: "flex items-center gap-2",
@@ -187,6 +186,6 @@ function y() {
187
186
  });
188
187
  }
189
188
  //#endregion
190
- export { y as PaymentsSecurityPagePage };
189
+ export { b as PaymentsSecurityPagePage };
191
190
 
192
191
  //# sourceMappingURL=PaymentsSecurityPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PaymentsSecurityPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/PaymentsSecurityPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { AlertTriangle, CheckCircle, Shield, ShieldCheck } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype SecurityCheck = {\n name: string;\n status: 'passed' | 'warning';\n lastChecked: string;\n};\n\ntype SecurityAlert = {\n id: string;\n message: string;\n severity: 'medium' | 'low' | 'info';\n time: string;\n};\n\nconst formatDate = (value: string): string => {\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n return 'Unknown';\n }\n return parsed.toISOString().split('T')[0];\n};\n\nconst timeAgo = (value: string): string => {\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n return 'recently';\n }\n const hours = Math.max(1, Math.floor((Date.now() - parsed.getTime()) / (1000 * 60 * 60)));\n return hours < 24 ? `${hours}h ago` : `${Math.floor(hours / 24)}d ago`;\n};\n\nexport function PaymentsSecurityPagePage() {\n const { notifications, invoices, payrollRecords } = useCrewFoundryStore();\n\n const securityChecks = useMemo<SecurityCheck[]>(() => {\n const failedInvoices = invoices.filter((invoice) => invoice.status === 'overdue').length;\n const payrollFailures = payrollRecords.filter((record) => record.status === 'failed').length;\n const warning = failedInvoices > 0 || payrollFailures > 0;\n\n return [\n {\n name: 'PCI DSS Compliance',\n status: 'passed',\n lastChecked: formatDate(new Date().toISOString()),\n },\n {\n name: 'SSL/TLS Encryption',\n status: 'passed',\n lastChecked: formatDate(new Date().toISOString()),\n },\n {\n name: 'Two-Factor Authentication',\n status: 'passed',\n lastChecked: formatDate(new Date().toISOString()),\n },\n {\n name: 'Data Encryption at Rest',\n status: 'passed',\n lastChecked: formatDate(new Date().toISOString()),\n },\n {\n name: 'Payment Processing Audit',\n status: warning ? 'warning' : 'passed',\n lastChecked: formatDate(new Date().toISOString()),\n },\n {\n name: 'Access Control Review',\n status: notifications.some((notification) => notification.type === 'error')\n ? 'warning'\n : 'passed',\n lastChecked: formatDate(new Date().toISOString()),\n },\n ];\n }, [invoices, notifications, payrollRecords]);\n\n const recentAlerts = useMemo<SecurityAlert[]>(() => {\n return notifications.slice(0, 6).map((notification) => {\n const severity: SecurityAlert['severity'] =\n notification.type === 'error' ? 'medium' : notification.type === 'warning' ? 'low' : 'info';\n\n return {\n id: notification.id,\n message: notification.message,\n severity,\n time: timeAgo(notification.createdAt),\n };\n });\n }, [notifications]);\n\n const passedChecks = securityChecks.filter((check) => check.status === 'passed').length;\n const securityScore = Math.round((passedChecks / Math.max(securityChecks.length, 1)) * 100);\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>Payment Security</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Security controls and compliance status</p>\n <PagePurpose className=\"mt-1\">Protect your account and payments — review security settings, activity, and safeguards that keep your money and data safe.</PagePurpose>\n </div>\n <Button variant=\"outline\" size=\"sm\">\n <Shield className=\"mr-1 h-4 w-4\" />\n Run Audit\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Security Score</CardTitle>\n <ShieldCheck className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{securityScore}/100</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Checks Passing</CardTitle>\n <CheckCircle className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {passedChecks}/{securityChecks.length}\n </div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Active Alerts</CardTitle>\n <AlertTriangle className=\"h-4 w-4 text-status-warning-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{recentAlerts.length}</div>\n </CardContent>\n </GlassCard>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Security Checks</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {securityChecks.map((check) => (\n <div key={check.name} className=\"flex items-center justify-between rounded border p-3\">\n <div className=\"flex items-center gap-2\">\n {check.status === 'passed' ? (\n <CheckCircle className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertTriangle className=\"h-4 w-4 text-status-warning-text\" />\n )}\n <span className=\"text-sm font-medium\">{check.name}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-secondary\">Last: {check.lastChecked}</span>\n <Badge\n variant={check.status === 'passed' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {check.status}\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Security Alerts</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {recentAlerts.map((alert) => (\n <div key={alert.id} className=\"flex items-center justify-between rounded border p-3\">\n <div className=\"flex items-center gap-2\">\n <AlertTriangle\n className={`h-4 w-4 ${\n alert.severity === 'medium'\n ? 'text-status-warning-text'\n : alert.severity === 'low'\n ? 'text-status-info-text'\n : 'text-text-secondary'\n }`}\n />\n <span className=\"text-sm\">{alert.message}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-secondary\">{alert.time}</span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {alert.severity}\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"PaymentsSecurityPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/PaymentsSecurityPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { AlertTriangle, CheckCircle, Shield, ShieldCheck } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype HealthCheck = {\n name: string;\n detail: string;\n status: 'ok' | 'warning';\n};\n\ntype SecurityAlert = {\n id: string;\n message: string;\n severity: 'medium' | 'low' | 'info';\n time: string;\n};\n\nconst timeAgo = (value: string): string => {\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n return 'recently';\n }\n const hours = Math.max(1, Math.floor((Date.now() - parsed.getTime()) / (1000 * 60 * 60)));\n return hours < 24 ? `${hours}h ago` : `${Math.floor(hours / 24)}d ago`;\n};\n\nexport function PaymentsSecurityPagePage() {\n const { notifications, invoices, payrollRecords } = useCrewFoundryStore();\n\n const healthChecks = useMemo<HealthCheck[]>(() => {\n const overdueInvoices = invoices.filter((invoice) => invoice.status === 'overdue').length;\n const failedPayroll = payrollRecords.filter((record) => record.status === 'failed').length;\n const criticalAlerts = notifications.filter((note) => note.type === 'error').length;\n const openWarnings = notifications.filter((note) => note.type === 'warning').length;\n\n return [\n {\n name: 'Overdue invoices',\n detail:\n overdueInvoices > 0\n ? `${overdueInvoices} invoice${overdueInvoices === 1 ? '' : 's'} past due`\n : 'No overdue invoices',\n status: overdueInvoices > 0 ? 'warning' : 'ok',\n },\n {\n name: 'Payroll runs',\n detail:\n failedPayroll > 0\n ? `${failedPayroll} failed payroll run${failedPayroll === 1 ? '' : 's'}`\n : 'All payroll runs healthy',\n status: failedPayroll > 0 ? 'warning' : 'ok',\n },\n {\n name: 'Critical alerts',\n detail:\n criticalAlerts > 0\n ? `${criticalAlerts} unresolved critical alert${criticalAlerts === 1 ? '' : 's'}`\n : 'No critical alerts',\n status: criticalAlerts > 0 ? 'warning' : 'ok',\n },\n {\n name: 'Open warnings',\n detail:\n openWarnings > 0\n ? `${openWarnings} open warning${openWarnings === 1 ? '' : 's'}`\n : 'No open warnings',\n status: openWarnings > 0 ? 'warning' : 'ok',\n },\n ];\n }, [invoices, notifications, payrollRecords]);\n\n const recentAlerts = useMemo<SecurityAlert[]>(() => {\n return notifications.slice(0, 6).map((notification) => {\n const severity: SecurityAlert['severity'] =\n notification.type === 'error' ? 'medium' : notification.type === 'warning' ? 'low' : 'info';\n\n return {\n id: notification.id,\n message: notification.message,\n severity,\n time: timeAgo(notification.createdAt),\n };\n });\n }, [notifications]);\n\n const attentionNeeded = healthChecks.filter((check) => check.status === 'warning').length;\n const allClear = healthChecks.filter((check) => check.status === 'ok').length;\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>Payment Security</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Account health and payment alerts</p>\n <PagePurpose className=\"mt-1\">Protect your account and payments — review live health signals and alerts derived from your invoices, payroll, and activity.</PagePurpose>\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled\n aria-label=\"Run external security audit (coming soon)\"\n title=\"External security audit is coming soon\"\n >\n <Shield className=\"mr-1 h-4 w-4\" />\n Run Audit\n <Badge variant=\"secondary\" className=\"ml-1 text-[9px]\">\n Soon\n </Badge>\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Needs Attention</CardTitle>\n <AlertTriangle className=\"h-4 w-4 text-status-warning-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{attentionNeeded}</div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">All Clear</CardTitle>\n <ShieldCheck className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {allClear}/{healthChecks.length}\n </div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Active Alerts</CardTitle>\n <AlertTriangle className=\"h-4 w-4 text-status-warning-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{recentAlerts.length}</div>\n </CardContent>\n </GlassCard>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Account &amp; Payment Health</CardTitle>\n <CardDescription>\n Live checks derived from your invoices, payroll, and alerts — not compliance\n certifications.\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {healthChecks.map((check) => (\n <div key={check.name} className=\"flex items-center justify-between rounded border p-3\">\n <div className=\"flex items-center gap-2\">\n {check.status === 'ok' ? (\n <CheckCircle className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertTriangle className=\"h-4 w-4 text-status-warning-text\" />\n )}\n <div>\n <p className=\"text-sm font-medium\">{check.name}</p>\n <p className=\"text-xs text-text-secondary\">{check.detail}</p>\n </div>\n </div>\n <Badge\n variant={check.status === 'ok' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {check.status === 'ok' ? 'clear' : 'attention'}\n </Badge>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Recent Alerts</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {recentAlerts.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title=\"No alerts\"\n description=\"Payment and account alerts will show up here.\"\n />\n ) : (\n recentAlerts.map((alert) => (\n <div key={alert.id} className=\"flex items-center justify-between rounded border p-3\">\n <div className=\"flex items-center gap-2\">\n <AlertTriangle\n className={`h-4 w-4 ${\n alert.severity === 'medium'\n ? 'text-status-warning-text'\n : alert.severity === 'low'\n ? 'text-status-info-text'\n : 'text-text-secondary'\n }`}\n />\n <span className=\"text-sm\">{alert.message}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs text-text-secondary\">{alert.time}</span>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {alert.severity}\n </Badge>\n </div>\n </div>\n ))\n )}\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -109,7 +109,7 @@ function m() {
109
109
  })]
110
110
  }) : null,
111
111
  /* @__PURE__ */ o("div", {
112
- className: "grid grid-cols-2 gap-4",
112
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
113
113
  children: [/* @__PURE__ */ o("div", {
114
114
  className: "space-y-2",
115
115
  children: [/* @__PURE__ */ a("label", {
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectsCreateProjectPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/ProjectsCreateProjectPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Button,\n EmphasisPanel,\n GradientText,\n Input,\n PagePurpose,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { FolderKanban, Save } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore, type Project } from '../store/crewfoundryStore';\n\nexport function ProjectsCreateProjectPagePage() {\n const navigate = useNavigate();\n const { showToast } = useGlobalUi();\n const addProject = useCrewFoundryStore((state) => state.addProject);\n const teams = useCrewFoundryStore((state) => state.teams);\n\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [startDate, setStartDate] = useState('');\n const [endDate, setEndDate] = useState('');\n const [budget, setBudget] = useState('');\n const [teamId, setTeamId] = useState('');\n const [submitting, setSubmitting] = useState(false);\n\n const handleCreate = async (status: Project['status']) => {\n if (submitting) return;\n if (name.trim() === '') {\n showToast('Project Name is required', 'warning');\n return;\n }\n const selectedTeam = teams.find((team) => team.id === teamId);\n const budgetValue = budget.trim() === '' ? undefined : Number(budget);\n // CreateCrewProjectInput only accepts a known field subset; build exactly\n // that shape. The store replaces this optimistic row with the server's\n // complete Project, so display-only fields need not be provided here.\n const payload: Partial<Project> = {\n name: name.trim(),\n description: description.trim(),\n status,\n priority: 'medium',\n ...(startDate ? { startDate } : {}),\n ...(endDate ? { endDate } : {}),\n ...(budgetValue !== undefined && !Number.isNaN(budgetValue) ? { budget: budgetValue } : {}),\n ...(selectedTeam ? { teamId: selectedTeam.id, teamName: selectedTeam.name } : {}),\n };\n setSubmitting(true);\n try {\n await addProject(payload as Project);\n showToast(\n status === 'planning' ? 'Draft project saved' : 'Project created',\n 'success'\n );\n navigate('../../projects/projects-page');\n } catch (error) {\n showToast(error instanceof Error ? error.message : 'Unable to create project', 'error');\n } finally {\n setSubmitting(false);\n }\n };\n\n const selectClass =\n 'flex h-10 w-full rounded-input border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary transition-colors duration-200 focus-visible:border-border-focus focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50';\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Create Project</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Set up a new project for your team</p>\n <PagePurpose className=\"mt-1\">Start a new project — define its scope, budget, and team here so you can begin tracking work toward a clear goal.</PagePurpose>\n </div>\n <EmphasisPanel>\n <div className=\"mb-4 flex items-center gap-2 text-lg font-semibold\">\n <FolderKanban className=\"h-5 w-5\" />\n Project Details\n </div>\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <label htmlFor=\"cpName\" className=\"text-sm font-medium\">\n Project Name\n </label>\n <Input\n id=\"cpName\"\n placeholder=\"e.g. HR Analytics Dashboard v3\"\n value={name}\n disabled={submitting}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpDesc\" className=\"text-sm font-medium\">\n Description\n </label>\n <Textarea\n id=\"cpDesc\"\n placeholder=\"Describe the project objectives and scope...\"\n rows={3}\n value={description}\n disabled={submitting}\n onChange={(e) => setDescription(e.target.value)}\n />\n </div>\n {teams.length > 0 ? (\n <div className=\"space-y-2\">\n <label htmlFor=\"cpTeam\" className=\"text-sm font-medium\">\n Team\n </label>\n <select\n id=\"cpTeam\"\n className={selectClass}\n value={teamId}\n disabled={submitting}\n onChange={(e) => setTeamId(e.target.value)}\n >\n <option value=\"\">Unassigned</option>\n {teams.map((team) => (\n <option key={team.id} value={team.id}>\n {team.name}\n </option>\n ))}\n </select>\n </div>\n ) : null}\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label htmlFor=\"cpStart\" className=\"text-sm font-medium\">\n Start Date\n </label>\n <Input\n id=\"cpStart\"\n type=\"date\"\n value={startDate}\n disabled={submitting}\n onChange={(e) => setStartDate(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpEnd\" className=\"text-sm font-medium\">\n End Date\n </label>\n <Input\n id=\"cpEnd\"\n type=\"date\"\n value={endDate}\n disabled={submitting}\n onChange={(e) => setEndDate(e.target.value)}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpBudget\" className=\"text-sm font-medium\">\n Budget ($)\n </label>\n <Input\n id=\"cpBudget\"\n type=\"number\"\n placeholder=\"e.g. 250000\"\n value={budget}\n disabled={submitting}\n onChange={(e) => setBudget(e.target.value)}\n />\n </div>\n </div>\n </EmphasisPanel>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" disabled={submitting} onClick={() => handleCreate('planning')}>\n Save as Draft\n </Button>\n <Button disabled={submitting} onClick={() => handleCreate('active')}>\n <Save className=\"h-4 w-4 mr-1\" />\n {submitting ? 'Saving…' : 'Create Project'}\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProjectsCreateProjectPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/ProjectsCreateProjectPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Button,\n EmphasisPanel,\n GradientText,\n Input,\n PagePurpose,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { FolderKanban, Save } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore, type Project } from '../store/crewfoundryStore';\n\nexport function ProjectsCreateProjectPagePage() {\n const navigate = useNavigate();\n const { showToast } = useGlobalUi();\n const addProject = useCrewFoundryStore((state) => state.addProject);\n const teams = useCrewFoundryStore((state) => state.teams);\n\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [startDate, setStartDate] = useState('');\n const [endDate, setEndDate] = useState('');\n const [budget, setBudget] = useState('');\n const [teamId, setTeamId] = useState('');\n const [submitting, setSubmitting] = useState(false);\n\n const handleCreate = async (status: Project['status']) => {\n if (submitting) return;\n if (name.trim() === '') {\n showToast('Project Name is required', 'warning');\n return;\n }\n const selectedTeam = teams.find((team) => team.id === teamId);\n const budgetValue = budget.trim() === '' ? undefined : Number(budget);\n // CreateCrewProjectInput only accepts a known field subset; build exactly\n // that shape. The store replaces this optimistic row with the server's\n // complete Project, so display-only fields need not be provided here.\n const payload: Partial<Project> = {\n name: name.trim(),\n description: description.trim(),\n status,\n priority: 'medium',\n ...(startDate ? { startDate } : {}),\n ...(endDate ? { endDate } : {}),\n ...(budgetValue !== undefined && !Number.isNaN(budgetValue) ? { budget: budgetValue } : {}),\n ...(selectedTeam ? { teamId: selectedTeam.id, teamName: selectedTeam.name } : {}),\n };\n setSubmitting(true);\n try {\n await addProject(payload as Project);\n showToast(\n status === 'planning' ? 'Draft project saved' : 'Project created',\n 'success'\n );\n navigate('../../projects/projects-page');\n } catch (error) {\n showToast(error instanceof Error ? error.message : 'Unable to create project', 'error');\n } finally {\n setSubmitting(false);\n }\n };\n\n const selectClass =\n 'flex h-10 w-full rounded-input border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary transition-colors duration-200 focus-visible:border-border-focus focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50';\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Create Project</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Set up a new project for your team</p>\n <PagePurpose className=\"mt-1\">Start a new project — define its scope, budget, and team here so you can begin tracking work toward a clear goal.</PagePurpose>\n </div>\n <EmphasisPanel>\n <div className=\"mb-4 flex items-center gap-2 text-lg font-semibold\">\n <FolderKanban className=\"h-5 w-5\" />\n Project Details\n </div>\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <label htmlFor=\"cpName\" className=\"text-sm font-medium\">\n Project Name\n </label>\n <Input\n id=\"cpName\"\n placeholder=\"e.g. HR Analytics Dashboard v3\"\n value={name}\n disabled={submitting}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpDesc\" className=\"text-sm font-medium\">\n Description\n </label>\n <Textarea\n id=\"cpDesc\"\n placeholder=\"Describe the project objectives and scope...\"\n rows={3}\n value={description}\n disabled={submitting}\n onChange={(e) => setDescription(e.target.value)}\n />\n </div>\n {teams.length > 0 ? (\n <div className=\"space-y-2\">\n <label htmlFor=\"cpTeam\" className=\"text-sm font-medium\">\n Team\n </label>\n <select\n id=\"cpTeam\"\n className={selectClass}\n value={teamId}\n disabled={submitting}\n onChange={(e) => setTeamId(e.target.value)}\n >\n <option value=\"\">Unassigned</option>\n {teams.map((team) => (\n <option key={team.id} value={team.id}>\n {team.name}\n </option>\n ))}\n </select>\n </div>\n ) : null}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <label htmlFor=\"cpStart\" className=\"text-sm font-medium\">\n Start Date\n </label>\n <Input\n id=\"cpStart\"\n type=\"date\"\n value={startDate}\n disabled={submitting}\n onChange={(e) => setStartDate(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpEnd\" className=\"text-sm font-medium\">\n End Date\n </label>\n <Input\n id=\"cpEnd\"\n type=\"date\"\n value={endDate}\n disabled={submitting}\n onChange={(e) => setEndDate(e.target.value)}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpBudget\" className=\"text-sm font-medium\">\n Budget ($)\n </label>\n <Input\n id=\"cpBudget\"\n type=\"number\"\n placeholder=\"e.g. 250000\"\n value={budget}\n disabled={submitting}\n onChange={(e) => setBudget(e.target.value)}\n />\n </div>\n </div>\n </EmphasisPanel>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" disabled={submitting} onClick={() => handleCreate('planning')}>\n Save as Draft\n </Button>\n <Button disabled={submitting} onClick={() => handleCreate('active')}>\n <Save className=\"h-4 w-4 mr-1\" />\n {submitting ? 'Saving…' : 'Create Project'}\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}