@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 +1 @@
1
- {"version":3,"file":"AnalyticsFinancialAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n Separator,\n} from '@burdenoff/fe-libs/ui';\nimport { ArrowUp, DollarSign, FileText, Receipt, TrendingUp, Wallet } from 'lucide-react';\nimport { useMemo } from 'react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function AnalyticsFinancialAnalyticsPagePage() {\n const { employees, departments, payrollRecords, invoices, projects } = useCrewFoundryStore();\n\n const monthlyPayrollTrend = useMemo(() => {\n const byPeriod = payrollRecords.reduce<\n Record<string, { gross: number; net: number; deductions: number }>\n >((acc, record) => {\n const month = new Date(record.payDate).toLocaleString('en-US', { month: 'short' });\n const current = acc[month] || { gross: 0, net: 0, deductions: 0 };\n current.gross += record.grossPay;\n current.net += record.netPay;\n current.deductions += record.deductions;\n acc[month] = current;\n return acc;\n }, {});\n return Object.entries(byPeriod)\n .map(([month, value]) => ({ month, ...value }))\n .slice(-6);\n }, [payrollRecords]);\n\n const expenseCategories = useMemo(\n () => [\n {\n category: 'Payroll',\n amount: payrollRecords.reduce((sum, record) => sum + record.grossPay, 0),\n budget: departments.reduce((sum, department) => sum + department.budget * 0.7, 0),\n icon: Wallet,\n },\n {\n category: 'Benefits',\n amount: payrollRecords.reduce((sum, record) => sum + record.deductions * 0.4, 0),\n budget: departments.reduce((sum, department) => sum + department.budget * 0.15, 0),\n icon: Receipt,\n },\n {\n category: 'Recruitment',\n amount: invoices.reduce(\n (sum, invoice) => sum + (invoice.status === 'paid' ? invoice.amount * 0.15 : 0),\n 0\n ),\n budget: departments.reduce((sum, department) => sum + department.budget * 0.1, 0),\n icon: FileText,\n },\n {\n category: 'Training',\n amount: projects.reduce((sum, project) => sum + project.spent * 0.08, 0),\n budget: departments.reduce((sum, department) => sum + department.budget * 0.08, 0),\n icon: TrendingUp,\n },\n ],\n [departments, invoices, payrollRecords, projects]\n );\n\n const totalPayroll = employees.reduce((sum, e) => sum + e.salary, 0);\n const monthlyPayroll = Math.round(totalPayroll / 12);\n const totalInvoiced = invoices.reduce((sum, inv) => sum + inv.amount, 0);\n const paidInvoices = invoices\n .filter((i) => i.status === 'paid')\n .reduce((s, i) => s + i.amount, 0);\n const totalProjectBudget = projects.reduce((s, p) => s + p.budget, 0);\n const totalProjectSpent = projects.reduce((s, p) => s + p.spent, 0);\n\n const maxPayroll = Math.max(1, ...monthlyPayrollTrend.map((m) => m.gross));\n\n const deptCost = departments.map((d) => {\n const deptEmps = employees.filter((e) => e.department === d.name);\n const totalSal = deptEmps.reduce((s, e) => s + e.salary, 0);\n return { name: d.name, salary: totalSal, budget: d.budget, headcount: deptEmps.length };\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>Financial Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Workforce financial metrics and cost analysis\n </p>\n </div>\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\">Monthly Payroll</CardTitle>\n <DollarSign className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(monthlyPayroll / 1000).toFixed(0)}K\n </div>\n <div className=\"flex items-center text-xs text-status-warning-text\">\n <ArrowUp className=\"h-3 w-3 mr-1\" />\n +2.1% from last month\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\">Annual Salary Cost</CardTitle>\n <Wallet className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(totalPayroll / 1000000).toFixed(1)}M\n </div>\n <p className=\"text-xs text-text-secondary\">{employees.length} employees</p>\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\">Total Invoiced</CardTitle>\n <FileText className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(totalInvoiced / 1000).toFixed(1)}K\n </div>\n <p className=\"text-xs text-text-secondary\">\n ${(paidInvoices / 1000).toFixed(1)}K collected\n </p>\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\">Project Budget</CardTitle>\n <TrendingUp className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(totalProjectBudget / 1000000).toFixed(1)}M\n </div>\n <p className=\"text-xs text-text-secondary\">\n {Math.round((totalProjectSpent / totalProjectBudget) * 100)}% utilized\n </p>\n </CardContent>\n </GlassCard>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Payroll Trend</CardTitle>\n <CardDescription>Monthly gross payroll over the last 6 months</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {monthlyPayrollTrend.map((m) => (\n <div key={m.month} className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-text-secondary\">{m.month}</span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden flex\">\n <div\n className=\"h-5 bg-action-primary-bg\"\n style={{ width: `${Math.round((m.net / maxPayroll) * 100)}%` }}\n />\n <div\n className=\"h-5 bg-action-primary-bg/30\"\n style={{ width: `${Math.round((m.deductions / maxPayroll) * 100)}%` }}\n />\n </div>\n <span className=\"text-sm font-medium w-20 text-right\">\n ${(m.gross / 1000000).toFixed(2)}M\n </span>\n </div>\n ))}\n <div className=\"flex items-center gap-4 mt-2 text-xs text-text-secondary\">\n <div className=\"flex items-center gap-1\">\n <div className=\"h-3 w-3 bg-action-primary-bg rounded\" />\n <span>Net Pay</span>\n </div>\n <div className=\"flex items-center gap-1\">\n <div className=\"h-3 w-3 bg-action-primary-bg/30 rounded\" />\n <span>Deductions</span>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle>Budget vs Actual</CardTitle>\n <CardDescription>Monthly expense tracking by category</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {expenseCategories.map((cat) => {\n const pct = Math.round((cat.amount / cat.budget) * 100);\n return (\n <div key={cat.category} className=\"space-y-1\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"font-medium\">{cat.category}</span>\n <span>\n ${(cat.amount / 1000).toFixed(0)}K / ${(cat.budget / 1000).toFixed(0)}K\n </span>\n </div>\n <div className=\"h-3 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-3 rounded ${pct > 95 ? 'bg-status-error-text' : pct > 80 ? 'bg-status-warning-text' : 'bg-status-success-text'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n <p className=\"text-xs text-text-secondary text-right\">{pct}% utilized</p>\n </div>\n );\n })}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Outstanding Invoices</CardTitle>\n <CardDescription>Invoices requiring attention</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {invoices.map((inv) => (\n <div key={inv.id} className=\"flex items-center justify-between rounded border p-3\">\n <div>\n <p className=\"text-sm font-medium\">{inv.number}</p>\n <p className=\"text-xs text-text-secondary\">{inv.clientName}</p>\n </div>\n <div className=\"text-right\">\n <p className=\"text-sm font-medium\">${inv.amount.toLocaleString()}</p>\n <Badge\n variant={\n inv.status === 'paid'\n ? 'default'\n : inv.status === 'overdue'\n ? 'destructive'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {inv.status}\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Department Cost Analysis</CardTitle>\n <CardDescription>Total salary cost and budget allocation by department</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-5 gap-2 text-xs font-medium text-text-secondary border-b pb-2 mb-2\">\n <span>Department</span>\n <span className=\"text-right\">Headcount</span>\n <span className=\"text-right\">Total Salary</span>\n <span className=\"text-right\">Dept Budget</span>\n <span className=\"text-right\">Salary/Budget %</span>\n </div>\n {deptCost\n .sort((a, b) => b.salary - a.salary)\n .map((d) => (\n <div\n key={d.name}\n className=\"grid grid-cols-5 gap-2 py-2 border-b last:border-0 text-sm\"\n >\n <span className=\"font-medium\">{d.name}</span>\n <span className=\"text-right\">{d.headcount}</span>\n <span className=\"text-right\">${(d.salary / 1000).toFixed(0)}K</span>\n <span className=\"text-right\">${(d.budget / 1000000).toFixed(1)}M</span>\n <span className=\"text-right\">\n <Badge\n variant={d.salary / d.budget > 0.5 ? 'destructive' : 'default'}\n className=\"text-[10px]\"\n >\n {Math.round((d.salary / d.budget) * 100)}%\n </Badge>\n </span>\n </div>\n ))}\n <Separator className=\"my-2\" />\n <div className=\"grid grid-cols-5 gap-2 text-sm font-bold\">\n <span>Total</span>\n <span className=\"text-right\">{employees.length}</span>\n <span className=\"text-right\">${(totalPayroll / 1000000).toFixed(1)}M</span>\n <span className=\"text-right\">\n ${(departments.reduce((s, d) => s + d.budget, 0) / 1000000).toFixed(1)}M\n </span>\n <span />\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AnalyticsFinancialAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n Separator,\n} from '@burdenoff/fe-libs/ui';\nimport { ArrowUp, DollarSign, FileText, Receipt, TrendingUp, Wallet } from 'lucide-react';\nimport { useMemo } from 'react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function AnalyticsFinancialAnalyticsPagePage() {\n const { employees, departments, payrollRecords, invoices, projects } = useCrewFoundryStore();\n\n const monthlyPayrollTrend = useMemo(() => {\n const byPeriod = payrollRecords.reduce<\n Record<string, { gross: number; net: number; deductions: number }>\n >((acc, record) => {\n const month = new Date(record.payDate).toLocaleString('en-US', { month: 'short' });\n const current = acc[month] || { gross: 0, net: 0, deductions: 0 };\n current.gross += record.grossPay;\n current.net += record.netPay;\n current.deductions += record.deductions;\n acc[month] = current;\n return acc;\n }, {});\n return Object.entries(byPeriod)\n .map(([month, value]) => ({ month, ...value }))\n .slice(-6);\n }, [payrollRecords]);\n\n const expenseCategories = useMemo(\n () => [\n {\n category: 'Payroll',\n amount: payrollRecords.reduce((sum, record) => sum + record.grossPay, 0),\n budget: departments.reduce((sum, department) => sum + department.budget * 0.7, 0),\n icon: Wallet,\n },\n {\n category: 'Benefits',\n amount: payrollRecords.reduce((sum, record) => sum + record.deductions * 0.4, 0),\n budget: departments.reduce((sum, department) => sum + department.budget * 0.15, 0),\n icon: Receipt,\n },\n {\n category: 'Recruitment',\n amount: invoices.reduce(\n (sum, invoice) => sum + (invoice.status === 'paid' ? invoice.amount * 0.15 : 0),\n 0\n ),\n budget: departments.reduce((sum, department) => sum + department.budget * 0.1, 0),\n icon: FileText,\n },\n {\n category: 'Training',\n amount: projects.reduce((sum, project) => sum + project.spent * 0.08, 0),\n budget: departments.reduce((sum, department) => sum + department.budget * 0.08, 0),\n icon: TrendingUp,\n },\n ],\n [departments, invoices, payrollRecords, projects]\n );\n\n const totalPayroll = employees.reduce((sum, e) => sum + e.salary, 0);\n const monthlyPayroll = Math.round(totalPayroll / 12);\n const totalInvoiced = invoices.reduce((sum, inv) => sum + inv.amount, 0);\n const paidInvoices = invoices\n .filter((i) => i.status === 'paid')\n .reduce((s, i) => s + i.amount, 0);\n const totalProjectBudget = projects.reduce((s, p) => s + p.budget, 0);\n const totalProjectSpent = projects.reduce((s, p) => s + p.spent, 0);\n\n const maxPayroll = Math.max(1, ...monthlyPayrollTrend.map((m) => m.gross));\n\n const deptCost = departments.map((d) => {\n const deptEmps = employees.filter((e) => e.department === d.name);\n const totalSal = deptEmps.reduce((s, e) => s + e.salary, 0);\n return { name: d.name, salary: totalSal, budget: d.budget, headcount: deptEmps.length };\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>Financial Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Workforce financial metrics and cost analysis\n </p>\n <PagePurpose className=\"mt-1\">Understand the money side of your workforce — payroll, project budgets, and spend trends — so you can plan headcount and control costs with confidence.</PagePurpose>\n </div>\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\">Monthly Payroll</CardTitle>\n <DollarSign className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(monthlyPayroll / 1000).toFixed(0)}K\n </div>\n <div className=\"flex items-center text-xs text-status-warning-text\">\n <ArrowUp className=\"h-3 w-3 mr-1\" />\n +2.1% from last month\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\">Annual Salary Cost</CardTitle>\n <Wallet className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(totalPayroll / 1000000).toFixed(1)}M\n </div>\n <p className=\"text-xs text-text-secondary\">{employees.length} employees</p>\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\">Total Invoiced</CardTitle>\n <FileText className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(totalInvoiced / 1000).toFixed(1)}K\n </div>\n <p className=\"text-xs text-text-secondary\">\n ${(paidInvoices / 1000).toFixed(1)}K collected\n </p>\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\">Project Budget</CardTitle>\n <TrendingUp className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(totalProjectBudget / 1000000).toFixed(1)}M\n </div>\n <p className=\"text-xs text-text-secondary\">\n {Math.round((totalProjectSpent / totalProjectBudget) * 100)}% utilized\n </p>\n </CardContent>\n </GlassCard>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Payroll Trend</CardTitle>\n <CardDescription>Monthly gross payroll over the last 6 months</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {monthlyPayrollTrend.map((m) => (\n <div key={m.month} className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-text-secondary\">{m.month}</span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden flex\">\n <div\n className=\"h-5 bg-action-primary-bg\"\n style={{ width: `${Math.round((m.net / maxPayroll) * 100)}%` }}\n />\n <div\n className=\"h-5 bg-action-primary-bg/30\"\n style={{ width: `${Math.round((m.deductions / maxPayroll) * 100)}%` }}\n />\n </div>\n <span className=\"text-sm font-medium w-20 text-right\">\n ${(m.gross / 1000000).toFixed(2)}M\n </span>\n </div>\n ))}\n <div className=\"flex items-center gap-4 mt-2 text-xs text-text-secondary\">\n <div className=\"flex items-center gap-1\">\n <div className=\"h-3 w-3 bg-action-primary-bg rounded\" />\n <span>Net Pay</span>\n </div>\n <div className=\"flex items-center gap-1\">\n <div className=\"h-3 w-3 bg-action-primary-bg/30 rounded\" />\n <span>Deductions</span>\n </div>\n </div>\n </CardContent>\n </Card>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n <Card>\n <CardHeader>\n <CardTitle>Budget vs Actual</CardTitle>\n <CardDescription>Monthly expense tracking by category</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {expenseCategories.map((cat) => {\n const pct = Math.round((cat.amount / cat.budget) * 100);\n return (\n <div key={cat.category} className=\"space-y-1\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"font-medium\">{cat.category}</span>\n <span>\n ${(cat.amount / 1000).toFixed(0)}K / ${(cat.budget / 1000).toFixed(0)}K\n </span>\n </div>\n <div className=\"h-3 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-3 rounded ${pct > 95 ? 'bg-status-error-text' : pct > 80 ? 'bg-status-warning-text' : 'bg-status-success-text'}`}\n style={{ width: `${pct}%` }}\n />\n </div>\n <p className=\"text-xs text-text-secondary text-right\">{pct}% utilized</p>\n </div>\n );\n })}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Outstanding Invoices</CardTitle>\n <CardDescription>Invoices requiring attention</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {invoices.map((inv) => (\n <div key={inv.id} className=\"flex items-center justify-between rounded border p-3\">\n <div>\n <p className=\"text-sm font-medium\">{inv.number}</p>\n <p className=\"text-xs text-text-secondary\">{inv.clientName}</p>\n </div>\n <div className=\"text-right\">\n <p className=\"text-sm font-medium\">${inv.amount.toLocaleString()}</p>\n <Badge\n variant={\n inv.status === 'paid'\n ? 'default'\n : inv.status === 'overdue'\n ? 'destructive'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {inv.status}\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Department Cost Analysis</CardTitle>\n <CardDescription>Total salary cost and budget allocation by department</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-5 gap-2 text-xs font-medium text-text-secondary border-b pb-2 mb-2\">\n <span>Department</span>\n <span className=\"text-right\">Headcount</span>\n <span className=\"text-right\">Total Salary</span>\n <span className=\"text-right\">Dept Budget</span>\n <span className=\"text-right\">Salary/Budget %</span>\n </div>\n {deptCost\n .sort((a, b) => b.salary - a.salary)\n .map((d) => (\n <div\n key={d.name}\n className=\"grid grid-cols-5 gap-2 py-2 border-b last:border-0 text-sm\"\n >\n <span className=\"font-medium\">{d.name}</span>\n <span className=\"text-right\">{d.headcount}</span>\n <span className=\"text-right\">${(d.salary / 1000).toFixed(0)}K</span>\n <span className=\"text-right\">${(d.budget / 1000000).toFixed(1)}M</span>\n <span className=\"text-right\">\n <Badge\n variant={d.salary / d.budget > 0.5 ? 'destructive' : 'default'}\n className=\"text-[10px]\"\n >\n {Math.round((d.salary / d.budget) * 100)}%\n </Badge>\n </span>\n </div>\n ))}\n <Separator className=\"my-2\" />\n <div className=\"grid grid-cols-5 gap-2 text-sm font-bold\">\n <span>Total</span>\n <span className=\"text-right\">{employees.length}</span>\n <span className=\"text-right\">${(totalPayroll / 1000000).toFixed(1)}M</span>\n <span className=\"text-right\">\n ${(departments.reduce((s, d) => s + d.budget, 0) / 1000000).toFixed(1)}M\n </span>\n <span />\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -2,10 +2,10 @@ import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
2
  import { useMemo as t } from "react";
3
3
  import { Briefcase as n, Clock as r, Target as i, TrendingUp as a, Users as o } from "lucide-react";
4
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 } from "@burdenoff/fe-libs/ui";
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 _ } from "@burdenoff/fe-libs/ui";
6
6
  //#region src/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.tsx
