@burdenoff/microfe-crewfoundry 2026.625.1 → 2026.625.2

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 (131) hide show
  1. package/dist/crewfoundry/pages/AdminAdminPagePage.js +37 -29
  2. package/dist/crewfoundry/pages/AdminAdminPagePage.js.map +1 -1
  3. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +50 -42
  4. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  5. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +39 -31
  6. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
  7. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +52 -44
  8. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
  9. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +46 -38
  10. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
  11. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +28 -15
  12. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
  13. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +30 -22
  14. package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +1 -1
  15. package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js +87 -69
  16. package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js.map +1 -1
  17. package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js +99 -80
  18. package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js.map +1 -1
  19. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +86 -67
  20. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
  21. package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js +31 -15
  22. package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js.map +1 -1
  23. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +37 -29
  24. package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +1 -1
  25. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +29 -21
  26. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
  27. package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js +25 -17
  28. package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js.map +1 -1
  29. package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js +42 -35
  30. package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js.map +1 -1
  31. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +80 -62
  32. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
  33. package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js +41 -33
  34. package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js.map +1 -1
  35. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +142 -108
  36. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
  37. package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +177 -136
  38. package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
  39. package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js +44 -36
  40. package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js.map +1 -1
  41. package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js +49 -38
  42. package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js.map +1 -1
  43. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +26 -18
  44. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
  45. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +112 -93
  46. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
  47. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +53 -46
  48. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
  49. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +31 -23
  50. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
  51. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +129 -90
  52. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
  53. package/dist/crewfoundry/pages/HiringJobsPagePage.js +96 -85
  54. package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
  55. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +26 -18
  56. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
  57. package/dist/crewfoundry/pages/HrEmployeesPagePage.js +47 -35
  58. package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
  59. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +33 -25
  60. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
  61. package/dist/crewfoundry/pages/HrPayrollPagePage.js +36 -28
  62. package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
  63. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +27 -19
  64. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
  65. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +27 -19
  66. package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
  67. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +93 -75
  68. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
  69. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +111 -70
  70. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
  71. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +65 -53
  72. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
  73. package/dist/crewfoundry/pages/LearningCoursesPagePage.js +35 -19
  74. package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
  75. package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js +33 -25
  76. package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js.map +1 -1
  77. package/dist/crewfoundry/pages/LearningLearningPagePage.js +26 -18
  78. package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
  79. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +80 -55
  80. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
  81. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +33 -17
  82. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
  83. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +31 -23
  84. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
  85. package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +29 -21
  86. package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
  87. package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +35 -27
  88. package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +1 -1
  89. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +147 -112
  90. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +1 -1
  91. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +31 -27
  92. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
  93. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +31 -23
  94. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
  95. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +104 -85
  96. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
  97. package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js +75 -56
  98. package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js.map +1 -1
  99. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +78 -60
  100. package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
  101. package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +133 -92
  102. package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +1 -1
  103. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +93 -52
  104. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
  105. package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js +28 -20
  106. package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js.map +1 -1
  107. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +84 -65
  108. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
  109. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +25 -17
  110. package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
  111. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js +58 -40
  112. package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js.map +1 -1
  113. package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js +41 -33
  114. package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js.map +1 -1
  115. package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +36 -29
  116. package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
  117. package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +103 -72
  118. package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
  119. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +43 -27
  120. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
  121. package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js +28 -20
  122. package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
  123. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +103 -62
  124. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
  125. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +83 -64
  126. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
  127. package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +185 -144
  128. package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
  129. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +40 -24
  130. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
  131. package/package.json +2 -2
@@ -1,84 +1,102 @@
1
1
  import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
2
  import { Mail as t, Plus as n, Star as r } from "lucide-react";
3
3
  import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
- import { Badge as o, Button as s, Card as c, CardContent as l, CardHeader as u, CardTitle as d, GradientText as f } from "@burdenoff/fe-libs/ui";
4
+ import { Badge as o, Button as s, CardContent as c, CardHeader as l, CardTitle as u, GlassCard as d, GradientText as f, IllustratedEmptyState as p, PagePurpose as m } from "@burdenoff/fe-libs/ui";
5
5
  //#region src/crewfoundry/pages/CompanyVendorManagementPagePage.tsx
