@burdenoff/microfe-crewfoundry 2026.703.1 → 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 (129) 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/dist/crewfoundry/store/crewfoundryStore.js +35 -3
  128. package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
  129. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardEnhancedDashboardPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/DashboardEnhancedDashboardPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n EmphasisPanel,\n GradientText,\n NextSteps,\n PagePurpose,\n Separator,\n} from '@burdenoff/fe-libs/ui';\nimport {\n AlertTriangle,\n ArrowUpRight,\n Award,\n Bell,\n Briefcase,\n CheckCircle,\n MapPin,\n Star,\n Users,\n Zap,\n} from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\nimport { useCrewFoundry } from '../providers/CrewFoundryProvider';\n\nexport function DashboardEnhancedDashboardPagePage() {\n const navigate = useNavigate();\n const { showToast } = useGlobalUi();\n const { currentUser } = useCrewFoundry();\n const {\n employees,\n jobPostings,\n candidates,\n interviews,\n leaveRequests,\n notifications,\n projects,\n announcements,\n updateLeaveRequest,\n } = useCrewFoundryStore();\n const [processingLeaveId, setProcessingLeaveId] = useState<string | null>(null);\n\n const approverName =\n currentUser?.name ||\n [currentUser?.firstName, currentUser?.lastName].filter(Boolean).join(' ') ||\n currentUser?.email ||\n 'Manager';\n\n const decideLeave = async (id: string, status: 'approved' | 'rejected') => {\n setProcessingLeaveId(id);\n try {\n await updateLeaveRequest(id, { status, approverName });\n showToast(status === 'approved' ? 'Leave approved' : 'Leave rejected', 'success');\n } catch (error) {\n showToast(\n error instanceof Error ? error.message : 'Unable to update leave request',\n 'error'\n );\n } finally {\n setProcessingLeaveId(null);\n }\n };\n\n const quickActions = useMemo(\n () => [\n {\n label: `Post New Job (${jobPostings.filter((job) => job.status === 'active').length} active)`,\n icon: Briefcase,\n color: 'text-status-info-text',\n to: '../../hiring/create-job-page',\n },\n {\n label: `Review Candidates (${candidates.filter((candidate) => candidate.status === 'new').length})`,\n icon: Users,\n color: 'text-action-primary-bg',\n to: '../../hiring/candidates-page',\n },\n {\n label: `Approve Leaves (${leaveRequests.filter((leave) => leave.status === 'pending').length})`,\n icon: CheckCircle,\n color: 'text-status-success-text',\n to: '../../hr/leave-management-page',\n },\n {\n label: `Run Payroll (${projects.filter((project) => project.status === 'active').length} projects)`,\n icon: Zap,\n color: 'text-status-warning-text',\n to: '../../hr/payroll-page',\n },\n ],\n [candidates, jobPostings, leaveRequests, projects]\n );\n\n const companyGoals = useMemo(\n () => [\n {\n goal: 'Reduce time-to-hire to 25 days',\n current: Math.max(\n 20,\n 40 - candidates.filter((candidate) => candidate.status === 'hired').length\n ),\n target: 25,\n unit: 'days',\n },\n {\n goal: 'Achieve 95% employee satisfaction',\n current: Math.round(\n (employees.reduce((sum, employee) => sum + employee.performanceScore, 0) /\n Math.max(employees.length, 1)) *\n 20\n ),\n target: 95,\n unit: '%',\n },\n {\n goal: 'Fill 30 open positions by Q2',\n current: candidates.filter((candidate) => candidate.status === 'hired').length,\n target: 30,\n unit: 'positions',\n },\n {\n goal: 'Complete 80% training compliance',\n current: Math.min(\n 100,\n 60 +\n Math.round(\n (employees.filter((employee) => employee.status === 'active').length /\n Math.max(employees.length, 1)) *\n 30\n )\n ),\n target: 80,\n unit: '%',\n },\n ],\n [candidates, employees]\n );\n\n const upcomingInterviews = interviews.filter((i) => i.status === 'scheduled');\n const pendingLeaves = leaveRequests.filter((l) => l.status === 'pending');\n const unreadNotifs = notifications.filter((n) => !n.read);\n const pinnedAnnouncements = announcements.filter((a) => a.isPinned);\n const topPerformers = [...employees]\n .sort((a, b) => b.performanceScore - a.performanceScore)\n .slice(0, 5);\n const recentHires = [...employees]\n .sort((a, b) => b.startDate.localeCompare(a.startDate))\n .slice(0, 5);\n\n const locationMap = employees.reduce<Record<string, number>>((acc, e) => {\n acc[e.location] = (acc[e.location] || 0) + 1;\n return acc;\n }, {});\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Enhanced Dashboard</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Complete workforce command center</p>\n <PagePurpose className=\"mt-1\">A richer, customizable command center for your workforce — see live metrics, activity, and trends tailored to how you run your organization.</PagePurpose>\n </div>\n <div className=\"flex items-center gap-3\">\n <div className=\"relative\">\n <Bell className=\"h-5 w-5 text-text-secondary\" />\n {unreadNotifs.length > 0 && (\n <span className=\"absolute -top-1 -right-1 h-4 w-4 rounded-full bg-status-error-text text-[10px] text-white flex items-center justify-center\">\n {unreadNotifs.length}\n </span>\n )}\n </div>\n <Button size=\"sm\" onClick={() => navigate('../../hr/leave-management-page')}>\n <Zap className=\"h-4 w-4 mr-1\" />\n Quick Actions\n </Button>\n </div>\n </div>\n\n <NextSteps\n storageKey=\"crewfoundry-enhanced-dashboard\"\n steps={[\n {\n id: 'hiring',\n label: 'Move hiring forward',\n description: 'Review open roles and applicants in your pipeline.',\n icon: <Briefcase className=\"h-4 w-4\" />,\n onClick: () => navigate('../../hiring/jobs-page'),\n },\n {\n id: 'people',\n label: 'Check on your people',\n description: 'See who is active, on leave, or needs attention.',\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => navigate('../../hr/employees-page'),\n },\n {\n id: 'analytics',\n label: 'Dig into analytics',\n description: 'Explore deeper workforce and hiring trends.',\n icon: <ArrowUpRight className=\"h-4 w-4\" />,\n onClick: () => navigate('../../analytics/analytics-page'),\n },\n ]}\n />\n\n <div className=\"grid gap-3 md:grid-cols-4\">\n {quickActions.map((action) => (\n <Card\n key={action.label}\n role=\"button\"\n tabIndex={0}\n aria-label={action.label}\n className=\"cursor-pointer hover:shadow-md transition-shadow\"\n onClick={() => navigate(action.to)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n navigate(action.to);\n }\n }}\n >\n <CardContent className=\"flex items-center gap-3 p-4\">\n <action.icon className={`h-5 w-5 ${action.color}`} />\n <span className=\"text-sm font-medium\">{action.label}</span>\n <ArrowUpRight className=\"h-4 w-4 ml-auto text-text-secondary\" />\n </CardContent>\n </Card>\n ))}\n </div>\n\n {pinnedAnnouncements.length > 0 && (\n <Card className=\"border-status-warning-text/30 bg-status-warning-bg/50\">\n <CardContent className=\"p-4\">\n {pinnedAnnouncements.map((ann) => (\n <div key={ann.id} className=\"flex items-start gap-3\">\n <AlertTriangle className=\"h-4 w-4 text-status-warning-text mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium\">{ann.title}</p>\n <p className=\"text-xs text-text-secondary mt-1\">{ann.content.slice(0, 120)}...</p>\n <p className=\"text-xs text-text-secondary mt-1\">\n — {ann.author}, {ann.authorRole}\n </p>\n </div>\n <Badge variant=\"outline\" className=\"ml-auto flex-shrink-0\">\n {ann.priority}\n </Badge>\n </div>\n ))}\n </CardContent>\n </Card>\n )}\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n <EmphasisPanel>\n <div className=\"text-base font-semibold\">Company Goals</div>\n <p className=\"mb-4 text-sm text-text-secondary\">Q1 2026 targets</p>\n <div className=\"space-y-4\">\n {companyGoals.map((g) => {\n const pct = Math.round((g.current / g.target) * 100);\n return (\n <div key={g.goal} className=\"space-y-1\">\n <div className=\"flex justify-between text-xs\">\n <span className=\"text-text-secondary\">{g.goal}</span>\n <span className=\"font-medium\">\n {g.current}/{g.target} {g.unit}\n </span>\n </div>\n <div className=\"h-2 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-2 rounded ${pct >= 90 ? 'bg-status-success-text' : pct >= 70 ? 'bg-status-warning-text' : 'bg-status-error-text'}`}\n style={{ width: `${Math.min(pct, 100)}%` }}\n />\n </div>\n </div>\n );\n })}\n </div>\n </EmphasisPanel>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Upcoming Interviews</CardTitle>\n <CardDescription>{upcomingInterviews.length} scheduled</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {upcomingInterviews.map((interview) => (\n <div key={interview.id} className=\"flex items-center gap-3 rounded border p-2\">\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">{interview.candidateName}</p>\n <p className=\"text-xs text-text-secondary\">{interview.position}</p>\n </div>\n <div className=\"text-right flex-shrink-0\">\n <p className=\"text-xs font-medium\">{interview.date}</p>\n <p className=\"text-xs text-text-secondary\">{interview.time}</p>\n </div>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {interview.type}\n </Badge>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Pending Actions</CardTitle>\n <CardDescription>Items requiring your attention</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {pendingLeaves.map((leave) => (\n <div key={leave.id} className=\"flex items-center justify-between rounded border p-2\">\n <div>\n <p className=\"text-sm font-medium\">{leave.employeeName}</p>\n <p className=\"text-xs text-text-secondary\">\n {leave.type} leave · {leave.days} days\n </p>\n </div>\n <div className=\"flex gap-1\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs\"\n disabled={processingLeaveId === leave.id}\n onClick={() => void decideLeave(leave.id, 'rejected')}\n >\n Deny\n </Button>\n <Button\n size=\"sm\"\n className=\"h-7 text-xs\"\n disabled={processingLeaveId === leave.id}\n onClick={() => void decideLeave(leave.id, 'approved')}\n >\n Approve\n </Button>\n </div>\n </div>\n ))}\n <Separator />\n <div className=\"text-xs text-text-secondary text-center\">\n {candidates.filter((c) => c.status === 'new').length} new applications to review\n </div>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Award className=\"h-4 w-4 text-status-warning-text\" />\n Top Performers\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {topPerformers.map((emp, idx) => (\n <div key={emp.id} className=\"flex items-center gap-3\">\n <span className=\"text-sm font-bold text-text-secondary w-5\">#{idx + 1}</span>\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium\">\n {emp.firstName} {emp.lastName}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {emp.position} · {emp.department}\n </p>\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 font-medium\">{emp.performanceScore}</span>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base flex items-center gap-2\">\n <MapPin className=\"h-4 w-4\" />\n Workforce Locations\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(locationMap)\n .sort(([, a], [, b]) => b - a)\n .map(([location, count]) => (\n <div key={location} className=\"flex items-center justify-between\">\n <span className=\"text-sm\">{location}</span>\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 / employees.length) * 100)}%)\n </span>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Recent Hires</CardTitle>\n <CardDescription>Newest team members</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-6 gap-2 text-xs font-medium text-text-secondary border-b pb-2 mb-2\">\n <span>Name</span>\n <span>Position</span>\n <span>Department</span>\n <span>Location</span>\n <span>Start Date</span>\n <span>Type</span>\n </div>\n {recentHires.map((emp) => (\n <div\n key={emp.id}\n className=\"grid grid-cols-6 gap-2 py-2 border-b last:border-0 text-sm\"\n >\n <span className=\"font-medium\">\n {emp.firstName} {emp.lastName}\n </span>\n <span className=\"text-text-secondary truncate\">{emp.position}</span>\n <span>{emp.department}</span>\n <span className=\"text-text-secondary truncate\">{emp.location}</span>\n <span>{emp.startDate}</span>\n <Badge variant=\"outline\" className=\"w-fit text-[10px]\">\n {emp.type.replace('_', ' ')}\n </Badge>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DashboardEnhancedDashboardPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/DashboardEnhancedDashboardPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n EmphasisPanel,\n GradientText,\n NextSteps,\n PagePurpose,\n ResponsiveTable,\n type ResponsiveTableColumn,\n Separator,\n} from '@burdenoff/fe-libs/ui';\nimport {\n AlertTriangle,\n ArrowUpRight,\n Award,\n Bell,\n Briefcase,\n CheckCircle,\n MapPin,\n Star,\n Users,\n Zap,\n} from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { useCrewFoundryStore, type Employee } from '../store/crewfoundryStore';\nimport { useCrewFoundry } from '../providers/CrewFoundryProvider';\n\nexport function DashboardEnhancedDashboardPagePage() {\n const navigate = useNavigate();\n const { showToast } = useGlobalUi();\n const { currentUser } = useCrewFoundry();\n const {\n employees,\n jobPostings,\n candidates,\n interviews,\n leaveRequests,\n notifications,\n projects,\n announcements,\n updateLeaveRequest,\n markAllNotificationsRead,\n } = useCrewFoundryStore();\n const [processingLeaveId, setProcessingLeaveId] = useState<string | null>(null);\n const [markingRead, setMarkingRead] = useState(false);\n\n const handleMarkAllRead = async () => {\n setMarkingRead(true);\n try {\n await markAllNotificationsRead();\n showToast('All notifications marked as read', 'success');\n } catch (error) {\n showToast(\n error instanceof Error ? error.message : 'Unable to update notifications',\n 'error'\n );\n } finally {\n setMarkingRead(false);\n }\n };\n\n const approverName =\n currentUser?.name ||\n [currentUser?.firstName, currentUser?.lastName].filter(Boolean).join(' ') ||\n currentUser?.email ||\n 'Manager';\n\n const decideLeave = async (id: string, status: 'approved' | 'rejected') => {\n setProcessingLeaveId(id);\n try {\n await updateLeaveRequest(id, { status, approverName });\n showToast(status === 'approved' ? 'Leave approved' : 'Leave rejected', 'success');\n } catch (error) {\n showToast(\n error instanceof Error ? error.message : 'Unable to update leave request',\n 'error'\n );\n } finally {\n setProcessingLeaveId(null);\n }\n };\n\n const quickActions = useMemo(\n () => [\n {\n label: `Post New Job (${jobPostings.filter((job) => job.status === 'active').length} active)`,\n icon: Briefcase,\n color: 'text-status-info-text',\n to: '../../hiring/create-job-page',\n },\n {\n label: `Review Candidates (${candidates.filter((candidate) => candidate.status === 'new').length})`,\n icon: Users,\n color: 'text-action-primary-bg',\n to: '../../hiring/candidates-page',\n },\n {\n label: `Approve Leaves (${leaveRequests.filter((leave) => leave.status === 'pending').length})`,\n icon: CheckCircle,\n color: 'text-status-success-text',\n to: '../../hr/leave-management-page',\n },\n {\n label: `Run Payroll (${projects.filter((project) => project.status === 'active').length} projects)`,\n icon: Zap,\n color: 'text-status-warning-text',\n to: '../../hr/payroll-page',\n },\n ],\n [candidates, jobPostings, leaveRequests, projects]\n );\n\n // Only goals whose current value is derived from real store data.\n const companyGoals = useMemo(() => {\n const hired = candidates.filter((candidate) => candidate.status === 'hired').length;\n const avgPerformance =\n employees.reduce((sum, employee) => sum + employee.performanceScore, 0) /\n Math.max(employees.length, 1);\n const activeShare = Math.round(\n (employees.filter((employee) => employee.status === 'active').length /\n Math.max(employees.length, 1)) *\n 100\n );\n return [\n {\n goal: 'Fill 30 open positions',\n current: hired,\n target: 30,\n unit: 'positions',\n },\n {\n goal: 'Reach 90% average performance',\n current: Math.round(avgPerformance * 20),\n target: 90,\n unit: '%',\n },\n {\n goal: 'Keep 95% of workforce active',\n current: activeShare,\n target: 95,\n unit: '%',\n },\n ];\n }, [candidates, employees]);\n\n const upcomingInterviews = interviews.filter((i) => i.status === 'scheduled');\n const pendingLeaves = leaveRequests.filter((l) => l.status === 'pending');\n const unreadNotifs = notifications.filter((n) => !n.read);\n const pinnedAnnouncements = announcements.filter((a) => a.isPinned);\n const topPerformers = [...employees]\n .sort((a, b) => b.performanceScore - a.performanceScore)\n .slice(0, 5);\n const recentHires = [...employees]\n .sort((a, b) => b.startDate.localeCompare(a.startDate))\n .slice(0, 5);\n\n const locationMap = employees.reduce<Record<string, number>>((acc, e) => {\n acc[e.location] = (acc[e.location] || 0) + 1;\n return acc;\n }, {});\n\n const recentHireColumns: ResponsiveTableColumn<Employee>[] = [\n {\n key: 'name',\n header: 'Name',\n priority: 'primary',\n cell: (emp) => (\n <span className=\"font-medium\">\n {emp.firstName} {emp.lastName}\n </span>\n ),\n },\n {\n key: 'position',\n header: 'Position',\n priority: 'secondary',\n cell: (emp) => <span className=\"text-text-secondary\">{emp.position}</span>,\n },\n {\n key: 'department',\n header: 'Department',\n priority: 'secondary',\n cell: (emp) => <span>{emp.department}</span>,\n },\n {\n key: 'location',\n header: 'Location',\n priority: 'hidden-on-mobile',\n cell: (emp) => <span className=\"text-text-secondary\">{emp.location}</span>,\n },\n {\n key: 'startDate',\n header: 'Start Date',\n priority: 'secondary',\n cell: (emp) => <span>{emp.startDate}</span>,\n },\n {\n key: 'type',\n header: 'Type',\n priority: 'primary',\n cell: (emp) => (\n <Badge variant=\"outline\" className=\"w-fit text-[10px]\">\n {emp.type.replace('_', ' ')}\n </Badge>\n ),\n },\n ];\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Enhanced Dashboard</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Complete workforce command center</p>\n <PagePurpose className=\"mt-1\">A richer, customizable command center for your workforce — see live metrics, activity, and trends tailored to how you run your organization.</PagePurpose>\n </div>\n <div className=\"flex items-center gap-3\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"relative\"\n disabled={unreadNotifs.length === 0 || markingRead}\n aria-label={\n unreadNotifs.length > 0\n ? `${unreadNotifs.length} unread notifications, mark all as read`\n : 'No unread notifications'\n }\n title={\n unreadNotifs.length > 0\n ? 'Mark all notifications as read'\n : 'No unread notifications'\n }\n onClick={() => void handleMarkAllRead()}\n >\n <Bell className=\"h-5 w-5 text-text-secondary\" />\n {unreadNotifs.length > 0 && (\n <span className=\"absolute -top-1 -right-1 h-4 w-4 rounded-full bg-status-error-text text-[10px] text-text-inverse flex items-center justify-center\">\n {unreadNotifs.length}\n </span>\n )}\n </Button>\n <Button size=\"sm\" onClick={() => navigate('../../hr/leave-management-page')}>\n <Zap className=\"h-4 w-4 mr-1\" />\n Quick Actions\n </Button>\n </div>\n </div>\n\n <NextSteps\n storageKey=\"crewfoundry-enhanced-dashboard\"\n steps={[\n {\n id: 'hiring',\n label: 'Move hiring forward',\n description: 'Review open roles and applicants in your pipeline.',\n icon: <Briefcase className=\"h-4 w-4\" />,\n onClick: () => navigate('../../hiring/jobs-page'),\n },\n {\n id: 'people',\n label: 'Check on your people',\n description: 'See who is active, on leave, or needs attention.',\n icon: <Users className=\"h-4 w-4\" />,\n onClick: () => navigate('../../hr/employees-page'),\n },\n {\n id: 'analytics',\n label: 'Dig into analytics',\n description: 'Explore deeper workforce and hiring trends.',\n icon: <ArrowUpRight className=\"h-4 w-4\" />,\n onClick: () => navigate('../../analytics/analytics-page'),\n },\n ]}\n />\n\n <div className=\"grid gap-3 md:grid-cols-4\">\n {quickActions.map((action) => (\n <Card\n key={action.label}\n role=\"button\"\n tabIndex={0}\n aria-label={action.label}\n className=\"cursor-pointer hover:shadow-md transition-shadow\"\n onClick={() => navigate(action.to)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n navigate(action.to);\n }\n }}\n >\n <CardContent className=\"flex items-center gap-3 p-4\">\n <action.icon className={`h-5 w-5 ${action.color}`} />\n <span className=\"text-sm font-medium\">{action.label}</span>\n <ArrowUpRight className=\"h-4 w-4 ml-auto text-text-secondary\" />\n </CardContent>\n </Card>\n ))}\n </div>\n\n {pinnedAnnouncements.length > 0 && (\n <Card className=\"border-status-warning-text/30 bg-status-warning-bg/50\">\n <CardContent className=\"p-4\">\n {pinnedAnnouncements.map((ann) => (\n <div key={ann.id} className=\"flex items-start gap-3\">\n <AlertTriangle className=\"h-4 w-4 text-status-warning-text mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium\">{ann.title}</p>\n <p className=\"text-xs text-text-secondary mt-1\">{ann.content.slice(0, 120)}...</p>\n <p className=\"text-xs text-text-secondary mt-1\">\n — {ann.author}, {ann.authorRole}\n </p>\n </div>\n <Badge variant=\"outline\" className=\"ml-auto flex-shrink-0\">\n {ann.priority}\n </Badge>\n </div>\n ))}\n </CardContent>\n </Card>\n )}\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n <EmphasisPanel>\n <div className=\"text-base font-semibold\">Company Goals</div>\n <p className=\"mb-4 text-sm text-text-secondary\">Q1 2026 targets</p>\n <div className=\"space-y-4\">\n {companyGoals.map((g) => {\n const pct = Math.round((g.current / g.target) * 100);\n return (\n <div key={g.goal} className=\"space-y-1\">\n <div className=\"flex justify-between text-xs\">\n <span className=\"text-text-secondary\">{g.goal}</span>\n <span className=\"font-medium\">\n {g.current}/{g.target} {g.unit}\n </span>\n </div>\n <div className=\"h-2 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-2 rounded ${pct >= 90 ? 'bg-status-success-text' : pct >= 70 ? 'bg-status-warning-text' : 'bg-status-error-text'}`}\n style={{ width: `${Math.min(pct, 100)}%` }}\n />\n </div>\n </div>\n );\n })}\n </div>\n </EmphasisPanel>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Upcoming Interviews</CardTitle>\n <CardDescription>{upcomingInterviews.length} scheduled</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {upcomingInterviews.map((interview) => (\n <div key={interview.id} className=\"flex items-center gap-3 rounded border p-2\">\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">{interview.candidateName}</p>\n <p className=\"text-xs text-text-secondary\">{interview.position}</p>\n </div>\n <div className=\"text-right flex-shrink-0\">\n <p className=\"text-xs font-medium\">{interview.date}</p>\n <p className=\"text-xs text-text-secondary\">{interview.time}</p>\n </div>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {interview.type}\n </Badge>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">Pending Actions</CardTitle>\n <CardDescription>Items requiring your attention</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {pendingLeaves.map((leave) => (\n <div key={leave.id} className=\"flex items-center justify-between rounded border p-2\">\n <div>\n <p className=\"text-sm font-medium\">{leave.employeeName}</p>\n <p className=\"text-xs text-text-secondary\">\n {leave.type} leave · {leave.days} days\n </p>\n </div>\n <div className=\"flex gap-1\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"h-7 text-xs\"\n disabled={processingLeaveId === leave.id}\n onClick={() => void decideLeave(leave.id, 'rejected')}\n >\n Deny\n </Button>\n <Button\n size=\"sm\"\n className=\"h-7 text-xs\"\n disabled={processingLeaveId === leave.id}\n onClick={() => void decideLeave(leave.id, 'approved')}\n >\n Approve\n </Button>\n </div>\n </div>\n ))}\n <Separator />\n <div className=\"text-xs text-text-secondary text-center\">\n {candidates.filter((c) => c.status === 'new').length} new applications to review\n </div>\n </CardContent>\n </Card>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base flex items-center gap-2\">\n <Award className=\"h-4 w-4 text-status-warning-text\" />\n Top Performers\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {topPerformers.map((emp, idx) => (\n <div key={emp.id} className=\"flex items-center gap-3\">\n <span className=\"text-sm font-bold text-text-secondary w-5\">#{idx + 1}</span>\n <div className=\"flex-1\">\n <p className=\"text-sm font-medium\">\n {emp.firstName} {emp.lastName}\n </p>\n <p className=\"text-xs text-text-secondary\">\n {emp.position} · {emp.department}\n </p>\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 font-medium\">{emp.performanceScore}</span>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base flex items-center gap-2\">\n <MapPin className=\"h-4 w-4\" />\n Workforce Locations\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {Object.entries(locationMap)\n .sort(([, a], [, b]) => b - a)\n .map(([location, count]) => (\n <div key={location} className=\"flex items-center justify-between\">\n <span className=\"text-sm\">{location}</span>\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>Recent Hires</CardTitle>\n <CardDescription>Newest team members</CardDescription>\n </CardHeader>\n <CardContent>\n <ResponsiveTable\n columns={recentHireColumns}\n data={recentHires}\n rowKey={(emp) => emp.id}\n />\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,357 +1,226 @@
1
1
  import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
2
  import { useMemo as t } from "react";
3
- import { ArrowUp as n, Building2 as r, DollarSign as i, Percent as a, Target as o } from "lucide-react";
4
- import { jsx as s, jsxs as c } from "react/jsx-runtime";
5
- import { Badge as l, Card as u, CardContent as d, CardDescription as f, CardHeader as p, CardTitle as m, GlassCard as h, GradientText as g, PagePurpose as _, Separator as v } from "@burdenoff/fe-libs/ui";
3
+ import { Building2 as n, Percent as r, Target as i } from "lucide-react";
4
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
5
+ import { Badge as s, Card as c, CardContent as l, CardDescription as u, CardHeader as d, CardTitle as f, GlassCard as p, GradientText as m, PagePurpose as h, ResponsiveTable as g, Separator as _ } from "@burdenoff/fe-libs/ui";
6
6
  //#region src/crewfoundry/pages/DashboardExecutiveDashboardPage.tsx
7
- function y() {
8
- let { employees: y, departments: b, projects: x, jobPostings: S } = e(), C = t(() => {
9
- let e = [
10
- "Q1 2025",
11
- "Q2 2025",
12
- "Q3 2025",
13
- "Q4 2025"
14
- ], t = x.reduce((e, t) => e + t.budget, 0) || 1e6;
15
- return e.map((e, n) => {
16
- let r = Math.round(t * (.55 + n * .08)), i = Math.max(1, y.length - (3 - n) * 4);
17
- return {
18
- quarter: e,
19
- revenue: r,
20
- headcount: i,
21
- revenuePerHead: Math.round(r / i)
22
- };
23
- });
24
- }, [y.length, x]), w = t(() => [
7
+ function v() {
8
+ let { employees: v, departments: y, projects: b, jobPostings: x } = e(), S = t(() => [
25
9
  {
26
10
  metric: "Flight Risk Employees",
27
- value: y.filter((e) => e.performanceScore < 3.6).length,
11
+ value: v.filter((e) => e.performanceScore < 3.6).length,
28
12
  severity: "warning",
29
- detail: `${Math.round(y.filter((e) => e.performanceScore < 3.6).length / Math.max(y.length, 1) * 100)}% of workforce`
13
+ detail: `${Math.round(v.filter((e) => e.performanceScore < 3.6).length / Math.max(v.length, 1) * 100)}% of workforce`
30
14
  },
31
15
  {
32
- metric: "Overdue Performance Reviews",
33
- value: y.filter((e) => e.status === "on_leave").length,
16
+ metric: "Employees On Leave",
17
+ value: v.filter((e) => e.status === "on_leave").length,
34
18
  severity: "error",
35
- detail: "Review follow-ups required"
19
+ detail: "Coverage follow-ups required"
36
20
  },
37
21
  {
38
- metric: "Unfilled Critical Roles",
39
- value: S.filter((e) => e.status === "active" && e.experienceLevel === "lead").length,
22
+ metric: "Unfilled Lead Roles",
23
+ value: x.filter((e) => e.status === "active" && e.experienceLevel === "lead").length,
40
24
  severity: "warning",
41
25
  detail: "Open lead-level positions"
42
26
  },
43
27
  {
44
- metric: "Expiring Contracts",
45
- value: y.filter((e) => e.type === "contract").length,
28
+ metric: "Contract Employees",
29
+ value: v.filter((e) => e.type === "contract").length,
46
30
  severity: "info",
47
31
  detail: "Contract renewals in focus"
48
32
  }
49
- ], [y, S]), T = t(() => [{
50
- category: "Company",
51
- male: 52,
52
- female: 43,
53
- other: 5
54
- }, ...b.map((e) => {
55
- let t = y.filter((t) => t.department === e.name).length, n = Math.min(100, Math.round(45 + t % 15)), r = Math.min(100 - n, Math.round(40 + t % 10)), i = Math.max(0, 100 - n - r);
56
- return {
57
- category: e.name,
58
- male: n,
59
- female: r,
60
- other: i
61
- };
62
- }).slice(0, 3)], [b, y]), E = y.reduce((e, t) => e + t.salary, 0), D = b.reduce((e, t) => e + t.budget, 0), O = x.reduce((e, t) => e + t.budget, 0), k = x.reduce((e, t) => e + t.spent, 0), A = Math.round(k / O * 100);
63
- return /* @__PURE__ */ c("div", {
33
+ ], [v, x]), C = v.reduce((e, t) => e + t.salary, 0), w = y.reduce((e, t) => e + t.budget, 0), T = b.reduce((e, t) => e + t.budget, 0), E = b.reduce((e, t) => e + t.spent, 0), D = T > 0 ? Math.round(E / T * 100) : 0, O = v.filter((e) => e.status === "terminated").length, k = v.length > 0 ? Math.round((1 - O / v.length) * 100) : 0, A = y.reduce((e, t) => e + t.employeeCount, 0), j = A > 0 ? w / A : 0;
34
+ return /* @__PURE__ */ o("div", {
64
35
  className: "space-y-6 p-6",
65
36
  children: [
66
- /* @__PURE__ */ c("div", {
37
+ /* @__PURE__ */ o("div", {
67
38
  className: "flex items-center justify-between",
68
- children: [/* @__PURE__ */ c("div", { children: [
69
- /* @__PURE__ */ s("h1", {
39
+ children: [/* @__PURE__ */ o("div", { children: [
40
+ /* @__PURE__ */ a("h1", {
70
41
  className: "text-2xl font-semibold",
71
- children: /* @__PURE__ */ s(g, { children: "Executive Dashboard" })
42
+ children: /* @__PURE__ */ a(m, { children: "Executive Dashboard" })
72
43
  }),
73
- /* @__PURE__ */ s("p", {
44
+ /* @__PURE__ */ a("p", {
74
45
  className: "text-sm text-text-secondary",
75
46
  children: "Strategic workforce insights for leadership"
76
47
  }),
77
- /* @__PURE__ */ s(_, {
48
+ /* @__PURE__ */ a(h, {
78
49
  className: "mt-1",
79
50
  children: "The executive snapshot — top-line workforce, financial, and hiring KPIs in one view so leaders can make decisions fast."
80
51
  })
81
- ] }), /* @__PURE__ */ s(l, {
52
+ ] }), /* @__PURE__ */ a(s, {
82
53
  variant: "outline",
83
54
  children: "Q1 2026"
84
55
  })]
85
56
  }),
86
- /* @__PURE__ */ c("div", {
87
- className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
57
+ /* @__PURE__ */ o("div", {
58
+ className: "grid gap-4 md:grid-cols-3",
88
59
  children: [
89
- /* @__PURE__ */ c(h, {
60
+ /* @__PURE__ */ o(p, {
90
61
  treatment: "glass",
91
62
  glow: !0,
92
63
  className: "border-border-seam",
93
- children: [/* @__PURE__ */ c(p, {
64
+ children: [/* @__PURE__ */ o(d, {
94
65
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
95
- children: [/* @__PURE__ */ s(m, {
96
- className: "text-sm font-medium",
97
- children: "Revenue per Employee"
98
- }), /* @__PURE__ */ s(i, { className: "h-4 w-4 text-text-secondary" })]
99
- }), /* @__PURE__ */ c(d, { children: [/* @__PURE__ */ s("div", {
100
- className: "text-2xl font-bold tabular-nums",
101
- children: "$21,862"
102
- }), /* @__PURE__ */ c("div", {
103
- className: "flex items-center text-xs text-status-success-text",
104
- children: [/* @__PURE__ */ s(n, { className: "h-3 w-3 mr-1" }), "+2.0% from Q3"]
105
- })] })]
106
- }),
107
- /* @__PURE__ */ c(h, {
108
- treatment: "metric",
109
- className: "border-border-seam",
110
- children: [/* @__PURE__ */ c(p, {
111
- className: "flex flex-row items-center justify-between space-y-0 pb-2",
112
- children: [/* @__PURE__ */ s(m, {
66
+ children: [/* @__PURE__ */ a(f, {
113
67
  className: "text-sm font-medium",
114
68
  children: "Total Workforce Cost"
115
- }), /* @__PURE__ */ s(r, { className: "h-4 w-4 text-text-secondary" })]
116
- }), /* @__PURE__ */ c(d, { children: [/* @__PURE__ */ c("div", {
69
+ }), /* @__PURE__ */ a(n, { className: "h-4 w-4 text-text-secondary" })]
70
+ }), /* @__PURE__ */ o(l, { children: [/* @__PURE__ */ o("div", {
117
71
  className: "text-2xl font-bold tabular-nums",
118
72
  children: [
119
73
  "$",
120
- (E / 1e6).toFixed(1),
74
+ (C / 1e6).toFixed(1),
121
75
  "M"
122
76
  ]
123
- }), /* @__PURE__ */ s("p", {
77
+ }), /* @__PURE__ */ a("p", {
124
78
  className: "text-xs text-text-secondary",
125
79
  children: "Annual salary expenditure"
126
80
  })] })]
127
81
  }),
128
- /* @__PURE__ */ c(h, {
82
+ /* @__PURE__ */ o(p, {
129
83
  treatment: "metric",
130
84
  className: "border-border-seam",
131
- children: [/* @__PURE__ */ c(p, {
85
+ children: [/* @__PURE__ */ o(d, {
132
86
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
133
- children: [/* @__PURE__ */ s(m, {
87
+ children: [/* @__PURE__ */ a(f, {
134
88
  className: "text-sm font-medium",
135
89
  children: "Budget Utilization"
136
- }), /* @__PURE__ */ s(a, { className: "h-4 w-4 text-text-secondary" })]
137
- }), /* @__PURE__ */ c(d, { children: [/* @__PURE__ */ c("div", {
90
+ }), /* @__PURE__ */ a(r, { className: "h-4 w-4 text-text-secondary" })]
91
+ }), /* @__PURE__ */ o(l, { children: [/* @__PURE__ */ o("div", {
138
92
  className: "text-2xl font-bold tabular-nums",
139
- children: [A, "%"]
140
- }), /* @__PURE__ */ c("p", {
93
+ children: [D, "%"]
94
+ }), /* @__PURE__ */ o("p", {
141
95
  className: "text-xs text-text-secondary",
142
96
  children: [
143
97
  "$",
144
- (k / 1e6).toFixed(1),
98
+ (E / 1e6).toFixed(1),
145
99
  "M of $",
146
- (O / 1e6).toFixed(1),
147
- "M"
100
+ (T / 1e6).toFixed(1),
101
+ "M project budget"
148
102
  ]
149
103
  })] })]
150
104
  }),
151
- /* @__PURE__ */ c(h, {
105
+ /* @__PURE__ */ o(p, {
152
106
  treatment: "metric",
153
107
  className: "border-border-seam",
154
- children: [/* @__PURE__ */ c(p, {
108
+ children: [/* @__PURE__ */ o(d, {
155
109
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
156
- children: [/* @__PURE__ */ s(m, {
110
+ children: [/* @__PURE__ */ a(f, {
157
111
  className: "text-sm font-medium",
158
112
  children: "Retention Rate"
159
- }), /* @__PURE__ */ s(o, { className: "h-4 w-4 text-text-secondary" })]
160
- }), /* @__PURE__ */ c(d, { children: [/* @__PURE__ */ s("div", {
113
+ }), /* @__PURE__ */ a(i, { className: "h-4 w-4 text-text-secondary" })]
114
+ }), /* @__PURE__ */ o(l, { children: [/* @__PURE__ */ o("div", {
161
115
  className: "text-2xl font-bold tabular-nums",
162
- children: "95.8%"
163
- }), /* @__PURE__ */ c("div", {
164
- className: "flex items-center text-xs text-status-success-text",
165
- children: [/* @__PURE__ */ s(n, { className: "h-3 w-3 mr-1" }), "+1.1% improvement"]
116
+ children: [k, "%"]
117
+ }), /* @__PURE__ */ o("p", {
118
+ className: "text-xs text-text-secondary",
119
+ children: [
120
+ O,
121
+ " of ",
122
+ v.length,
123
+ " employees no longer active"
124
+ ]
166
125
  })] })]
167
126
  })
168
127
  ]
169
128
  }),
170
- /* @__PURE__ */ c("div", {
171
- className: "grid gap-4 md:grid-cols-2",
172
- children: [/* @__PURE__ */ c(u, { children: [/* @__PURE__ */ c(p, { children: [/* @__PURE__ */ s(m, { children: "Revenue & Headcount Trend" }), /* @__PURE__ */ s(f, { children: "Quarterly performance metrics" })] }), /* @__PURE__ */ c(d, { children: [/* @__PURE__ */ c("div", {
173
- className: "grid grid-cols-4 gap-2 text-xs font-medium text-text-secondary border-b pb-2 mb-2",
174
- children: [
175
- /* @__PURE__ */ s("span", { children: "Quarter" }),
176
- /* @__PURE__ */ s("span", {
177
- className: "text-right",
178
- children: "Revenue"
179
- }),
180
- /* @__PURE__ */ s("span", {
181
- className: "text-right",
182
- children: "Headcount"
183
- }),
184
- /* @__PURE__ */ s("span", {
185
- className: "text-right",
186
- children: "Rev/Head"
187
- })
188
- ]
189
- }), C.map((e) => /* @__PURE__ */ c("div", {
190
- className: "grid grid-cols-4 gap-2 py-2 border-b last:border-0 text-sm",
191
- children: [
192
- /* @__PURE__ */ s("span", {
193
- className: "font-medium",
194
- children: e.quarter
195
- }),
196
- /* @__PURE__ */ c("span", {
197
- className: "text-right",
198
- children: [
199
- "$",
200
- (e.revenue / 1e6).toFixed(1),
201
- "M"
202
- ]
203
- }),
204
- /* @__PURE__ */ s("span", {
205
- className: "text-right",
206
- children: e.headcount
207
- }),
208
- /* @__PURE__ */ c("span", {
209
- className: "text-right font-medium",
210
- children: ["$", e.revenuePerHead.toLocaleString()]
211
- })
212
- ]
213
- }, e.quarter))] })] }), /* @__PURE__ */ c(u, { children: [/* @__PURE__ */ c(p, { children: [/* @__PURE__ */ s(m, { children: "Risk Indicators" }), /* @__PURE__ */ s(f, { children: "Items requiring executive attention" })] }), /* @__PURE__ */ s(d, {
214
- className: "space-y-3",
215
- children: w.map((e) => /* @__PURE__ */ c("div", {
216
- className: "flex items-center justify-between rounded border p-3",
217
- children: [/* @__PURE__ */ c("div", {
218
- className: "flex items-center gap-3",
219
- children: [/* @__PURE__ */ s("div", { className: `h-3 w-3 rounded-full ${e.severity === "error" ? "bg-status-error-text" : e.severity === "warning" ? "bg-status-warning-text" : "bg-status-info-text"}` }), /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("p", {
220
- className: "text-sm font-medium",
221
- children: e.metric
222
- }), /* @__PURE__ */ s("p", {
223
- className: "text-xs text-text-secondary",
224
- children: e.detail
225
- })] })]
226
- }), /* @__PURE__ */ s("span", {
227
- className: "text-lg font-bold",
228
- children: e.value
229
- })]
230
- }, e.metric))
231
- })] })]
232
- }),
233
- /* @__PURE__ */ c(u, { children: [/* @__PURE__ */ c(p, { children: [/* @__PURE__ */ s(m, { children: "Diversity & Inclusion Metrics" }), /* @__PURE__ */ s(f, { children: "Gender distribution across organization segments" })] }), /* @__PURE__ */ s(d, { children: /* @__PURE__ */ s("div", {
234
- className: "space-y-4",
235
- children: T.map((e) => /* @__PURE__ */ c("div", {
236
- className: "space-y-1",
237
- children: [/* @__PURE__ */ c("div", {
238
- className: "flex justify-between text-sm",
239
- children: [/* @__PURE__ */ s("span", {
240
- className: "font-medium",
241
- children: e.category
242
- }), /* @__PURE__ */ c("span", {
129
+ /* @__PURE__ */ o(c, { children: [/* @__PURE__ */ o(d, { children: [/* @__PURE__ */ a(f, { children: "Risk Indicators" }), /* @__PURE__ */ a(u, { children: "Items requiring executive attention" })] }), /* @__PURE__ */ a(l, {
130
+ className: "grid gap-3 md:grid-cols-2",
131
+ children: S.map((e) => /* @__PURE__ */ o("div", {
132
+ className: "flex items-center justify-between rounded border p-3",
133
+ children: [/* @__PURE__ */ o("div", {
134
+ className: "flex items-center gap-3",
135
+ children: [/* @__PURE__ */ a("div", { className: `h-3 w-3 rounded-full ${e.severity === "error" ? "bg-status-error-text" : e.severity === "warning" ? "bg-status-warning-text" : "bg-status-info-text"}` }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
136
+ className: "text-sm font-medium",
137
+ children: e.metric
138
+ }), /* @__PURE__ */ a("p", {
243
139
  className: "text-xs text-text-secondary",
244
- children: [
245
- "M: ",
246
- e.male,
247
- "% · F: ",
248
- e.female,
249
- "% · Other: ",
250
- e.other,
251
- "%"
252
- ]
253
- })]
254
- }), /* @__PURE__ */ c("div", {
255
- className: "flex h-3 rounded overflow-hidden",
256
- children: [
257
- /* @__PURE__ */ s("div", {
258
- className: "bg-status-info-text",
259
- style: { width: `${e.male}%` }
260
- }),
261
- /* @__PURE__ */ s("div", {
262
- className: "bg-action-primary-bg",
263
- style: { width: `${e.female}%` }
264
- }),
265
- /* @__PURE__ */ s("div", {
266
- className: "bg-status-success-text",
267
- style: { width: `${e.other}%` }
268
- })
269
- ]
140
+ children: e.detail
141
+ })] })]
142
+ }), /* @__PURE__ */ a("span", {
143
+ className: "text-lg font-bold",
144
+ children: e.value
270
145
  })]
271
- }, e.category))
272
- }) })] }),
273
- /* @__PURE__ */ c(u, { children: [/* @__PURE__ */ c(p, { children: [/* @__PURE__ */ s(m, { children: "Department Budget Status" }), /* @__PURE__ */ s(f, { children: "Annual budget allocation and headcount" })] }), /* @__PURE__ */ c(d, { children: [
274
- /* @__PURE__ */ c("div", {
275
- className: "grid grid-cols-5 gap-2 text-xs font-medium text-text-secondary border-b pb-2 mb-2",
276
- children: [
277
- /* @__PURE__ */ s("span", { children: "Department" }),
278
- /* @__PURE__ */ s("span", { children: "Head" }),
279
- /* @__PURE__ */ s("span", {
280
- className: "text-right",
281
- children: "Headcount"
282
- }),
283
- /* @__PURE__ */ s("span", {
284
- className: "text-right",
285
- children: "Budget"
286
- }),
287
- /* @__PURE__ */ s("span", {
288
- className: "text-right",
289
- children: "Cost/Employee"
290
- })
291
- ]
292
- }),
293
- b.map((e) => {
294
- let t = e.employeeCount > 0 ? Math.round(e.budget / e.employeeCount) : 0;
295
- return /* @__PURE__ */ c("div", {
296
- className: "grid grid-cols-5 gap-2 py-2 border-b last:border-0 text-sm",
297
- children: [
298
- /* @__PURE__ */ s("span", {
146
+ }, e.metric))
147
+ })] }),
148
+ /* @__PURE__ */ o(c, { children: [/* @__PURE__ */ o(d, { children: [/* @__PURE__ */ a(f, { children: "Department Budget Status" }), /* @__PURE__ */ a(u, { children: "Annual budget allocation and headcount" })] }), /* @__PURE__ */ o(l, { children: [
149
+ /* @__PURE__ */ a(g, {
150
+ columns: [
151
+ {
152
+ key: "name",
153
+ header: "Department",
154
+ priority: "primary",
155
+ cell: (e) => /* @__PURE__ */ a("span", {
299
156
  className: "font-medium",
300
157
  children: e.name
301
- }),
302
- /* @__PURE__ */ s("span", {
158
+ })
159
+ },
160
+ {
161
+ key: "head",
162
+ header: "Head",
163
+ priority: "secondary",
164
+ cell: (e) => /* @__PURE__ */ a("span", {
303
165
  className: "text-text-secondary",
304
166
  children: e.headName
305
- }),
306
- /* @__PURE__ */ s("span", {
307
- className: "text-right",
167
+ })
168
+ },
169
+ {
170
+ key: "headcount",
171
+ header: "Headcount",
172
+ priority: "secondary",
173
+ cell: (e) => /* @__PURE__ */ a("span", {
174
+ className: "md:block md:text-right",
308
175
  children: e.employeeCount
309
- }),
310
- /* @__PURE__ */ c("span", {
311
- className: "text-right",
176
+ })
177
+ },
178
+ {
179
+ key: "budget",
180
+ header: "Budget",
181
+ priority: "secondary",
182
+ cell: (e) => /* @__PURE__ */ o("span", {
183
+ className: "md:block md:text-right",
312
184
  children: [
313
185
  "$",
314
186
  (e.budget / 1e6).toFixed(1),
315
187
  "M"
316
188
  ]
317
- }),
318
- /* @__PURE__ */ c("span", {
319
- className: "text-right",
189
+ })
190
+ },
191
+ {
192
+ key: "costPerEmployee",
193
+ header: "Cost/Employee",
194
+ priority: "primary",
195
+ cell: (e) => /* @__PURE__ */ o("span", {
196
+ className: "md:block md:text-right",
320
197
  children: [
321
198
  "$",
322
- (t / 1e3).toFixed(0),
199
+ ((e.employeeCount > 0 ? Math.round(e.budget / e.employeeCount) : 0) / 1e3).toFixed(0),
323
200
  "K"
324
201
  ]
325
202
  })
326
- ]
327
- }, e.id);
203
+ }
204
+ ],
205
+ data: y,
206
+ rowKey: (e) => e.id
328
207
  }),
329
- /* @__PURE__ */ s(v, { className: "my-2" }),
330
- /* @__PURE__ */ c("div", {
331
- className: "grid grid-cols-5 gap-2 text-sm font-bold",
208
+ /* @__PURE__ */ a(_, { className: "my-3" }),
209
+ /* @__PURE__ */ o("div", {
210
+ className: "flex flex-wrap items-center justify-between gap-2 text-sm font-bold",
332
211
  children: [
333
- /* @__PURE__ */ s("span", { children: "Total" }),
334
- /* @__PURE__ */ s("span", {}),
335
- /* @__PURE__ */ s("span", {
336
- className: "text-right",
337
- children: b.reduce((e, t) => e + t.employeeCount, 0)
338
- }),
339
- /* @__PURE__ */ c("span", {
340
- className: "text-right",
341
- children: [
342
- "$",
343
- (D / 1e6).toFixed(1),
344
- "M"
345
- ]
346
- }),
347
- /* @__PURE__ */ c("span", {
348
- className: "text-right",
349
- children: [
350
- "$",
351
- (D / b.reduce((e, t) => e + t.employeeCount, 0) / 1e3).toFixed(0),
352
- "K"
353
- ]
354
- })
212
+ /* @__PURE__ */ a("span", { children: "Total" }),
213
+ /* @__PURE__ */ o("span", { children: [A, " employees"] }),
214
+ /* @__PURE__ */ o("span", { children: [
215
+ "$",
216
+ (w / 1e6).toFixed(1),
217
+ "M budget"
218
+ ] }),
219
+ /* @__PURE__ */ o("span", { children: [
220
+ "$",
221
+ (j / 1e3).toFixed(0),
222
+ "K / employee"
223
+ ] })
355
224
  ]
356
225
  })
357
226
  ] })] })
@@ -359,6 +228,6 @@ function y() {
359
228
  });
360
229
  }
361
230
  //#endregion
362
- export { y as DashboardExecutiveDashboardPage };
231
+ export { v as DashboardExecutiveDashboardPage };
363
232
 
364
233
  //# sourceMappingURL=DashboardExecutiveDashboardPage.js.map