7
- function _() {
8
- let { jobPostings: _, candidates: v, interviews: y } = e(), b = t(() => [
7
+ function v() {
8
+ let { jobPostings: v, candidates: y, interviews: b } = e(), x = t(() => [
9
9
  "Sep",
10
10
  "Oct",
11
11
  "Nov",
@@ -13,7 +13,7 @@ function _() {
13
13
  "Jan",
14
14
  "Feb"
15
15
  ].map((e, t) => {
16
- let n = y.filter((t) => new Date(t.date).toLocaleString("en-US", { month: "short" }) === e).length, r = v.filter((t) => new Date(t.appliedDate).toLocaleString("en-US", { month: "short" }) === e), i = r.filter((e) => e.status === "offer").length, a = r.filter((e) => e.status === "hired").length, o = r.length + _.reduce((e, t) => e + t.applicants, 0) / 6;
16
+ let n = b.filter((t) => new Date(t.date).toLocaleString("en-US", { month: "short" }) === e).length, r = y.filter((t) => new Date(t.appliedDate).toLocaleString("en-US", { month: "short" }) === e), i = r.filter((e) => e.status === "offer").length, a = r.filter((e) => e.status === "hired").length, o = r.length + v.reduce((e, t) => e + t.applicants, 0) / 6;
17
17
  return {
18
18
  month: e,
19
19
  applications: Math.round(o - t * 3),
@@ -22,11 +22,11 @@ function _() {
22
22
  hires: a
23
23
  };
24
24
  }), [
25
- v,
26
25
  y,
27
- _
28
- ]), x = t(() => {
29
- let e = v.reduce((e, t) => {
26
+ b,
27
+ v
28
+ ]), S = t(() => {
29
+ let e = y.reduce((e, t) => {
30
30
  let n = t.source || "Unknown", r = e[n] || {
31
31
  applications: 0,
32
32
  hires: 0
@@ -38,63 +38,71 @@ function _() {
38
38
  applications: t.applications,
39
39
  hires: t.hires,
40
40
  conversionRate: Number((t.hires / Math.max(t.applications, 1) * 100).toFixed(1)),
41
- costPerHire: Math.round(_.reduce((e, t) => e + t.salaryMin * .02, 0) / Math.max(t.hires, 1))
41
+ costPerHire: Math.round(v.reduce((e, t) => e + t.salaryMin * .02, 0) / Math.max(t.hires, 1))
42
42
  }));
43
- }, [v, _]), S = _.filter((e) => e.status === "active"), C = _.reduce((e, t) => e + t.applicants, 0), w = y.filter((e) => e.status === "scheduled").length, T = y.filter((e) => e.status === "completed").length, E = v.filter((e) => e.status === "offer").length, D = v.filter((e) => e.status === "hired").length, O = Math.max(1, ...b.map((e) => e.applications)), k = [
43
+ }, [y, v]), C = v.filter((e) => e.status === "active"), w = v.reduce((e, t) => e + t.applicants, 0), T = b.filter((e) => e.status === "scheduled").length, E = b.filter((e) => e.status === "completed").length, D = y.filter((e) => e.status === "offer").length, O = y.filter((e) => e.status === "hired").length, k = Math.max(1, ...x.map((e) => e.applications)), A = [
44
44
  {
45
45
  status: "New",
46
- count: v.filter((e) => e.status === "new").length,
46
+ count: y.filter((e) => e.status === "new").length,
47
47
  color: "bg-text-secondary"
48
48
  },
49
49
  {
50
50
  status: "Screening",
51
- count: v.filter((e) => e.status === "screening").length,
51
+ count: y.filter((e) => e.status === "screening").length,
52
52
  color: "bg-status-info-text"
53
53
  },
54
54
  {
55
55
  status: "Interview",
56
- count: v.filter((e) => e.status === "interview").length,
56
+ count: y.filter((e) => e.status === "interview").length,
57
57
  color: "bg-status-info-text"
58
58
  },
59
59
  {
60
60
  status: "Assessment",
61
- count: v.filter((e) => e.status === "assessment").length,
61
+ count: y.filter((e) => e.status === "assessment").length,
62
62
  color: "bg-action-primary-bg"
63
63
  },
64
64
  {
65
65
  status: "Offer",
66
- count: E,
66
+ count: D,
67
67
  color: "bg-status-warning-text"
68
68
  },
69
69
  {
70
70
  status: "Hired",
71
- count: D,
71
+ count: O,
72
72
  color: "bg-status-success-text"
73
73
  },
74
74
  {
75
75
  status: "Rejected",
76
- count: v.filter((e) => e.status === "rejected").length,
76
+ count: y.filter((e) => e.status === "rejected").length,
77
77
  color: "bg-status-error-text"
78
78
  }
79
- ], A = k.reduce((e, t) => e + t.count, 0);
79
+ ], j = A.reduce((e, t) => e + t.count, 0);
80
80
  return /* @__PURE__ */ c("div", {
81
81
  className: "space-y-6 p-6",
82
82
  children: [
83
83
  /* @__PURE__ */ s("div", {
84
84
  className: "flex items-center justify-between",
85
- children: /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("h1", {
86
- className: "text-2xl font-semibold",
87
- children: /* @__PURE__ */ s(g, { children: "Hiring Analytics" })
88
- }), /* @__PURE__ */ s("p", {
89
- className: "text-sm text-text-secondary",
90
- children: "Recruitment performance and pipeline analysis"
91
- })] })
85
+ children: /* @__PURE__ */ c("div", { children: [
86
+ /* @__PURE__ */ s("h1", {
87
+ className: "text-2xl font-semibold",
88
+ children: /* @__PURE__ */ s(g, { children: "Hiring Analytics" })
89
+ }),
90
+ /* @__PURE__ */ s("p", {
91
+ className: "text-sm text-text-secondary",
92
+ children: "Recruitment performance and pipeline analysis"
93
+ }),
94
+ /* @__PURE__ */ s(_, {
95
+ className: "mt-1",
96
+ children: "Measure how your hiring funnel performs — applications, time-to-hire, and source quality — to make recruiting faster and more effective."
97
+ })
98
+ ] })
92
99
  }),
93
100
  /* @__PURE__ */ c("div", {
94
101
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
95
102
  children: [
96
103
  /* @__PURE__ */ c(h, {
97
- treatment: "metric",
104
+ treatment: "glass",
105
+ glow: !0,
98
106
  className: "border-border-seam",
99
107
  children: [/* @__PURE__ */ c(p, {
100
108
  className: "flex flex-row items-center justify-between space-y-0 pb-2",
@@ -104,10 +112,10 @@ function _() {
104
112
  }), /* @__PURE__ */ s(n, { className: "h-4 w-4 text-text-secondary" })]
105
113
  }), /* @__PURE__ */ c(d, { children: [/* @__PURE__ */ s("div", {
106
114
  className: "text-2xl font-bold tabular-nums",
107
- children: S.length
115
+ children: C.length
108
116
  }), /* @__PURE__ */ c("p", {
109
117
  className: "text-xs text-text-secondary",
110
- children: [C, " total applicants"]
118
+ children: [w, " total applicants"]
111
119
  })] })]
112
120
  }),
113
121
  /* @__PURE__ */ c(h, {
@@ -142,9 +150,9 @@ function _() {
142
150
  }), /* @__PURE__ */ c("p", {
143
151
  className: "text-xs text-text-secondary",
144
152
  children: [
145
- w,
146
- " scheduled, ",
147
153
  T,
154
+ " scheduled, ",
155
+ E,
148
156
  " completed"
149
157
  ]
150
158
  })] })]
@@ -163,7 +171,7 @@ function _() {
163
171
  children: "87%"
164
172
  }), /* @__PURE__ */ c("p", {
165
173
  className: "text-xs text-text-secondary",
166
- children: [D, " hired this quarter"]
174
+ children: [O, " hired this quarter"]
167
175
  })] })]