6
- function p() {
7
- let { vendors: p } = e(), m = p.reduce((e, t) => e + t.contractValue, 0);
6
+ function h() {
7
+ let { vendors: h } = e(), g = h.reduce((e, t) => e + t.contractValue, 0);
8
8
  return /* @__PURE__ */ a("div", {
9
9
  className: "space-y-6 p-6",
10
10
  children: [/* @__PURE__ */ a("div", {
11
11
  className: "flex items-center justify-between",
12
- children: [/* @__PURE__ */ a("div", { children: [/* @__PURE__ */ i("h1", {
13
- className: "text-2xl font-semibold",
14
- children: /* @__PURE__ */ i(f, { children: "Vendor Management" })
15
- }), /* @__PURE__ */ a("p", {
16
- className: "text-sm text-text-secondary",
17
- children: [
18
- p.length,
19
- " vendors · $",
20
- (m / 1e3).toFixed(0),
21
- "K total contract value"
22
- ]
23
- })] }), /* @__PURE__ */ a(s, {
12
+ children: [/* @__PURE__ */ a("div", { children: [
13
+ /* @__PURE__ */ i("h1", {
14
+ className: "text-2xl font-semibold",
15
+ children: /* @__PURE__ */ i(f, { children: "Vendor Management" })
16
+ }),
17
+ /* @__PURE__ */ a("p", {
18
+ className: "text-sm text-text-secondary",
19
+ children: [
20
+ h.length,
21
+ " vendors · $",
22
+ (g / 1e3).toFixed(0),
23
+ "K total contract value"
24
+ ]
25
+ }),
26
+ /* @__PURE__ */ i(m, {
27
+ className: "mt-1",
28
+ children: "Track the vendors and suppliers you depend on — contracts, contacts, and status — to manage external relationships in one place."
29
+ })
30
+ ] }), /* @__PURE__ */ a(s, {
24
31
  size: "sm",
25
32
  children: [/* @__PURE__ */ i(n, { className: "h-4 w-4 mr-1" }), "Add Vendor"]
26
33
  })]
27
34
  }), /* @__PURE__ */ i("div", {
28
35
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
29
- children: p.map((e) => /* @__PURE__ */ a(c, { children: [/* @__PURE__ */ i(u, { children: /* @__PURE__ */ a("div", {
30
- className: "flex items-center justify-between",
31
- children: [/* @__PURE__ */ i(d, {
32
- className: "text-base",
33
- children: e.name
34
- }), /* @__PURE__ */ i(o, {
35
- variant: e.status === "active" ? "default" : "secondary",
36
- className: "text-[10px]",
37
- children: e.status
38
- })]
39
- }) }), /* @__PURE__ */ i(l, { children: /* @__PURE__ */ a("div", {
40
- className: "space-y-2",
41
- children: [
42
- /* @__PURE__ */ i(o, {
43
- variant: "outline",
36
+ children: h.length === 0 ? /* @__PURE__ */ i("div", {
37
+ className: "col-span-full",
38
+ children: /* @__PURE__ */ i(p, {
39
+ illustration: "empty-data",
40
+ title: "No vendors yet",
41
+ description: "Add a vendor to start tracking external relationships."
42
+ })
43
+ }) : h.map((e, n) => /* @__PURE__ */ a(d, {
44
+ treatment: n === 0 ? "glass" : "plain",
45
+ glow: n === 0,
46
+ children: [/* @__PURE__ */ i(l, { children: /* @__PURE__ */ a("div", {
47
+ className: "flex items-center justify-between",
48
+ children: [/* @__PURE__ */ i(u, {
49
+ className: "text-base",
50
+ children: e.name
51
+ }), /* @__PURE__ */ i(o, {
52
+ variant: e.status === "active" ? "default" : "secondary",
44
53
  className: "text-[10px]",
45
- children: e.category
46
- }),
47
- /* @__PURE__ */ a("div", {
48
- className: "grid grid-cols-2 gap-2 mt-2",
49
- children: [/* @__PURE__ */ a("div", { children: [/* @__PURE__ */ i("p", {
50
- className: "text-xs text-text-secondary",
51
- children: "Contact"
52
- }), /* @__PURE__ */ i("p", {
53
- className: "text-sm",
54
- children: e.contactPerson
55
- })] }), /* @__PURE__ */ a("div", { children: [/* @__PURE__ */ i("p", {
56
- className: "text-xs text-text-secondary",
57
- children: "Contract Value"
58
- }), /* @__PURE__ */ a("p", {
59
- className: "text-sm font-medium",
60
- children: ["$", e.contractValue.toLocaleString()]
61
- })] })]
62
- }),
63
- /* @__PURE__ */ a("div", {
64
- className: "flex items-center justify-between pt-2 border-t mt-2",
65
- children: [/* @__PURE__ */ a("div", {
66
- className: "flex items-center gap-1 text-xs text-text-secondary",
67
- children: [/* @__PURE__ */ i(t, { className: "h-3 w-3" }), e.email]
68
- }), /* @__PURE__ */ a("div", {
69
- className: "flex items-center gap-1",
70
- children: [/* @__PURE__ */ i(r, { className: "h-3 w-3 text-status-warning-text" }), /* @__PURE__ */ i("span", {
54
+ children: e.status
55
+ })]
56
+ }) }), /* @__PURE__ */ i(c, { children: /* @__PURE__ */ a("div", {
57
+ className: "space-y-2",
58
+ children: [
59
+ /* @__PURE__ */ i(o, {
60
+ variant: "outline",
61
+ className: "text-[10px]",
62
+ children: e.category
63
+ }),
64
+ /* @__PURE__ */ a("div", {
65
+ className: "grid grid-cols-2 gap-2 mt-2",
66
+ children: [/* @__PURE__ */ a("div", { children: [/* @__PURE__ */ i("p", {
67
+ className: "text-xs text-text-secondary",
68
+ children: "Contact"
69
+ }), /* @__PURE__ */ i("p", {
71
70
  className: "text-sm",
72
- children: e.rating
71
+ children: e.contactPerson
72
+ })] }), /* @__PURE__ */ a("div", { children: [/* @__PURE__ */ i("p", {
73
+ className: "text-xs text-text-secondary",
74
+ children: "Contract Value"
75
+ }), /* @__PURE__ */ a("p", {
76
+ className: "text-sm font-medium",
77
+ children: ["$", e.contractValue.toLocaleString()]
78
+ })] })]
79
+ }),
80
+ /* @__PURE__ */ a("div", {
81
+ className: "flex items-center justify-between pt-2 border-t mt-2",
82
+ children: [/* @__PURE__ */ a("div", {
83
+ className: "flex items-center gap-1 text-xs text-text-secondary",
84
+ children: [/* @__PURE__ */ i(t, { className: "h-3 w-3" }), e.email]
85
+ }), /* @__PURE__ */ a("div", {
86
+ className: "flex items-center gap-1",
87
+ children: [/* @__PURE__ */ i(r, { className: "h-3 w-3 text-status-warning-text" }), /* @__PURE__ */ i("span", {
88
+ className: "text-sm",
89
+ children: e.rating
90
+ })]
73
91
  })]
74
- })]
75
- })
76
- ]
77
- }) })] }, e.id))
92
+ })
93
+ ]
94
+ }) })]
95
+ }, e.id))
78
96
  })]
79
97
  });
80
98
  }
81
99
  //#endregion
82
- export { p as CompanyVendorManagementPagePage };
100
+ export { h as CompanyVendorManagementPagePage };
83
101
 
84
102
  //# sourceMappingURL=CompanyVendorManagementPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CompanyVendorManagementPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CompanyVendorManagementPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GradientText,\n} from '@burdenoff/fe-libs/ui';\nimport { DollarSign, Mail, Phone, Plus, Star } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function CompanyVendorManagementPagePage() {\n const { vendors } = useCrewFoundryStore();\n const totalContractValue = vendors.reduce((s, v) => s + v.contractValue, 0);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Vendor Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {vendors.length} vendors · ${(totalContractValue / 1000).toFixed(0)}K total contract\n value\n </p>\n </div>\n <Button size=\"sm\">\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Vendor\n </Button>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {vendors.map((vendor) => (\n <Card key={vendor.id}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{vendor.name}</CardTitle>\n <Badge\n variant={vendor.status === 'active' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {vendor.status}\n </Badge>\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-2\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {vendor.category}\n </Badge>\n <div className=\"grid grid-cols-2 gap-2 mt-2\">\n <div>\n <p className=\"text-xs text-text-secondary\">Contact</p>\n <p className=\"text-sm\">{vendor.contactPerson}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Contract Value</p>\n <p className=\"text-sm font-medium\">${vendor.contractValue.toLocaleString()}</p>\n </div>\n </div>\n <div className=\"flex items-center justify-between pt-2 border-t mt-2\">\n <div className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Mail className=\"h-3 w-3\" />\n {vendor.email}\n </div>\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" />\n <span className=\"text-sm\">{vendor.rating}</span>\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAYA,SAAgB,IAAkC;CAChD,IAAM,EAAE,eAAY,GAAqB,EACnC,IAAqB,EAAQ,QAAQ,GAAG,MAAM,IAAI,EAAE,eAAe,EAAE;AAE3E,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;IAAI,WAAU;cACZ,kBAAC,GAAD,EAAA,UAAc,qBAAgC,CAAA;IAC3C,CAAA,EACL,kBAAC,KAAD;IAAG,WAAU;cAAb;KACG,EAAQ;KAAO;MAAc,IAAqB,KAAM,QAAQ,EAAE;KAAC;KAElE;MACA,EAAA,CAAA,EACN,kBAAC,GAAD;IAAQ,MAAK;cAAb,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAAA,aAE1B;MACL;MACN,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAQ,KAAK,MACZ,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAW,WAAU;eAAa,EAAO;KAAiB,CAAA,EAC1D,kBAAC,GAAD;KACE,SAAS,EAAO,WAAW,WAAW,YAAY;KAClD,WAAU;eAET,EAAO;KACF,CAAA,CACJ;OACK,CAAA,EACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MAAO,SAAQ;MAAU,WAAU;gBAChC,EAAO;MACF,CAAA;KACR,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;OAAG,WAAU;iBAA8B;OAAW,CAAA,EACtD,kBAAC,KAAD;OAAG,WAAU;iBAAW,EAAO;OAAkB,CAAA,CAC7C,EAAA,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;OAAG,WAAU;iBAA8B;OAAkB,CAAA,EAC7D,kBAAC,KAAD;OAAG,WAAU;iBAAb,CAAmC,KAAE,EAAO,cAAc,gBAAgB,CAAK;SAC3E,EAAA,CAAA,CACF;;KACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAC3B,EAAO,MACJ;UACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAM,WAAU,oCAAqC,CAAA,EACrD,kBAAC,QAAD;QAAM,WAAU;kBAAW,EAAO;QAAc,CAAA,CAC5C;SACF;;KACF;OACM,CAAA,CACT,EAAA,EAvCI,EAAO,GAuCX,CACP;GACE,CAAA,CACF"}
1
+ {"version":3,"file":"CompanyVendorManagementPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CompanyVendorManagementPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { DollarSign, Mail, Phone, Plus, Star } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function CompanyVendorManagementPagePage() {\n const { vendors } = useCrewFoundryStore();\n const totalContractValue = vendors.reduce((s, v) => s + v.contractValue, 0);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Vendor Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {vendors.length} vendors · ${(totalContractValue / 1000).toFixed(0)}K total contract\n value\n </p>\n <PagePurpose className=\"mt-1\">Track the vendors and suppliers you depend on — contracts, contacts, and status — to manage external relationships in one place.</PagePurpose>\n </div>\n <Button size=\"sm\">\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Vendor\n </Button>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {vendors.length === 0 ? (\n <div className=\"col-span-full\">\n <IllustratedEmptyState illustration=\"empty-data\" title=\"No vendors yet\" description=\"Add a vendor to start tracking external relationships.\" />\n </div>\n ) : (\n vendors.map((vendor, _idx) => (\n <GlassCard key={vendor.id} treatment={_idx === 0 ? 'glass' : 'plain'} glow={_idx === 0}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{vendor.name}</CardTitle>\n <Badge\n variant={vendor.status === 'active' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {vendor.status}\n </Badge>\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-2\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {vendor.category}\n </Badge>\n <div className=\"grid grid-cols-2 gap-2 mt-2\">\n <div>\n <p className=\"text-xs text-text-secondary\">Contact</p>\n <p className=\"text-sm\">{vendor.contactPerson}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Contract Value</p>\n <p className=\"text-sm font-medium\">${vendor.contractValue.toLocaleString()}</p>\n </div>\n </div>\n <div className=\"flex items-center justify-between pt-2 border-t mt-2\">\n <div className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Mail className=\"h-3 w-3\" />\n {vendor.email}\n </div>\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" />\n <span className=\"text-sm\">{vendor.rating}</span>\n </div>\n </div>\n </div>\n </CardContent>\n </GlassCard>\n )))}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAcA,SAAgB,IAAkC;CAChD,IAAM,EAAE,eAAY,GAAqB,EACnC,IAAqB,EAAQ,QAAQ,GAAG,MAAM,IAAI,EAAE,eAAe,EAAE;AAE3E,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD,EAAA,UAAA;IACE,kBAAC,MAAD;KAAI,WAAU;eACZ,kBAAC,GAAD,EAAA,UAAc,qBAAgC,CAAA;KAC3C,CAAA;IACL,kBAAC,KAAD;KAAG,WAAU;eAAb;MACG,EAAQ;MAAO;OAAc,IAAqB,KAAM,QAAQ,EAAE;MAAC;MAElE;;IACJ,kBAAC,GAAD;KAAa,WAAU;eAAO;KAA8I,CAAA;IACxK,EAAA,CAAA,EACN,kBAAC,GAAD;IAAQ,MAAK;cAAb,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAAA,aAE1B;MACL;MACN,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAQ,WAAW,IAClB,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KAAuB,cAAa;KAAa,OAAM;KAAiB,aAAY;KAA2D,CAAA;IAC3I,CAAA,GAEN,EAAQ,KAAK,GAAQ,MACrB,kBAAC,GAAD;IAA2B,WAAW,MAAS,IAAI,UAAU;IAAS,MAAM,MAAS;cAArF,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAW,WAAU;gBAAa,EAAO;MAAiB,CAAA,EAC1D,kBAAC,GAAD;MACE,SAAS,EAAO,WAAW,WAAW,YAAY;MAClD,WAAU;gBAET,EAAO;MACF,CAAA,CACJ;QACK,CAAA,EACb,kBAAC,GAAD,EAAA,UACE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD;OAAO,SAAQ;OAAU,WAAU;iBAChC,EAAO;OACF,CAAA;MACR,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAAW,CAAA,EACtD,kBAAC,KAAD;QAAG,WAAU;kBAAW,EAAO;QAAkB,CAAA,CAC7C,EAAA,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA8B;QAAkB,CAAA,EAC7D,kBAAC,KAAD;QAAG,WAAU;kBAAb,CAAmC,KAAE,EAAO,cAAc,gBAAgB,CAAK;UAC3E,EAAA,CAAA,CACF;;MACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAC3B,EAAO,MACJ;WACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAM,WAAU,oCAAqC,CAAA,EACrD,kBAAC,QAAD;SAAM,WAAU;mBAAW,EAAO;SAAc,CAAA,CAC5C;UACF;;MACF;QACM,CAAA,CACJ;MAvCI,EAAO,GAuCX,CACZ;GACE,CAAA,CACF"}
@@ -2,11 +2,11 @@ import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
2
  import { useMemo as t } from "react";
3
3
  import { BarChart3 as n, DollarSign as r, Target as i, TrendingDown as a, TrendingUp as o, Users as s } from "lucide-react";
4
4
  import { jsx as c, jsxs as l } from "react/jsx-runtime";
5
- import { Badge as u, Card as d, CardContent as f, CardDescription as p, CardHeader as m, CardTitle as h, GlassCard as g, GradientText as _ } from "@burdenoff/fe-libs/ui";
5
+ import { Badge as u, Card as d, CardContent as f, CardDescription as p, CardHeader as m, CardTitle as h, GlassCard as g, GradientText as _, PagePurpose as v } from "@burdenoff/fe-libs/ui";
6
6
  //#region src/crewfoundry/pages/DashboardAnalyticsPagePage.tsx
7
- function v() {
8
- let { employees: v, departments: y, jobPostings: b, payrollRecords: x, projects: S } = e(), C = t(() => {
9
- let e = [...v].sort((e, t) => e.startDate.localeCompare(t.startDate));
7
+ function y() {
8
+ let { employees: y, departments: b, jobPostings: x, payrollRecords: S, projects: C } = e(), w = t(() => {
9
+ let e = [...y].sort((e, t) => e.startDate.localeCompare(t.startDate));
10
10
  return e.slice(-6).map((t, n) => {
11
11
  let r = new Date(t.startDate).toLocaleString("en-US", { month: "short" });
12
12
  return {
@@ -16,26 +16,26 @@ function v() {
16
16
  headcount: Math.max(1, e.length - (5 - n))
17
17
  };
18
18
  });
19
- }, [v]), w = Math.max(1, ...C.map((e) => e.headcount)), T = x.reduce((e, t) => e + t.netPay, 0), E = Math.round(v.reduce((e, t) => e + t.salary, 0) / Math.max(v.length, 1)), D = b.filter((e) => e.status === "active").length, O = v.reduce((e, t) => {
19
+ }, [y]), T = Math.max(1, ...w.map((e) => e.headcount)), E = S.reduce((e, t) => e + t.netPay, 0), D = Math.round(y.reduce((e, t) => e + t.salary, 0) / Math.max(y.length, 1)), O = x.filter((e) => e.status === "active").length, k = y.reduce((e, t) => {
20
20
  let n = t.type.replace("_", " ");
21
21
  return e[n] = (e[n] || 0) + 1, e;
22
- }, {}), k = t(() => {
22
+ }, {}), A = t(() => {
23
23
  let e = [
24
24
  {
25
25
  category: "Payroll",
26
- amount: T
26
+ amount: E
27
27
  },
28
28
  {
29
29
  category: "Recruitment",
30
- amount: b.reduce((e, t) => e + t.applicants * 120, 0)
30
+ amount: x.reduce((e, t) => e + t.applicants * 120, 0)
31
31
  },
32
32
  {
33
33
  category: "Project Delivery",
34
- amount: S.reduce((e, t) => e + t.spent, 0)
34
+ amount: C.reduce((e, t) => e + t.spent, 0)
35
35
  },
36
36
  {
37
37
  category: "Department Ops",
38
- amount: y.reduce((e, t) => e + t.budget * .03, 0)
38
+ amount: b.reduce((e, t) => e + t.budget * .03, 0)
39
39
  }
40
40
  ], t = e.reduce((e, t) => e + t.amount, 0) || 1;
41
41
  return e.map((e) => ({
@@ -43,26 +43,34 @@ function v() {
43
43
  percentage: Math.round(e.amount / t * 100)
44
44
  }));
45
45
  }, [
46
- y,
47
46
  b,
48
- S,
49
- T
47
+ x,
48
+ C,
49
+ E
50
50
  ]);
51
51
  return /* @__PURE__ */ l("div", {
52
52
  className: "space-y-6 p-6",
53
53
  children: [
54
- /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("h1", {
55
- className: "text-2xl font-semibold",
56
- children: /* @__PURE__ */ c(_, { children: "Dashboard Analytics" })
57
- }), /* @__PURE__ */ c("p", {
58
- className: "text-sm text-text-secondary",
59
- children: "Workforce analytics and operational insights"
60
- })] }),
54
+ /* @__PURE__ */ l("div", { children: [
55
+ /* @__PURE__ */ c("h1", {
56
+ className: "text-2xl font-semibold",
57
+ children: /* @__PURE__ */ c(_, { children: "Dashboard Analytics" })
58
+ }),
59
+ /* @__PURE__ */ c("p", {
60
+ className: "text-sm text-text-secondary",
61
+ children: "Workforce analytics and operational insights"
62
+ }),
63
+ /* @__PURE__ */ c(v, {
64
+ className: "mt-1",
65
+ children: "A consolidated analytics view across your organization — use it to monitor the metrics that matter most without digging through separate reports."
66
+ })
67
+ ] }),
61
68
  /* @__PURE__ */ l("div", {
62
69
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
63
70
  children: [
64
71
  /* @__PURE__ */ l(g, {
65
- treatment: "metric",
72
+ treatment: "glass",
73
+ glow: !0,
66
74
  className: "border-border-seam",
67
75
  children: [/* @__PURE__ */ l(m, {
68
76
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
@@ -72,7 +80,7 @@ function v() {
72
80
  }), /* @__PURE__ */ c(s, { className: "h-4 w-4 text-text-secondary" })]
73
81
  }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
74
82
  className: "text-2xl font-bold tabular-nums",
75
- children: v.length
83
+ children: y.length
76
84
  }), /* @__PURE__ */ l("div", {
77
85
  className: "flex items-center text-xs text-status-success-text",
78
86
  children: [/* @__PURE__ */ c(o, { className: "mr-1 h-3 w-3" }), "Live workforce count"]
@@ -89,7 +97,7 @@ function v() {
89
97
  }), /* @__PURE__ */ c(r, { className: "h-4 w-4 text-text-secondary" })]
90
98
  }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ l("div", {
91
99
  className: "text-2xl font-bold tabular-nums",
92
- children: ["$", E.toLocaleString()]
100
+ children: ["$", D.toLocaleString()]
93
101
  }), /* @__PURE__ */ l("div", {
94
102
  className: "flex items-center text-xs text-status-success-text",
95
103
  children: [/* @__PURE__ */ c(o, { className: "mr-1 h-3 w-3" }), "Updated from employee records"]
@@ -106,7 +114,7 @@ function v() {
106
114
  }), /* @__PURE__ */ c(a, { className: "h-4 w-4 text-text-secondary" })]
107
115
  }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ l("div", {
108
116
  className: "text-2xl font-bold tabular-nums",
109
- children: [Math.round(v.filter((e) => e.status === "terminated").length / Math.max(v.length, 1) * 100), "%"]
117
+ children: [Math.round(y.filter((e) => e.status === "terminated").length / Math.max(y.length, 1) * 100), "%"]
110
118
  }), /* @__PURE__ */ l("div", {
111
119
  className: "flex items-center text-xs text-status-success-text",
112
120
  children: [/* @__PURE__ */ c(a, { className: "mr-1 h-3 w-3" }), "Calculated from status mix"]
@@ -123,7 +131,7 @@ function v() {
123
131
  }), /* @__PURE__ */ c(i, { className: "h-4 w-4 text-text-secondary" })]
124
132
  }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
125
133
  className: "text-2xl font-bold tabular-nums",
126
- children: D
134
+ children: O
127
135
  }), /* @__PURE__ */ c("p", {
128
136
  className: "text-xs text-text-secondary",
129
137
  children: "Based on active job postings"
@@ -137,7 +145,7 @@ function v() {
137
145
  className: "col-span-4",
138
146
  children: [/* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c(h, { children: "Headcount Trend" }), /* @__PURE__ */ c(p, { children: "Monthly headcount over recent months" })] }), /* @__PURE__ */ c(f, {
139
147
  className: "space-y-3",
140
- children: C.map((e, t) => /* @__PURE__ */ l("div", {
148
+ children: w.map((e, t) => /* @__PURE__ */ l("div", {
141
149
  className: "flex items-center gap-3",
142
150
  children: [
143
151
  /* @__PURE__ */ c("span", {
@@ -148,7 +156,7 @@ function v() {
148
156
  className: "h-4 flex-1 overflow-hidden rounded bg-bg-sunken",
149
157
  children: /* @__PURE__ */ c("div", {
150
158
  className: "h-4 rounded bg-action-primary-bg",
151
- style: { width: `${Math.round(e.headcount / w * 100)}%` }
159
+ style: { width: `${Math.round(e.headcount / T * 100)}%` }
152
160
  })
153
161
  }),
154
162
  /* @__PURE__ */ c("span", {
@@ -174,7 +182,7 @@ function v() {
174
182
  className: "col-span-3",
175
183
  children: [/* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c(h, { children: "Employee Types" }), /* @__PURE__ */ c(p, { children: "Distribution by employment type" })] }), /* @__PURE__ */ c(f, {
176
184
  className: "space-y-4",
177
- children: Object.entries(O).sort(([, e], [, t]) => t - e).map(([e, t]) => /* @__PURE__ */ l("div", {
185
+ children: Object.entries(k).sort(([, e], [, t]) => t - e).map(([e, t]) => /* @__PURE__ */ l("div", {
178
186
  className: "flex items-center justify-between",
179
187
  children: [/* @__PURE__ */ l("div", {
180
188
  className: "flex items-center gap-2",
@@ -191,7 +199,7 @@ function v() {
191
199
  className: "text-xs text-text-secondary",
192
200
  children: [
193
201
  "(",
194
- Math.round(t / Math.max(v.length, 1) * 100),
202
+ Math.round(t / Math.max(y.length, 1) * 100),
195
203
  "%)"
196
204
  ]
197
205
  })]
@@ -202,7 +210,7 @@ function v() {
202
210
  }),
203
211
  /* @__PURE__ */ l(d, { children: [/* @__PURE__ */ l(m, { children: [/* @__PURE__ */ c(h, { children: "Workforce Cost Breakdown" }), /* @__PURE__ */ c(p, { children: "Operational costs by category" })] }), /* @__PURE__ */ l(f, { children: [/* @__PURE__ */ c("div", {
204
212
  className: "space-y-3",
205
- children: k.map((e) => /* @__PURE__ */ l("div", {
213
+ children: A.map((e) => /* @__PURE__ */ l("div", {
206
214
  className: "flex items-center gap-4",
207
215
  children: [
208
216
  /* @__PURE__ */ c("span", {
@@ -239,7 +247,7 @@ function v() {
239
247
  className: "font-bold",
240
248
  children: [
241
249
  "$",
242
- (k.reduce((e, t) => e + t.amount, 0) / 1e3).toFixed(0),
250
+ (A.reduce((e, t) => e + t.amount, 0) / 1e3).toFixed(0),
243
251
  "K"
244
252
  ]
245
253
  })]
@@ -262,7 +270,7 @@ function v() {
262
270
  children: "Status"
263
271
  })
264
272
  ]
265
- }), y.map((e) => /* @__PURE__ */ l("div", {
273
+ }), b.map((e) => /* @__PURE__ */ l("div", {
266
274
  className: "grid grid-cols-5 gap-2 border-b py-2 text-sm last:border-0",
267
275
  children: [
268
276
  /* @__PURE__ */ c("span", {
@@ -298,6 +306,6 @@ function v() {
298
306
  });
299
307
  }
300
308
  //#endregion
301
- export { v as DashboardAnalyticsPagePage };
309
+ export { y as DashboardAnalyticsPagePage };
302
310
 
303
311
  //# sourceMappingURL=DashboardAnalyticsPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/DashboardAnalyticsPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { BarChart3, DollarSign, Target, TrendingDown, TrendingUp, Users } from 'lucide-react';\nimport {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n} from '@burdenoff/fe-libs/ui';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype MonthlyTrend = {\n month: string;\n hires: number;\n attrition: number;\n headcount: number;\n};\n\ntype CostItem = {\n category: string;\n amount: number;\n percentage: number;\n};\n\nexport function DashboardAnalyticsPagePage() {\n const { employees, departments, jobPostings, payrollRecords, projects } = useCrewFoundryStore();\n\n const monthlyTrends = useMemo<MonthlyTrend[]>(() => {\n const sorted = [...employees].sort((a, b) => a.startDate.localeCompare(b.startDate));\n return sorted.slice(-6).map((employee, index) => {\n const month = new Date(employee.startDate).toLocaleString('en-US', { month: 'short' });\n const hires = sorted.filter(\n (item) =>\n new Date(item.startDate).toLocaleString('en-US', { month: 'short' }) === month &&\n item.status === 'active'\n ).length;\n const attrition = sorted.filter(\n (item) =>\n new Date(item.startDate).toLocaleString('en-US', { month: 'short' }) === month &&\n item.status === 'terminated'\n ).length;\n return {\n month,\n hires,\n attrition,\n headcount: Math.max(1, sorted.length - (5 - index)),\n };\n });\n }, [employees]);\n\n const maxTrend = Math.max(1, ...monthlyTrends.map((trend) => trend.headcount));\n\n const totalPayroll = payrollRecords.reduce((sum, record) => sum + record.netPay, 0);\n const avgSalary = Math.round(\n employees.reduce((sum, employee) => sum + employee.salary, 0) / Math.max(employees.length, 1)\n );\n const activePostings = jobPostings.filter((posting) => posting.status === 'active').length;\n\n const typeDistribution = employees.reduce<Record<string, number>>((acc, employee) => {\n const key = employee.type.replace('_', ' ');\n acc[key] = (acc[key] || 0) + 1;\n return acc;\n }, {});\n\n const costBreakdown = useMemo<CostItem[]>(() => {\n const costs: Array<{ category: string; amount: number }> = [\n { category: 'Payroll', amount: totalPayroll },\n {\n category: 'Recruitment',\n amount: jobPostings.reduce((sum, posting) => sum + posting.applicants * 120, 0),\n },\n {\n category: 'Project Delivery',\n amount: projects.reduce((sum, project) => sum + project.spent, 0),\n },\n {\n category: 'Department Ops',\n amount: departments.reduce((sum, department) => sum + department.budget * 0.03, 0),\n },\n ];\n const total = costs.reduce((sum, item) => sum + item.amount, 0) || 1;\n return costs.map((item) => ({\n ...item,\n percentage: Math.round((item.amount / total) * 100),\n }));\n }, [departments, jobPostings, projects, totalPayroll]);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Dashboard Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Workforce analytics and operational insights</p>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\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\">Total Headcount</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{employees.length}</div>\n <div className=\"flex items-center text-xs text-status-success-text\">\n <TrendingUp className=\"mr-1 h-3 w-3\" />\n Live workforce count\n </div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Avg Salary</CardTitle>\n <DollarSign className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${avgSalary.toLocaleString()}</div>\n <div className=\"flex items-center text-xs text-status-success-text\">\n <TrendingUp className=\"mr-1 h-3 w-3\" />\n Updated from employee records\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\">Attrition Rate</CardTitle>\n <TrendingDown className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {Math.round(\n (employees.filter((employee) => employee.status === 'terminated').length /\n Math.max(employees.length, 1)) *\n 100\n )}\n %\n </div>\n <div className=\"flex items-center text-xs text-status-success-text\">\n <TrendingDown className=\"mr-1 h-3 w-3\" />\n Calculated from status mix\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\">Open Roles</CardTitle>\n <Target className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activePostings}</div>\n <p className=\"text-xs text-text-secondary\">Based on active job postings</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-7\">\n <Card className=\"col-span-4\">\n <CardHeader>\n <CardTitle>Headcount Trend</CardTitle>\n <CardDescription>Monthly headcount over recent months</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {monthlyTrends.map((trend, index) => (\n <div key={`${trend.month}-${index}`} className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-text-secondary\">{trend.month}</span>\n <div className=\"h-4 flex-1 overflow-hidden rounded bg-bg-sunken\">\n <div\n className=\"h-4 rounded bg-action-primary-bg\"\n style={{ width: `${Math.round((trend.headcount / maxTrend) * 100)}%` }}\n />\n </div>\n <span className=\"w-10 text-right text-sm font-medium\">{trend.headcount}</span>\n <div className=\"flex w-24 gap-1\">\n <Badge variant=\"default\" className=\"text-[10px]\">\n +{trend.hires}\n </Badge>\n <Badge variant=\"destructive\" className=\"text-[10px]\">\n -{trend.attrition}\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card className=\"col-span-3\">\n <CardHeader>\n <CardTitle>Employee Types</CardTitle>\n <CardDescription>Distribution by employment type</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {Object.entries(typeDistribution)\n .sort(([, a], [, b]) => b - a)\n .map(([type, count]) => (\n <div key={type} className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4 text-text-secondary\" />\n <span className=\"text-sm capitalize\">{type}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium\">{count}</span>\n <span className=\"text-xs text-text-secondary\">\n ({Math.round((count / Math.max(employees.length, 1)) * 100)}%)\n </span>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Workforce Cost Breakdown</CardTitle>\n <CardDescription>Operational costs by category</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {costBreakdown.map((item) => (\n <div key={item.category} className=\"flex items-center gap-4\">\n <span className=\"w-48 text-sm text-text-secondary\">{item.category}</span>\n <div className=\"h-3 flex-1 overflow-hidden rounded bg-bg-sunken\">\n <div\n className=\"h-3 rounded bg-action-primary-bg/80\"\n style={{ width: `${item.percentage}%` }}\n />\n </div>\n <span className=\"w-24 text-right text-sm font-medium\">\n ${(item.amount / 1000).toFixed(0)}K\n </span>\n <span className=\"w-10 text-right text-xs text-text-secondary\">\n {item.percentage}%\n </span>\n </div>\n ))}\n </div>\n <div className=\"mt-4 flex justify-between border-t pt-4 text-sm\">\n <span className=\"font-medium\">Total Monthly Cost</span>\n <span className=\"font-bold\">\n ${(costBreakdown.reduce((sum, item) => sum + item.amount, 0) / 1000).toFixed(0)}K\n </span>\n </div>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Department Overview</CardTitle>\n <CardDescription>Key metrics by department</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"mb-2 grid grid-cols-5 gap-2 border-b pb-2 text-xs font-medium text-text-secondary\">\n <span>Department</span>\n <span>Head</span>\n <span className=\"text-right\">Employees</span>\n <span className=\"text-right\">Budget</span>\n <span className=\"text-right\">Status</span>\n </div>\n {departments.map((department) => (\n <div\n key={department.id}\n className=\"grid grid-cols-5 gap-2 border-b py-2 text-sm last:border-0\"\n >\n <span className=\"font-medium\">{department.name}</span>\n <span className=\"text-text-secondary\">{department.headName}</span>\n <span className=\"text-right\">{department.employeeCount}</span>\n <span className=\"text-right\">${(department.budget / 1000000).toFixed(1)}M</span>\n <div className=\"text-right\">\n <Badge variant={department.status === 'active' ? 'default' : 'secondary'}>\n {department.status}\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":"DashboardAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/DashboardAnalyticsPagePage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { BarChart3, DollarSign, Target, TrendingDown, TrendingUp, Users } from 'lucide-react';\nimport {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\ntype MonthlyTrend = {\n month: string;\n hires: number;\n attrition: number;\n headcount: number;\n};\n\ntype CostItem = {\n category: string;\n amount: number;\n percentage: number;\n};\n\nexport function DashboardAnalyticsPagePage() {\n const { employees, departments, jobPostings, payrollRecords, projects } = useCrewFoundryStore();\n\n const monthlyTrends = useMemo<MonthlyTrend[]>(() => {\n const sorted = [...employees].sort((a, b) => a.startDate.localeCompare(b.startDate));\n return sorted.slice(-6).map((employee, index) => {\n const month = new Date(employee.startDate).toLocaleString('en-US', { month: 'short' });\n const hires = sorted.filter(\n (item) =>\n new Date(item.startDate).toLocaleString('en-US', { month: 'short' }) === month &&\n item.status === 'active'\n ).length;\n const attrition = sorted.filter(\n (item) =>\n new Date(item.startDate).toLocaleString('en-US', { month: 'short' }) === month &&\n item.status === 'terminated'\n ).length;\n return {\n month,\n hires,\n attrition,\n headcount: Math.max(1, sorted.length - (5 - index)),\n };\n });\n }, [employees]);\n\n const maxTrend = Math.max(1, ...monthlyTrends.map((trend) => trend.headcount));\n\n const totalPayroll = payrollRecords.reduce((sum, record) => sum + record.netPay, 0);\n const avgSalary = Math.round(\n employees.reduce((sum, employee) => sum + employee.salary, 0) / Math.max(employees.length, 1)\n );\n const activePostings = jobPostings.filter((posting) => posting.status === 'active').length;\n\n const typeDistribution = employees.reduce<Record<string, number>>((acc, employee) => {\n const key = employee.type.replace('_', ' ');\n acc[key] = (acc[key] || 0) + 1;\n return acc;\n }, {});\n\n const costBreakdown = useMemo<CostItem[]>(() => {\n const costs: Array<{ category: string; amount: number }> = [\n { category: 'Payroll', amount: totalPayroll },\n {\n category: 'Recruitment',\n amount: jobPostings.reduce((sum, posting) => sum + posting.applicants * 120, 0),\n },\n {\n category: 'Project Delivery',\n amount: projects.reduce((sum, project) => sum + project.spent, 0),\n },\n {\n category: 'Department Ops',\n amount: departments.reduce((sum, department) => sum + department.budget * 0.03, 0),\n },\n ];\n const total = costs.reduce((sum, item) => sum + item.amount, 0) || 1;\n return costs.map((item) => ({\n ...item,\n percentage: Math.round((item.amount / total) * 100),\n }));\n }, [departments, jobPostings, projects, totalPayroll]);\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Dashboard Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Workforce analytics and operational insights</p>\n <PagePurpose className=\"mt-1\">A consolidated analytics view across your organization — use it to monitor the metrics that matter most without digging through separate reports.</PagePurpose>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Total Headcount</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{employees.length}</div>\n <div className=\"flex items-center text-xs text-status-success-text\">\n <TrendingUp className=\"mr-1 h-3 w-3\" />\n Live workforce count\n </div>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Avg Salary</CardTitle>\n <DollarSign className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${avgSalary.toLocaleString()}</div>\n <div className=\"flex items-center text-xs text-status-success-text\">\n <TrendingUp className=\"mr-1 h-3 w-3\" />\n Updated from employee records\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\">Attrition Rate</CardTitle>\n <TrendingDown className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {Math.round(\n (employees.filter((employee) => employee.status === 'terminated').length /\n Math.max(employees.length, 1)) *\n 100\n )}\n %\n </div>\n <div className=\"flex items-center text-xs text-status-success-text\">\n <TrendingDown className=\"mr-1 h-3 w-3\" />\n Calculated from status mix\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\">Open Roles</CardTitle>\n <Target className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activePostings}</div>\n <p className=\"text-xs text-text-secondary\">Based on active job postings</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-7\">\n <Card className=\"col-span-4\">\n <CardHeader>\n <CardTitle>Headcount Trend</CardTitle>\n <CardDescription>Monthly headcount over recent months</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {monthlyTrends.map((trend, index) => (\n <div key={`${trend.month}-${index}`} className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-text-secondary\">{trend.month}</span>\n <div className=\"h-4 flex-1 overflow-hidden rounded bg-bg-sunken\">\n <div\n className=\"h-4 rounded bg-action-primary-bg\"\n style={{ width: `${Math.round((trend.headcount / maxTrend) * 100)}%` }}\n />\n </div>\n <span className=\"w-10 text-right text-sm font-medium\">{trend.headcount}</span>\n <div className=\"flex w-24 gap-1\">\n <Badge variant=\"default\" className=\"text-[10px]\">\n +{trend.hires}\n </Badge>\n <Badge variant=\"destructive\" className=\"text-[10px]\">\n -{trend.attrition}\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card className=\"col-span-3\">\n <CardHeader>\n <CardTitle>Employee Types</CardTitle>\n <CardDescription>Distribution by employment type</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {Object.entries(typeDistribution)\n .sort(([, a], [, b]) => b - a)\n .map(([type, count]) => (\n <div key={type} className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <BarChart3 className=\"h-4 w-4 text-text-secondary\" />\n <span className=\"text-sm capitalize\">{type}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium\">{count}</span>\n <span className=\"text-xs text-text-secondary\">\n ({Math.round((count / Math.max(employees.length, 1)) * 100)}%)\n </span>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Workforce Cost Breakdown</CardTitle>\n <CardDescription>Operational costs by category</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-3\">\n {costBreakdown.map((item) => (\n <div key={item.category} className=\"flex items-center gap-4\">\n <span className=\"w-48 text-sm text-text-secondary\">{item.category}</span>\n <div className=\"h-3 flex-1 overflow-hidden rounded bg-bg-sunken\">\n <div\n className=\"h-3 rounded bg-action-primary-bg/80\"\n style={{ width: `${item.percentage}%` }}\n />\n </div>\n <span className=\"w-24 text-right text-sm font-medium\">\n ${(item.amount / 1000).toFixed(0)}K\n </span>\n <span className=\"w-10 text-right text-xs text-text-secondary\">\n {item.percentage}%\n </span>\n </div>\n ))}\n </div>\n <div className=\"mt-4 flex justify-between border-t pt-4 text-sm\">\n <span className=\"font-medium\">Total Monthly Cost</span>\n <span className=\"font-bold\">\n ${(costBreakdown.reduce((sum, item) => sum + item.amount, 0) / 1000).toFixed(0)}K\n </span>\n </div>\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Department Overview</CardTitle>\n <CardDescription>Key metrics by department</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"mb-2 grid grid-cols-5 gap-2 border-b pb-2 text-xs font-medium text-text-secondary\">\n <span>Department</span>\n <span>Head</span>\n <span className=\"text-right\">Employees</span>\n <span className=\"text-right\">Budget</span>\n <span className=\"text-right\">Status</span>\n </div>\n {departments.map((department) => (\n <div\n key={department.id}\n className=\"grid grid-cols-5 gap-2 border-b py-2 text-sm last:border-0\"\n >\n <span className=\"font-medium\">{department.name}</span>\n <span className=\"text-text-secondary\">{department.headName}</span>\n <span className=\"text-right\">{department.employeeCount}</span>\n <span className=\"text-right\">${(department.budget / 1000000).toFixed(1)}M</span>\n <div className=\"text-right\">\n <Badge variant={department.status === 'active' ? 'default' : 'secondary'}>\n {department.status}\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}