168
176
  })
169
177
  ]
@@ -174,7 +182,7 @@ function _() {
174
182
  className: "col-span-4",
175
183
  children: [/* @__PURE__ */ c(p, { children: [/* @__PURE__ */ s(m, { children: "Monthly Hiring Activity" }), /* @__PURE__ */ s(f, { children: "Applications, interviews, and hires over time" })] }), /* @__PURE__ */ s(d, {
176
184
  className: "space-y-3",
177
- children: b.map((e) => /* @__PURE__ */ c("div", {
185
+ children: x.map((e) => /* @__PURE__ */ c("div", {
178
186
  className: "flex items-center gap-3",
179
187
  children: [
180
188
  /* @__PURE__ */ s("span", {
@@ -185,7 +193,7 @@ function _() {
185
193
  className: "flex-1 h-5 bg-bg-sunken rounded overflow-hidden",
186
194
  children: /* @__PURE__ */ s("div", {
187
195
  className: "h-5 bg-action-primary-bg rounded",
188
- style: { width: `${Math.round(e.applications / (O + 20) * 100)}%` }
196
+ style: { width: `${Math.round(e.applications / (k + 20) * 100)}%` }
189
197
  })
190
198
  }),
191
199
  /* @__PURE__ */ c("div", {
@@ -215,7 +223,7 @@ function _() {
215
223
  className: "col-span-3",
216
224
  children: [/* @__PURE__ */ c(p, { children: [/* @__PURE__ */ s(m, { children: "Pipeline Status" }), /* @__PURE__ */ s(f, { children: "Current candidate distribution" })] }), /* @__PURE__ */ s(d, {
217
225
  className: "space-y-3",
218
- children: k.map((e) => /* @__PURE__ */ c("div", {
226
+ children: A.map((e) => /* @__PURE__ */ c("div", {
219
227
  className: "flex items-center gap-3",
220
228
  children: [
221
229
  /* @__PURE__ */ s("div", { className: `h-3 w-3 rounded-full ${e.color}` }),
@@ -227,7 +235,7 @@ function _() {
227
235
  className: "flex-1 h-3 bg-bg-sunken rounded overflow-hidden",
228
236
  children: /* @__PURE__ */ s("div", {
229
237
  className: `h-3 rounded ${e.color}`,
230
- style: { width: `${A > 0 ? Math.max(Math.round(e.count / A * 100), 3) : 3}%` }
238
+ style: { width: `${j > 0 ? Math.max(Math.round(e.count / j * 100), 3) : 3}%` }
231
239
  })
232
240
  }),
233
241
  /* @__PURE__ */ s("span", {
@@ -260,7 +268,7 @@ function _() {
260
268
  children: "Cost/Hire"
261
269
  })
262
270
  ]
263
- }), x.sort((e, t) => t.conversionRate - e.conversionRate).map((e) => /* @__PURE__ */ c("div", {
271
+ }), S.sort((e, t) => t.conversionRate - e.conversionRate).map((e) => /* @__PURE__ */ c("div", {
264
272
  className: "grid grid-cols-5 gap-2 py-2 border-b last:border-0 text-sm",
265
273
  children: [
266
274
  /* @__PURE__ */ s("span", {
@@ -308,7 +316,7 @@ function _() {
308
316
  children: "Status"
309
317
  })
310
318
  ]
311
- }), _.map((e) => /* @__PURE__ */ c("div", {
319
+ }), v.map((e) => /* @__PURE__ */ c("div", {
312
320
  className: "grid grid-cols-6 gap-2 py-2 border-b last:border-0 text-sm",
313
321
  children: [
314
322
  /* @__PURE__ */ s("span", {
@@ -352,6 +360,6 @@ function _() {
352
360
  });
353
361
  }
354
362
  //#endregion
355
- export { _ as AnalyticsHiringAnalyticsPagePage };
363
+ export { v as AnalyticsHiringAnalyticsPagePage };
356
364
 
357
365
  //# sourceMappingURL=AnalyticsHiringAnalyticsPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsHiringAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n} from '@burdenoff/fe-libs/ui';\nimport { Briefcase, Clock, Target, TrendingUp, Users } from 'lucide-react';\nimport { useMemo } from 'react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function AnalyticsHiringAnalyticsPagePage() {\n const { jobPostings, candidates, interviews } = useCrewFoundryStore();\n\n const hiringMetrics = useMemo(() => {\n const months = ['Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb'];\n return months.map((month, index) => {\n const monthInterviews = interviews.filter(\n (interview) =>\n new Date(interview.date).toLocaleString('en-US', { month: 'short' }) === month\n ).length;\n const monthCandidates = candidates.filter(\n (candidate) =>\n new Date(candidate.appliedDate).toLocaleString('en-US', { month: 'short' }) === month\n );\n const offers = monthCandidates.filter((candidate) => candidate.status === 'offer').length;\n const hires = monthCandidates.filter((candidate) => candidate.status === 'hired').length;\n const applications =\n monthCandidates.length +\n jobPostings.reduce((sum, posting) => sum + posting.applicants, 0) / 6;\n return {\n month,\n applications: Math.round(applications - index * 3),\n interviews: monthInterviews,\n offers,\n hires,\n };\n });\n }, [candidates, interviews, jobPostings]);\n\n const sourceEffectiveness = useMemo(() => {\n const grouped = candidates.reduce<Record<string, { applications: number; hires: number }>>(\n (acc, candidate) => {\n const source = candidate.source || 'Unknown';\n const value = acc[source] || { applications: 0, hires: 0 };\n value.applications += 1;\n if (candidate.status === 'hired') {\n value.hires += 1;\n }\n acc[source] = value;\n return acc;\n },\n {}\n );\n\n return Object.entries(grouped).map(([source, value]) => ({\n source,\n applications: value.applications,\n hires: value.hires,\n conversionRate: Number(((value.hires / Math.max(value.applications, 1)) * 100).toFixed(1)),\n costPerHire: Math.round(\n jobPostings.reduce((sum, posting) => sum + posting.salaryMin * 0.02, 0) /\n Math.max(value.hires, 1)\n ),\n }));\n }, [candidates, jobPostings]);\n\n const activeJobs = jobPostings.filter((j) => j.status === 'active');\n const totalApplicants = jobPostings.reduce((s, j) => s + j.applicants, 0);\n const scheduledInterviews = interviews.filter((i) => i.status === 'scheduled').length;\n const completedInterviews = interviews.filter((i) => i.status === 'completed').length;\n const offeredCandidates = candidates.filter((c) => c.status === 'offer').length;\n const hiredCandidates = candidates.filter((c) => c.status === 'hired').length;\n\n const maxApplications = Math.max(1, ...hiringMetrics.map((m) => m.applications));\n\n const statusPipeline = [\n {\n status: 'New',\n count: candidates.filter((c) => c.status === 'new').length,\n color: 'bg-text-secondary',\n },\n {\n status: 'Screening',\n count: candidates.filter((c) => c.status === 'screening').length,\n color: 'bg-status-info-text',\n },\n {\n status: 'Interview',\n count: candidates.filter((c) => c.status === 'interview').length,\n color: 'bg-status-info-text',\n },\n {\n status: 'Assessment',\n count: candidates.filter((c) => c.status === 'assessment').length,\n color: 'bg-action-primary-bg',\n },\n { status: 'Offer', count: offeredCandidates, color: 'bg-status-warning-text' },\n { status: 'Hired', count: hiredCandidates, color: 'bg-status-success-text' },\n {\n status: 'Rejected',\n count: candidates.filter((c) => c.status === 'rejected').length,\n color: 'bg-status-error-text',\n },\n ];\n const totalPipeline = statusPipeline.reduce((s, p) => s + p.count, 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>Hiring Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Recruitment performance and pipeline analysis\n </p>\n </div>\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\">Active Postings</CardTitle>\n <Briefcase className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activeJobs.length}</div>\n <p className=\"text-xs text-text-secondary\">{totalApplicants} total applicants</p>\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\">Time to Fill</CardTitle>\n <Clock className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">28 days</div>\n <div className=\"flex items-center text-xs text-status-success-text\">\n <TrendingUp className=\"h-3 w-3 mr-1\" />\n -3 days from last quarter\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\">Interview to Offer</CardTitle>\n <Target className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">32%</div>\n <p className=\"text-xs text-text-secondary\">\n {scheduledInterviews} scheduled, {completedInterviews} completed\n </p>\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\">Offer Acceptance</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">87%</div>\n <p className=\"text-xs text-text-secondary\">{hiredCandidates} hired this quarter</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>Monthly Hiring Activity</CardTitle>\n <CardDescription>Applications, interviews, and hires over time</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {hiringMetrics.map((m) => (\n <div key={m.month} className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-text-secondary\">{m.month}</span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-5 bg-action-primary-bg rounded\"\n style={{\n width: `${Math.round((m.applications / (maxApplications + 20)) * 100)}%`,\n }}\n />\n </div>\n <div className=\"flex gap-1 w-48 justify-end\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {m.applications} apps\n </Badge>\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n {m.interviews} int\n </Badge>\n <Badge variant=\"default\" className=\"text-[10px]\">\n {m.hires} hired\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card className=\"col-span-3\">\n <CardHeader>\n <CardTitle>Pipeline Status</CardTitle>\n <CardDescription>Current candidate distribution</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {statusPipeline.map((stage) => (\n <div key={stage.status} className=\"flex items-center gap-3\">\n <div className={`h-3 w-3 rounded-full ${stage.color}`} />\n <span className=\"w-20 text-sm\">{stage.status}</span>\n <div className=\"flex-1 h-3 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-3 rounded ${stage.color}`}\n style={{\n width: `${totalPipeline > 0 ? Math.max(Math.round((stage.count / totalPipeline) * 100), 3) : 3}%`,\n }}\n />\n </div>\n <span className=\"text-sm font-medium w-6 text-right\">{stage.count}</span>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Source Effectiveness</CardTitle>\n <CardDescription>Recruitment channel performance comparison</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-5 gap-2 text-xs font-medium text-text-secondary border-b pb-2 mb-2\">\n <span>Source</span>\n <span className=\"text-right\">Applications</span>\n <span className=\"text-right\">Hires</span>\n <span className=\"text-right\">Conversion</span>\n <span className=\"text-right\">Cost/Hire</span>\n </div>\n {sourceEffectiveness\n .sort((a, b) => b.conversionRate - a.conversionRate)\n .map((src) => (\n <div\n key={src.source}\n className=\"grid grid-cols-5 gap-2 py-2 border-b last:border-0 text-sm\"\n >\n <span className=\"font-medium\">{src.source}</span>\n <span className=\"text-right\">{src.applications}</span>\n <span className=\"text-right\">{src.hires}</span>\n <span className=\"text-right\">\n <Badge\n variant={src.conversionRate >= 5 ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {src.conversionRate}%\n </Badge>\n </span>\n <span className=\"text-right\">${src.costPerHire.toLocaleString()}</span>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Open Positions Detail</CardTitle>\n <CardDescription>Active job postings and applicant counts</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>Position</span>\n <span>Department</span>\n <span>Level</span>\n <span className=\"text-right\">Applicants</span>\n <span className=\"text-right\">Salary Range</span>\n <span className=\"text-right\">Status</span>\n </div>\n {jobPostings.map((job) => (\n <div\n key={job.id}\n className=\"grid grid-cols-6 gap-2 py-2 border-b last:border-0 text-sm\"\n >\n <span className=\"font-medium truncate\">{job.title}</span>\n <span className=\"text-text-secondary\">{job.department}</span>\n <Badge variant=\"outline\" className=\"w-fit text-[10px]\">\n {job.experienceLevel}\n </Badge>\n <span className=\"text-right\">{job.applicants}</span>\n <span className=\"text-right text-text-secondary\">\n ${(job.salaryMin / 1000).toFixed(0)}K-${(job.salaryMax / 1000).toFixed(0)}K\n </span>\n <div className=\"text-right\">\n <Badge\n variant={job.status === 'active' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {job.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":"AnalyticsHiringAnalyticsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.tsx"],"sourcesContent":["import {\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 { Briefcase, Clock, Target, TrendingUp, Users } from 'lucide-react';\nimport { useMemo } from 'react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function AnalyticsHiringAnalyticsPagePage() {\n const { jobPostings, candidates, interviews } = useCrewFoundryStore();\n\n const hiringMetrics = useMemo(() => {\n const months = ['Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb'];\n return months.map((month, index) => {\n const monthInterviews = interviews.filter(\n (interview) =>\n new Date(interview.date).toLocaleString('en-US', { month: 'short' }) === month\n ).length;\n const monthCandidates = candidates.filter(\n (candidate) =>\n new Date(candidate.appliedDate).toLocaleString('en-US', { month: 'short' }) === month\n );\n const offers = monthCandidates.filter((candidate) => candidate.status === 'offer').length;\n const hires = monthCandidates.filter((candidate) => candidate.status === 'hired').length;\n const applications =\n monthCandidates.length +\n jobPostings.reduce((sum, posting) => sum + posting.applicants, 0) / 6;\n return {\n month,\n applications: Math.round(applications - index * 3),\n interviews: monthInterviews,\n offers,\n hires,\n };\n });\n }, [candidates, interviews, jobPostings]);\n\n const sourceEffectiveness = useMemo(() => {\n const grouped = candidates.reduce<Record<string, { applications: number; hires: number }>>(\n (acc, candidate) => {\n const source = candidate.source || 'Unknown';\n const value = acc[source] || { applications: 0, hires: 0 };\n value.applications += 1;\n if (candidate.status === 'hired') {\n value.hires += 1;\n }\n acc[source] = value;\n return acc;\n },\n {}\n );\n\n return Object.entries(grouped).map(([source, value]) => ({\n source,\n applications: value.applications,\n hires: value.hires,\n conversionRate: Number(((value.hires / Math.max(value.applications, 1)) * 100).toFixed(1)),\n costPerHire: Math.round(\n jobPostings.reduce((sum, posting) => sum + posting.salaryMin * 0.02, 0) /\n Math.max(value.hires, 1)\n ),\n }));\n }, [candidates, jobPostings]);\n\n const activeJobs = jobPostings.filter((j) => j.status === 'active');\n const totalApplicants = jobPostings.reduce((s, j) => s + j.applicants, 0);\n const scheduledInterviews = interviews.filter((i) => i.status === 'scheduled').length;\n const completedInterviews = interviews.filter((i) => i.status === 'completed').length;\n const offeredCandidates = candidates.filter((c) => c.status === 'offer').length;\n const hiredCandidates = candidates.filter((c) => c.status === 'hired').length;\n\n const maxApplications = Math.max(1, ...hiringMetrics.map((m) => m.applications));\n\n const statusPipeline = [\n {\n status: 'New',\n count: candidates.filter((c) => c.status === 'new').length,\n color: 'bg-text-secondary',\n },\n {\n status: 'Screening',\n count: candidates.filter((c) => c.status === 'screening').length,\n color: 'bg-status-info-text',\n },\n {\n status: 'Interview',\n count: candidates.filter((c) => c.status === 'interview').length,\n color: 'bg-status-info-text',\n },\n {\n status: 'Assessment',\n count: candidates.filter((c) => c.status === 'assessment').length,\n color: 'bg-action-primary-bg',\n },\n { status: 'Offer', count: offeredCandidates, color: 'bg-status-warning-text' },\n { status: 'Hired', count: hiredCandidates, color: 'bg-status-success-text' },\n {\n status: 'Rejected',\n count: candidates.filter((c) => c.status === 'rejected').length,\n color: 'bg-status-error-text',\n },\n ];\n const totalPipeline = statusPipeline.reduce((s, p) => s + p.count, 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>Hiring Analytics</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n Recruitment performance and pipeline analysis\n </p>\n <PagePurpose className=\"mt-1\">Measure how your hiring funnel performs — applications, time-to-hire, and source quality — to make recruiting faster and more effective.</PagePurpose>\n </div>\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\">Active Postings</CardTitle>\n <Briefcase className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activeJobs.length}</div>\n <p className=\"text-xs text-text-secondary\">{totalApplicants} total applicants</p>\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\">Time to Fill</CardTitle>\n <Clock className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">28 days</div>\n <div className=\"flex items-center text-xs text-status-success-text\">\n <TrendingUp className=\"h-3 w-3 mr-1\" />\n -3 days from last quarter\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\">Interview to Offer</CardTitle>\n <Target className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">32%</div>\n <p className=\"text-xs text-text-secondary\">\n {scheduledInterviews} scheduled, {completedInterviews} completed\n </p>\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\">Offer Acceptance</CardTitle>\n <Users className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">87%</div>\n <p className=\"text-xs text-text-secondary\">{hiredCandidates} hired this quarter</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>Monthly Hiring Activity</CardTitle>\n <CardDescription>Applications, interviews, and hires over time</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {hiringMetrics.map((m) => (\n <div key={m.month} className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-text-secondary\">{m.month}</span>\n <div className=\"flex-1 h-5 bg-bg-sunken rounded overflow-hidden\">\n <div\n className=\"h-5 bg-action-primary-bg rounded\"\n style={{\n width: `${Math.round((m.applications / (maxApplications + 20)) * 100)}%`,\n }}\n />\n </div>\n <div className=\"flex gap-1 w-48 justify-end\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {m.applications} apps\n </Badge>\n <Badge variant=\"secondary\" className=\"text-[10px]\">\n {m.interviews} int\n </Badge>\n <Badge variant=\"default\" className=\"text-[10px]\">\n {m.hires} hired\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card className=\"col-span-3\">\n <CardHeader>\n <CardTitle>Pipeline Status</CardTitle>\n <CardDescription>Current candidate distribution</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {statusPipeline.map((stage) => (\n <div key={stage.status} className=\"flex items-center gap-3\">\n <div className={`h-3 w-3 rounded-full ${stage.color}`} />\n <span className=\"w-20 text-sm\">{stage.status}</span>\n <div className=\"flex-1 h-3 bg-bg-sunken rounded overflow-hidden\">\n <div\n className={`h-3 rounded ${stage.color}`}\n style={{\n width: `${totalPipeline > 0 ? Math.max(Math.round((stage.count / totalPipeline) * 100), 3) : 3}%`,\n }}\n />\n </div>\n <span className=\"text-sm font-medium w-6 text-right\">{stage.count}</span>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Source Effectiveness</CardTitle>\n <CardDescription>Recruitment channel performance comparison</CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-5 gap-2 text-xs font-medium text-text-secondary border-b pb-2 mb-2\">\n <span>Source</span>\n <span className=\"text-right\">Applications</span>\n <span className=\"text-right\">Hires</span>\n <span className=\"text-right\">Conversion</span>\n <span className=\"text-right\">Cost/Hire</span>\n </div>\n {sourceEffectiveness\n .sort((a, b) => b.conversionRate - a.conversionRate)\n .map((src) => (\n <div\n key={src.source}\n className=\"grid grid-cols-5 gap-2 py-2 border-b last:border-0 text-sm\"\n >\n <span className=\"font-medium\">{src.source}</span>\n <span className=\"text-right\">{src.applications}</span>\n <span className=\"text-right\">{src.hires}</span>\n <span className=\"text-right\">\n <Badge\n variant={src.conversionRate >= 5 ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {src.conversionRate}%\n </Badge>\n </span>\n <span className=\"text-right\">${src.costPerHire.toLocaleString()}</span>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <Card>\n <CardHeader>\n <CardTitle>Open Positions Detail</CardTitle>\n <CardDescription>Active job postings and applicant counts</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>Position</span>\n <span>Department</span>\n <span>Level</span>\n <span className=\"text-right\">Applicants</span>\n <span className=\"text-right\">Salary Range</span>\n <span className=\"text-right\">Status</span>\n </div>\n {jobPostings.map((job) => (\n <div\n key={job.id}\n className=\"grid grid-cols-6 gap-2 py-2 border-b last:border-0 text-sm\"\n >\n <span className=\"font-medium truncate\">{job.title}</span>\n <span className=\"text-text-secondary\">{job.department}</span>\n <Badge variant=\"outline\" className=\"w-fit text-[10px]\">\n {job.experienceLevel}\n </Badge>\n <span className=\"text-right\">{job.applicants}</span>\n <span className=\"text-right text-text-secondary\">\n ${(job.salaryMin / 1000).toFixed(0)}K-${(job.salaryMax / 1000).toFixed(0)}K\n </span>\n <div className=\"text-right\">\n <Badge\n variant={job.status === 'active' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {job.status}\n </Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,33 +1,41 @@
1
1
  import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
2
2
  import { Eye as t, Pin as n, Plus 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, Card as c, CardContent as l, CardHeader as u, CardTitle as d, GlassCard as f, GradientText as p, IllustratedEmptyState as m, PagePurpose as h } from "@burdenoff/fe-libs/ui";
5
5
  //#region src/crewfoundry/pages/CommunicationsAnnouncementsPagePage.tsx
6
- function p() {
7
- let { announcements: p } = e(), m = p.filter((e) => e.isPinned), h = p.filter((e) => !e.isPinned);
6
+ function g() {
7
+ let { announcements: g } = e(), _ = g.filter((e) => e.isPinned), v = g.filter((e) => !e.isPinned);
8
8
  return /* @__PURE__ */ a("div", {
9
9
  className: "space-y-6 p-6",
10
10
  children: [
11
11
  /* @__PURE__ */ a("div", {
12
12
  className: "flex items-center justify-between",
13
- children: [/* @__PURE__ */ a("div", { children: [/* @__PURE__ */ i("h1", {
14
- className: "text-2xl font-semibold",
15
- children: /* @__PURE__ */ i(f, { children: "Announcements" })
16
- }), /* @__PURE__ */ a("p", {
17
- className: "text-sm text-text-secondary",
18
- children: [p.length, " company announcements"]
19
- })] }), /* @__PURE__ */ a(s, {
13
+ children: [/* @__PURE__ */ a("div", { children: [
14
+ /* @__PURE__ */ i("h1", {
15
+ className: "text-2xl font-semibold",
16
+ children: /* @__PURE__ */ i(p, { children: "Announcements" })
17
+ }),
18
+ /* @__PURE__ */ a("p", {
19
+ className: "text-sm text-text-secondary",
20
+ children: [g.length, " company announcements"]
21
+ }),
22
+ /* @__PURE__ */ i(h, {
23
+ className: "mt-1",
24
+ children: "Broadcast company-wide news and updates so everyone stays informed — post announcements here when you have something the whole team needs to see."
25
+ })
26
+ ] }), /* @__PURE__ */ a(s, {
20
27
  size: "sm",
21
28
  children: [/* @__PURE__ */ i(r, { className: "h-4 w-4 mr-1" }), "New Announcement"]
22
29
  })]
23
30
  }),
24
- m.length > 0 && /* @__PURE__ */ a("div", {
31
+ _.length > 0 && /* @__PURE__ */ a("div", {
25
32
  className: "space-y-3",
26
33
  children: [/* @__PURE__ */ a("h2", {
27
34
  className: "text-sm font-medium flex items-center gap-1",
28
35
  children: [/* @__PURE__ */ i(n, { className: "h-4 w-4" }), "Pinned"]
29
- }), m.map((e) => /* @__PURE__ */ a(c, {
30
- className: "border-status-warning-text/30 bg-status-warning-bg/30",
36
+ }), _.map((e) => /* @__PURE__ */ a(f, {
37
+ treatment: "glass",
38
+ glow: !0,
31
39
  children: [/* @__PURE__ */ i(u, { children: /* @__PURE__ */ a("div", {
32
40
  className: "flex items-center justify-between",
33
41
  children: [/* @__PURE__ */ i(d, {
@@ -64,9 +72,14 @@ function p() {
64
72
  })] })]
65
73
  }, e.id))]
66
74
  }),
75
+ g.length === 0 && /* @__PURE__ */ i(m, {
76
+ illustration: "empty-notifications",
77
+ title: "No announcements yet",
78
+ description: "Post an announcement to share news with the whole team."
79
+ }),
67
80
  /* @__PURE__ */ i("div", {
68
81
  className: "space-y-3",
69
- children: h.map((e) => /* @__PURE__ */ a(c, { children: [/* @__PURE__ */ i(u, { children: /* @__PURE__ */ a("div", {
82
+ children: v.map((e) => /* @__PURE__ */ a(c, { children: [/* @__PURE__ */ i(u, { children: /* @__PURE__ */ a("div", {
70
83
  className: "flex items-center justify-between",
71
84
  children: [/* @__PURE__ */ i(d, {
72
85
  className: "text-base",
@@ -116,6 +129,6 @@ function p() {
116
129
  });
117
130
  }
118
131
  //#endregion
119
- export { p as CommunicationsAnnouncementsPagePage };
132
+ export { g as CommunicationsAnnouncementsPagePage };
120
133
 
121
134
  //# sourceMappingURL=CommunicationsAnnouncementsPagePage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CommunicationsAnnouncementsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CommunicationsAnnouncementsPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GradientText,\n} from '@burdenoff/fe-libs/ui';\nimport { Eye, Megaphone, Pin, Plus } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function CommunicationsAnnouncementsPagePage() {\n const { announcements } = useCrewFoundryStore();\n const pinned = announcements.filter((a) => a.isPinned);\n const regular = announcements.filter((a) => !a.isPinned);\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>Announcements</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {announcements.length} company announcements\n </p>\n </div>\n <Button size=\"sm\">\n <Plus className=\"h-4 w-4 mr-1\" />\n New Announcement\n </Button>\n </div>\n {pinned.length > 0 && (\n <div className=\"space-y-3\">\n <h2 className=\"text-sm font-medium flex items-center gap-1\">\n <Pin className=\"h-4 w-4\" />\n Pinned\n </h2>\n {pinned.map((ann) => (\n <Card key={ann.id} className=\"border-status-warning-text/30 bg-status-warning-bg/30\">\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{ann.title}</CardTitle>\n <div className=\"flex gap-1\">\n <Badge\n variant={\n ann.priority === 'urgent'\n ? 'destructive'\n : ann.priority === 'high'\n ? 'default'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {ann.priority}\n </Badge>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {ann.category}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-text-secondary\">{ann.content}</p>\n <div className=\"flex items-center justify-between mt-3 text-xs text-text-secondary\">\n <span>\n {ann.author} · {ann.authorRole}\n </span>\n <div className=\"flex items-center gap-3\">\n <span className=\"flex items-center gap-1\">\n <Eye className=\"h-3 w-3\" />\n {ann.viewCount}\n </span>\n <span>{ann.createdAt}</span>\n </div>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )}\n <div className=\"space-y-3\">\n {regular.map((ann) => (\n <Card key={ann.id}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{ann.title}</CardTitle>\n <div className=\"flex gap-1\">\n <Badge\n variant={\n ann.priority === 'urgent'\n ? 'destructive'\n : ann.priority === 'high'\n ? 'default'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {ann.priority}\n </Badge>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {ann.category}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-text-secondary\">{ann.content}</p>\n <div className=\"flex items-center justify-between mt-3 text-xs text-text-secondary\">\n <span>\n {ann.author} · {ann.authorRole}\n </span>\n <div className=\"flex items-center gap-3\">\n <span className=\"flex items-center gap-1\">\n <Eye className=\"h-3 w-3\" />\n {ann.viewCount}\n </span>\n <span>{ann.createdAt}</span>\n </div>\n </div>\n <div className=\"flex gap-1 mt-2\">\n {ann.tags.map((t) => (\n <Badge key={t} variant=\"outline\" className=\"text-[9px]\">\n {t}\n </Badge>\n ))}\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CommunicationsAnnouncementsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CommunicationsAnnouncementsPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Eye, Pin, Plus } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function CommunicationsAnnouncementsPagePage() {\n const { announcements } = useCrewFoundryStore();\n const pinned = announcements.filter((a) => a.isPinned);\n const regular = announcements.filter((a) => !a.isPinned);\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>Announcements</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {announcements.length} company announcements\n </p>\n <PagePurpose className=\"mt-1\">Broadcast company-wide news and updates so everyone stays informed — post announcements here when you have something the whole team needs to see.</PagePurpose>\n </div>\n <Button size=\"sm\">\n <Plus className=\"h-4 w-4 mr-1\" />\n New Announcement\n </Button>\n </div>\n {pinned.length > 0 && (\n <div className=\"space-y-3\">\n <h2 className=\"text-sm font-medium flex items-center gap-1\">\n <Pin className=\"h-4 w-4\" />\n Pinned\n </h2>\n {pinned.map((ann) => (\n <GlassCard key={ann.id} treatment=\"glass\" glow>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{ann.title}</CardTitle>\n <div className=\"flex gap-1\">\n <Badge\n variant={\n ann.priority === 'urgent'\n ? 'destructive'\n : ann.priority === 'high'\n ? 'default'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {ann.priority}\n </Badge>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {ann.category}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-text-secondary\">{ann.content}</p>\n <div className=\"flex items-center justify-between mt-3 text-xs text-text-secondary\">\n <span>\n {ann.author} · {ann.authorRole}\n </span>\n <div className=\"flex items-center gap-3\">\n <span className=\"flex items-center gap-1\">\n <Eye className=\"h-3 w-3\" />\n {ann.viewCount}\n </span>\n <span>{ann.createdAt}</span>\n </div>\n </div>\n </CardContent>\n </GlassCard>\n ))}\n </div>\n )}\n {announcements.length === 0 && (\n <IllustratedEmptyState\n illustration=\"empty-notifications\"\n title=\"No announcements yet\"\n description=\"Post an announcement to share news with the whole team.\"\n />\n )}\n <div className=\"space-y-3\">\n {regular.map((ann) => (\n <Card key={ann.id}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{ann.title}</CardTitle>\n <div className=\"flex gap-1\">\n <Badge\n variant={\n ann.priority === 'urgent'\n ? 'destructive'\n : ann.priority === 'high'\n ? 'default'\n : 'secondary'\n }\n className=\"text-[10px]\"\n >\n {ann.priority}\n </Badge>\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {ann.category}\n </Badge>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <p className=\"text-sm text-text-secondary\">{ann.content}</p>\n <div className=\"flex items-center justify-between mt-3 text-xs text-text-secondary\">\n <span>\n {ann.author} · {ann.authorRole}\n </span>\n <div className=\"flex items-center gap-3\">\n <span className=\"flex items-center gap-1\">\n <Eye className=\"h-3 w-3\" />\n {ann.viewCount}\n </span>\n <span>{ann.createdAt}</span>\n </div>\n </div>\n <div className=\"flex gap-1 mt-2\">\n {ann.tags.map((t) => (\n <Badge key={t} variant=\"outline\" className=\"text-[9px]\">\n {t}\n </Badge>\n ))}\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}