@burdenoff/microfe-crewfoundry 2026.704.6 → 2026.704.7

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 (148) hide show
  1. package/dist/crewfoundry/CrewFoundryRoutes.js +51 -43
  2. package/dist/crewfoundry/CrewFoundryRoutes.js.map +1 -1
  3. package/dist/crewfoundry/components/forms/formValues.js +5 -2
  4. package/dist/crewfoundry/components/forms/formValues.js.map +1 -1
  5. package/dist/crewfoundry/components/viz/AllocationBar.js +68 -0
  6. package/dist/crewfoundry/components/viz/AllocationBar.js.map +1 -0
  7. package/dist/crewfoundry/components/viz/AreaChart.js +102 -0
  8. package/dist/crewfoundry/components/viz/AreaChart.js.map +1 -0
  9. package/dist/crewfoundry/components/viz/AvatarStack.js +36 -0
  10. package/dist/crewfoundry/components/viz/AvatarStack.js.map +1 -0
  11. package/dist/crewfoundry/components/viz/BarChart.js +83 -0
  12. package/dist/crewfoundry/components/viz/BarChart.js.map +1 -0
  13. package/dist/crewfoundry/components/viz/CertificateCard.js +118 -0
  14. package/dist/crewfoundry/components/viz/CertificateCard.js.map +1 -0
  15. package/dist/crewfoundry/components/viz/DonutChart.js +109 -0
  16. package/dist/crewfoundry/components/viz/DonutChart.js.map +1 -0
  17. package/dist/crewfoundry/components/viz/HBarFunnel.js +54 -0
  18. package/dist/crewfoundry/components/viz/HBarFunnel.js.map +1 -0
  19. package/dist/crewfoundry/components/viz/Heatmap.js +91 -0
  20. package/dist/crewfoundry/components/viz/Heatmap.js.map +1 -0
  21. package/dist/crewfoundry/components/viz/KanbanBoard.js +50 -0
  22. package/dist/crewfoundry/components/viz/KanbanBoard.js.map +1 -0
  23. package/dist/crewfoundry/components/viz/LineChart.js +123 -0
  24. package/dist/crewfoundry/components/viz/LineChart.js.map +1 -0
  25. package/dist/crewfoundry/components/viz/OrgTree.js +83 -0
  26. package/dist/crewfoundry/components/viz/OrgTree.js.map +1 -0
  27. package/dist/crewfoundry/components/viz/PathSteps.js +68 -0
  28. package/dist/crewfoundry/components/viz/PathSteps.js.map +1 -0
  29. package/dist/crewfoundry/components/viz/ProgressRing.js +68 -0
  30. package/dist/crewfoundry/components/viz/ProgressRing.js.map +1 -0
  31. package/dist/crewfoundry/components/viz/RatingStars.js +51 -0
  32. package/dist/crewfoundry/components/viz/RatingStars.js.map +1 -0
  33. package/dist/crewfoundry/components/viz/SegmentedTabs.js +69 -0
  34. package/dist/crewfoundry/components/viz/SegmentedTabs.js.map +1 -0
  35. package/dist/crewfoundry/components/viz/SkillBar.js +3 -0
  36. package/dist/crewfoundry/components/viz/Sparkline.js +74 -0
  37. package/dist/crewfoundry/components/viz/Sparkline.js.map +1 -0
  38. package/dist/crewfoundry/components/viz/StatCard.js +60 -0
  39. package/dist/crewfoundry/components/viz/StatCard.js.map +1 -0
  40. package/dist/crewfoundry/components/viz/StepProgress.js +3 -0
  41. package/dist/crewfoundry/components/viz/Timeline.js +66 -0
  42. package/dist/crewfoundry/components/viz/Timeline.js.map +1 -0
  43. package/dist/crewfoundry/components/viz/index.js +23 -0
  44. package/dist/crewfoundry/components/viz/lib/Avatar.js +30 -0
  45. package/dist/crewfoundry/components/viz/lib/Avatar.js.map +1 -0
  46. package/dist/crewfoundry/components/viz/lib/CartesianFrame.js +119 -0
  47. package/dist/crewfoundry/components/viz/lib/CartesianFrame.js.map +1 -0
  48. package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js +35 -0
  49. package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js.map +1 -0
  50. package/dist/crewfoundry/components/viz/lib/format.js +21 -0
  51. package/dist/crewfoundry/components/viz/lib/format.js.map +1 -0
  52. package/dist/crewfoundry/components/viz/lib/geometry.js +69 -0
  53. package/dist/crewfoundry/components/viz/lib/geometry.js.map +1 -0
  54. package/dist/crewfoundry/components/viz/lib/hooks.js +39 -0
  55. package/dist/crewfoundry/components/viz/lib/hooks.js.map +1 -0
  56. package/dist/crewfoundry/components/viz/lib/palette.js +27 -0
  57. package/dist/crewfoundry/components/viz/lib/palette.js.map +1 -0
  58. package/dist/crewfoundry/lib/analytics.js +323 -0
  59. package/dist/crewfoundry/lib/analytics.js.map +1 -0
  60. package/dist/crewfoundry/lib/companyFinance.js +16 -0
  61. package/dist/crewfoundry/lib/companyFinance.js.map +1 -0
  62. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +226 -283
  63. package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
  64. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +107 -120
  65. package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
  66. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +122 -162
  67. package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
  68. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +121 -158
  69. package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
  70. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +316 -211
  71. package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
  72. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +75 -27
  73. package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
  74. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +167 -165
  75. package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
  76. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +168 -109
  77. package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
  78. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +401 -290
  79. package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
  80. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +84 -75
  81. package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
  82. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +368 -174
  83. package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
  84. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +236 -201
  85. package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
  86. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +369 -196
  87. package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
  88. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +269 -270
  89. package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
  90. package/dist/crewfoundry/pages/HiringJobsPagePage.js +210 -110
  91. package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
  92. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +216 -178
  93. package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
  94. package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js +385 -0
  95. package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js.map +1 -0
  96. package/dist/crewfoundry/pages/HrEmployeesPagePage.js +189 -130
  97. package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
  98. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +397 -241
  99. package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
  100. package/dist/crewfoundry/pages/HrPayrollPagePage.js +262 -147
  101. package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
  102. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +345 -167
  103. package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
  104. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +98 -24
  105. package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
  106. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +1 -1
  107. package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
  108. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +289 -108
  109. package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
  110. package/dist/crewfoundry/pages/LearningCoursesPagePage.js +221 -114
  111. package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
  112. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +134 -135
  113. package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
  114. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +148 -97
  115. package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
  116. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +264 -157
  117. package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
  118. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +85 -93
  119. package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
  120. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +211 -122
  121. package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
  122. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +94 -54
  123. package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
  124. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +289 -140
  125. package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
  126. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +169 -79
  127. package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
  128. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +296 -125
  129. package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
  130. package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js +187 -0
  131. package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js.map +1 -0
  132. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +140 -78
  133. package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
  134. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +93 -43
  135. package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
  136. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +250 -98
  137. package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
  138. package/dist/crewfoundry/store/crewfoundryStore.js +1 -1
  139. package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
  140. package/dist/crewfoundry/utils/cn.js +10 -0
  141. package/dist/crewfoundry/utils/cn.js.map +1 -0
  142. package/dist/crewfoundry/utils/courseProgress.js +46 -0
  143. package/dist/crewfoundry/utils/courseProgress.js.map +1 -0
  144. package/dist/node_modules/clsx/dist/clsx.js +18 -0
  145. package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
  146. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
  147. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  148. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"HiringInterviewsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/HiringInterviewsPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { Calendar, Clock, Plus, Star, Video } from 'lucide-react';\nimport { useCrewFoundryStore, type Interview } from '../store/crewfoundryStore';\nimport { FormModal, type FieldConfig, type FormValues } from '../components/forms/FormModal';\nimport { getText, newClientId } from '../components/forms/formValues';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\n\nconst INTERVIEW_TYPE_OPTIONS: FieldConfig['options'] = [\n { label: 'Phone', value: 'phone' },\n { label: 'Video', value: 'video' },\n { label: 'Onsite', value: 'onsite' },\n { label: 'Panel', value: 'panel' },\n { label: 'Technical', value: 'technical' },\n];\n\nconst INTERVIEW_STATUS_OPTIONS: FieldConfig['options'] = [\n { label: 'Scheduled', value: 'scheduled' },\n { label: 'Completed', value: 'completed' },\n { label: 'Cancelled', value: 'cancelled' },\n { label: 'No show', value: 'no_show' },\n];\n\nconst UPDATE_FIELDS: FieldConfig[] = [\n {\n name: 'status',\n label: 'Status',\n type: 'select',\n options: INTERVIEW_STATUS_OPTIONS,\n required: true,\n },\n { name: 'rating', label: 'Rating (out of 5)', type: 'number' },\n { name: 'feedback', label: 'Feedback', type: 'textarea', colSpan: 2 },\n];\n\nexport function HiringInterviewsPagePage() {\n const { showToast } = useGlobalUi();\n const { interviews, candidates, addInterview, updateInterview } = useCrewFoundryStore();\n const [scheduleOpen, setScheduleOpen] = useState(false);\n const [updateTarget, setUpdateTarget] = useState<Interview | null>(null);\n\n const scheduled = interviews.filter((i) => i.status === 'scheduled');\n const completed = interviews.filter((i) => i.status === 'completed');\n\n // Interviews dated within the current calendar week (Mon–Sun).\n const thisWeekCount = useMemo(() => {\n const now = new Date();\n const startOfWeek = new Date(now);\n startOfWeek.setDate(now.getDate() - ((now.getDay() + 6) % 7));\n startOfWeek.setHours(0, 0, 0, 0);\n const endOfWeek = new Date(startOfWeek);\n endOfWeek.setDate(startOfWeek.getDate() + 7);\n return interviews.filter((i) => {\n const date = new Date(i.date);\n return !Number.isNaN(date.getTime()) && date >= startOfWeek && date < endOfWeek;\n }).length;\n }, [interviews]);\n\n const scheduleFields = useMemo<FieldConfig[]>(\n () => [\n {\n name: 'candidateId',\n label: 'Candidate',\n type: 'select',\n required: true,\n placeholder: candidates.length ? 'Select a candidate…' : 'No candidates available',\n options: candidates.map((c) => ({\n label: `${c.firstName} ${c.lastName} — ${c.position}`,\n value: c.id,\n })),\n },\n { name: 'interviewerName', label: 'Interviewer', type: 'text', required: true },\n { name: 'date', label: 'Date', type: 'date', required: true },\n { name: 'time', label: 'Time', type: 'text', required: true, placeholder: 'e.g. 10:30 AM' },\n {\n name: 'type',\n label: 'Type',\n type: 'select',\n required: true,\n options: INTERVIEW_TYPE_OPTIONS,\n },\n ],\n [candidates]\n );\n\n const handleSchedule = async (values: FormValues) => {\n const candidate = candidates.find((c) => c.id === getText(values, 'candidateId'));\n if (!candidate) {\n throw new Error('Please select a candidate');\n }\n await addInterview({\n id: newClientId(),\n candidateId: candidate.id,\n candidateName: `${candidate.firstName} ${candidate.lastName}`,\n position: candidate.position,\n interviewerName: getText(values, 'interviewerName'),\n date: getText(values, 'date'),\n time: getText(values, 'time'),\n type: values.type as Interview['type'],\n status: 'scheduled',\n });\n showToast('Interview scheduled', 'success');\n };\n\n const handleUpdate = async (values: FormValues) => {\n if (!updateTarget) {\n return;\n }\n const ratingRaw = values.rating;\n const hasRating =\n typeof ratingRaw === 'number' || (typeof ratingRaw === 'string' && ratingRaw.trim() !== '');\n await updateInterview(updateTarget.id, {\n status: values.status as Interview['status'],\n feedback: getText(values, 'feedback'),\n ...(hasRating ? { rating: Number(ratingRaw) } : {}),\n });\n showToast('Interview updated', 'success');\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>Interviews</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {scheduled.length} upcoming · {completed.length} completed\n </p>\n <PagePurpose className=\"mt-1\">\n Schedule and track interviews across your hiring pipeline — keep everyone aligned on\n who&apos;s meeting which candidate and when.\n </PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => setScheduleOpen(true)}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Schedule Interview\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-3\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Scheduled</CardTitle>\n <Calendar className=\"h-4 w-4 text-status-info-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{scheduled.length}</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\">Completed</CardTitle>\n <Clock className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{completed.length}</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\">This Week</CardTitle>\n <Video className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{thisWeekCount}</div>\n </CardContent>\n </GlassCard>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Upcoming Interviews</CardTitle>\n <CardDescription>Scheduled interviews for the coming days</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {scheduled.map((interview) => (\n <div\n key={interview.id}\n className=\"flex flex-wrap items-center justify-between gap-3 rounded border p-4\"\n >\n <div>\n <p className=\"text-sm font-medium\">{interview.candidateName}</p>\n <p className=\"text-xs text-text-secondary\">{interview.position}</p>\n <p className=\"text-xs text-text-secondary mt-1\">\n Interviewer: {interview.interviewerName}\n </p>\n </div>\n <div className=\"flex items-center gap-3\">\n <div className=\"text-right\">\n <p className=\"text-sm font-medium\">{interview.date}</p>\n <p className=\"text-xs text-text-secondary\">{interview.time}</p>\n </div>\n <Badge variant=\"outline\">{formatEnumLabel(interview.type)}</Badge>\n <Badge variant=\"secondary\">{formatEnumLabel(interview.status)}</Badge>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setUpdateTarget(interview)}>\n Record outcome\n </Button>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n {completed.length > 0 && (\n <Card>\n <CardHeader>\n <CardTitle>Completed Interviews</CardTitle>\n <CardDescription>Recent interview feedback</CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {completed.map((interview) => (\n <div\n key={interview.id}\n className=\"flex flex-wrap items-center justify-between gap-3 rounded border p-4\"\n >\n <div>\n <p className=\"text-sm font-medium\">{interview.candidateName}</p>\n <p className=\"text-xs text-text-secondary\">{interview.position}</p>\n {interview.feedback && (\n <p className=\"text-xs text-text-secondary mt-1 italic\">\n &quot;{interview.feedback}&quot;\n </p>\n )}\n </div>\n <div className=\"flex items-center gap-3\">\n {interview.rating && (\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-4 w-4 text-status-warning-text\" />\n <span className=\"text-sm font-medium\">{interview.rating}/5</span>\n </div>\n )}\n <Badge variant=\"default\">completed</Badge>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n )}\n\n <FormModal\n open={scheduleOpen}\n onOpenChange={setScheduleOpen}\n title=\"Schedule Interview\"\n description=\"Set up a conversation with a candidate in your pipeline.\"\n fields={scheduleFields}\n submitLabel=\"Schedule\"\n onSubmit={handleSchedule}\n />\n <FormModal\n open={updateTarget !== null}\n onOpenChange={(open) => {\n if (!open) {\n setUpdateTarget(null);\n }\n }}\n title=\"Record Interview Outcome\"\n description={\n updateTarget ? `${updateTarget.candidateName} — ${updateTarget.position}` : undefined\n }\n fields={UPDATE_FIELDS}\n initialValues={\n updateTarget\n ? {\n status: updateTarget.status,\n rating: updateTarget.rating ?? '',\n feedback: updateTarget.feedback ?? '',\n }\n : undefined\n }\n submitLabel=\"Save outcome\"\n onSubmit={handleUpdate}\n />\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"HiringInterviewsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/HiringInterviewsPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { Calendar, Clock, Plus, Star, Video } from 'lucide-react';\nimport { useCrewFoundryStore, type Interview } from '../store/crewfoundryStore';\nimport { FormModal, type FieldConfig, type FormValues } from '../components/forms/FormModal';\nimport { getText, newClientId } from '../components/forms/formValues';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\nimport { RatingStars, getInitials } from '../components/viz';\n\nconst INTERVIEW_TYPE_OPTIONS: FieldConfig['options'] = [\n { label: 'Phone', value: 'phone' },\n { label: 'Video', value: 'video' },\n { label: 'Onsite', value: 'onsite' },\n { label: 'Panel', value: 'panel' },\n { label: 'Technical', value: 'technical' },\n];\n\n// Per-competency scorecard. CrewInterview has only a single `feedback` (String)\n// + `rating` (Float), and the gateway strips `rating` from update inputs — so the\n// four competency scores are persisted by encoding them into `feedback` behind a\n// compact machine marker, then parsed back out on load. The written notes follow\n// the marker line; the overall rating is derived from the competency scores.\nconst COMPETENCIES: { key: string; label: string }[] = [\n { key: 'technical', label: 'Technical Skills' },\n { key: 'problem', label: 'Problem Solving' },\n { key: 'communication', label: 'Communication' },\n { key: 'culture', label: 'Culture Fit' },\n];\n\nconst SCORECARD_MARKER = '@@scorecard';\n\ninterface ParsedScorecard {\n scores: Record<string, number>;\n notes: string;\n}\n\nfunction parseScorecard(feedback?: string | null): ParsedScorecard {\n if (!feedback) {\n return { scores: {}, notes: '' };\n }\n if (!feedback.startsWith(`${SCORECARD_MARKER}:`)) {\n return { scores: {}, notes: feedback };\n }\n const newline = feedback.indexOf('\\n');\n const header = newline === -1 ? feedback : feedback.slice(0, newline);\n const notes = newline === -1 ? '' : feedback.slice(newline + 1);\n const scores: Record<string, number> = {};\n const body = header.slice(SCORECARD_MARKER.length + 1);\n for (const pair of body.split(',')) {\n const [key, raw] = pair.split('=');\n const value = Number(raw);\n if (key && !Number.isNaN(value)) {\n scores[key] = value;\n }\n }\n return { scores, notes };\n}\n\nfunction serializeScorecard(scores: Record<string, number>, notes: string): string {\n const entries = COMPETENCIES.filter((c) => (scores[c.key] ?? 0) > 0).map(\n (c) => `${c.key}=${scores[c.key]}`\n );\n if (entries.length === 0) {\n return notes;\n }\n return `${SCORECARD_MARKER}:${entries.join(',')}\\n${notes}`;\n}\n\nfunction overallScore(scores: Record<string, number>): number {\n const values = COMPETENCIES.map((c) => scores[c.key]).filter(\n (v): v is number => typeof v === 'number' && v > 0\n );\n if (values.length === 0) {\n return 0;\n }\n return Math.round((values.reduce((a, b) => a + b, 0) / values.length) * 10) / 10;\n}\n\nfunction InitialsAvatar({ name, size = 40 }: { name: string; size?: number }) {\n return (\n <span\n className=\"inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full border border-border-subtle bg-bg-sunken font-medium text-text-secondary\"\n style={{ width: size, height: size, fontSize: Math.round(size * 0.36) }}\n aria-hidden=\"true\"\n >\n {getInitials(name)}\n </span>\n );\n}\n\n/** Interactive 1–max star input for a single competency. */\nfunction StarInput({\n value,\n onChange,\n label,\n max = 5,\n}: {\n value: number;\n onChange: (value: number) => void;\n label: string;\n max?: number;\n}) {\n return (\n <div className=\"flex items-center gap-0.5\" role=\"radiogroup\" aria-label={label}>\n {Array.from({ length: max }, (_, i) => i + 1).map((n) => (\n <button\n key={n}\n type=\"button\"\n role=\"radio\"\n aria-checked={value === n}\n aria-label={`${n} out of ${max}`}\n onClick={() => onChange(value === n ? 0 : n)}\n className=\"rounded p-0.5 outline-none transition-transform hover:scale-110 focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <Star\n className=\"h-5 w-5\"\n strokeWidth={1.5}\n style={{\n color: n <= value ? 'var(--color-status-warning-text)' : 'var(--color-border-strong)',\n }}\n fill={n <= value ? 'currentColor' : 'none'}\n />\n </button>\n ))}\n </div>\n );\n}\n\nconst TYPE_BADGE: Record<Interview['type'], 'default' | 'secondary' | 'outline'> = {\n technical: 'default',\n panel: 'secondary',\n onsite: 'secondary',\n video: 'outline',\n phone: 'outline',\n};\n\nfunction formatDay(dateStr: string): string {\n const date = new Date(dateStr);\n if (Number.isNaN(date.getTime())) {\n return dateStr || 'Unscheduled';\n }\n return date.toLocaleDateString(undefined, {\n weekday: 'short',\n month: 'short',\n day: 'numeric',\n });\n}\n\nexport function HiringInterviewsPagePage() {\n const { showToast } = useGlobalUi();\n const { interviews, candidates, addInterview, updateInterview } = useCrewFoundryStore();\n const [scheduleOpen, setScheduleOpen] = useState(false);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [saving, setSaving] = useState(false);\n\n const scheduled = interviews.filter((i) => i.status === 'scheduled');\n const completed = interviews.filter((i) => i.status === 'completed');\n\n // Interviews sorted chronologically, grouped by day for the schedule list.\n const dayGroups = useMemo(() => {\n const sorted = [...interviews].sort((a, b) => {\n const da = new Date(a.date).getTime();\n const db = new Date(b.date).getTime();\n if (Number.isNaN(da) && Number.isNaN(db)) return 0;\n if (Number.isNaN(da)) return 1;\n if (Number.isNaN(db)) return -1;\n return da - db;\n });\n const groups: { label: string; items: Interview[] }[] = [];\n for (const interview of sorted) {\n const label = formatDay(interview.date);\n const last = groups[groups.length - 1];\n if (last && last.label === label) {\n last.items.push(interview);\n } else {\n groups.push({ label, items: [interview] });\n }\n }\n return groups;\n }, [interviews]);\n\n // Effective selection is derived (no effect): honour an explicit click, else\n // default to the first scheduled interview, else the first interview overall.\n const activeId = selectedId ?? scheduled[0]?.id ?? interviews[0]?.id ?? null;\n const selected = activeId ? (interviews.find((i) => i.id === activeId) ?? null) : null;\n\n const thisWeekCount = useMemo(() => {\n const now = new Date();\n const startOfWeek = new Date(now);\n startOfWeek.setDate(now.getDate() - ((now.getDay() + 6) % 7));\n startOfWeek.setHours(0, 0, 0, 0);\n const endOfWeek = new Date(startOfWeek);\n endOfWeek.setDate(startOfWeek.getDate() + 7);\n return interviews.filter((i) => {\n const date = new Date(i.date);\n return !Number.isNaN(date.getTime()) && date >= startOfWeek && date < endOfWeek;\n }).length;\n }, [interviews]);\n\n const scheduleFields = useMemo<FieldConfig[]>(\n () => [\n {\n name: 'candidateId',\n label: 'Candidate',\n type: 'select',\n required: true,\n placeholder: candidates.length ? 'Select a candidate…' : 'No candidates available',\n options: candidates.map((c) => ({\n label: `${c.firstName} ${c.lastName} — ${c.position}`,\n value: c.id,\n })),\n },\n { name: 'interviewerName', label: 'Interviewer', type: 'text', required: true },\n { name: 'date', label: 'Date', type: 'date', required: true },\n { name: 'time', label: 'Time', type: 'text', required: true, placeholder: 'e.g. 10:30 AM' },\n {\n name: 'type',\n label: 'Type',\n type: 'select',\n required: true,\n options: INTERVIEW_TYPE_OPTIONS,\n },\n ],\n [candidates]\n );\n\n const handleSchedule = async (values: FormValues) => {\n const candidate = candidates.find((c) => c.id === getText(values, 'candidateId'));\n if (!candidate) {\n throw new Error('Please select a candidate');\n }\n await addInterview({\n id: newClientId(),\n candidateId: candidate.id,\n candidateName: `${candidate.firstName} ${candidate.lastName}`,\n position: candidate.position,\n interviewerName: getText(values, 'interviewerName'),\n date: getText(values, 'date'),\n time: getText(values, 'time'),\n type: values.type as Interview['type'],\n status: 'scheduled',\n });\n showToast('Interview scheduled', 'success');\n };\n\n const handleSaveScorecard = async (submit: boolean, feedback: string) => {\n if (!selected) {\n return;\n }\n setSaving(true);\n try {\n await updateInterview(selected.id, {\n status: submit ? 'completed' : selected.status,\n feedback,\n });\n showToast(submit ? 'Scorecard submitted' : 'Draft saved', 'success');\n } catch {\n showToast('Could not save the scorecard', 'error');\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Interviews</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {scheduled.length} upcoming · {completed.length} completed\n </p>\n <PagePurpose className=\"mt-1\">\n Schedule interviews and score candidates on a live scorecard — capture competency\n ratings and feedback the moment the conversation ends.\n </PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => setScheduleOpen(true)}>\n <Plus className=\"mr-1 h-4 w-4\" />\n Schedule Interview\n </Button>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Scheduled</CardTitle>\n <Calendar className=\"h-4 w-4 text-status-info-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{scheduled.length}</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\">Completed</CardTitle>\n <Clock className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{completed.length}</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\">This Week</CardTitle>\n <Video className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{thisWeekCount}</div>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"grid gap-6 lg:grid-cols-3\">\n {/* Scheduled / all interviews list */}\n <Card className=\"lg:col-span-2\">\n <CardHeader>\n <CardTitle>Scheduled Interviews</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {interviews.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No interviews scheduled\"\n description=\"Schedule an interview to start tracking your pipeline conversations.\"\n />\n ) : (\n dayGroups.map((group) => (\n <div key={group.label} className=\"space-y-2\">\n <div className=\"sticky top-0 rounded bg-bg-sunken px-3 py-1 text-xs font-medium text-text-secondary\">\n {group.label}\n </div>\n {group.items.map((interview) => {\n const isSelected = interview.id === activeId;\n const parsed = parseScorecard(interview.feedback);\n const overall = overallScore(parsed.scores) || interview.rating || 0;\n return (\n <button\n key={interview.id}\n type=\"button\"\n onClick={() => setSelectedId(interview.id)}\n aria-pressed={isSelected}\n className={`flex w-full flex-wrap items-center justify-between gap-3 rounded-[var(--radius-input)] border p-4 text-left transition-colors ${\n isSelected\n ? 'border-action-primary-bg bg-action-primary-bg/10'\n : 'border-border-subtle hover:bg-bg-sunken'\n }`}\n >\n <div className=\"flex min-w-0 items-center gap-3\">\n <InitialsAvatar name={interview.candidateName} />\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {interview.candidateName}\n </p>\n <p className=\"truncate text-xs text-text-secondary\">\n {interview.position}\n </p>\n <p className=\"truncate text-xs text-text-secondary\">\n Interviewer: {interview.interviewerName}\n </p>\n </div>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <div className=\"text-right\">\n <Badge variant={TYPE_BADGE[interview.type]} className=\"text-[10px]\">\n {formatEnumLabel(interview.type)}\n </Badge>\n <p className=\"mt-1 text-xs text-text-secondary\">{interview.time}</p>\n </div>\n {interview.status === 'completed' && overall > 0 && (\n <RatingStars value={overall} size={12} />\n )}\n <Badge\n variant={interview.status === 'completed' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {formatEnumLabel(interview.status)}\n </Badge>\n </div>\n </button>\n );\n })}\n </div>\n ))\n )}\n </CardContent>\n </Card>\n\n {/* Persistent scorecard panel */}\n <div className=\"lg:sticky lg:top-4 lg:self-start\">\n <Card>\n <CardHeader>\n <CardTitle>Interview Scorecard</CardTitle>\n {selected && (\n <p className=\"text-sm text-text-secondary\">\n {formatEnumLabel(selected.type)} interview for {selected.candidateName}\n </p>\n )}\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {!selected ? (\n <p className=\"text-sm text-text-muted\">\n Select an interview to open its scorecard.\n </p>\n ) : (\n <ScorecardEditor\n key={selected.id}\n interview={selected}\n saving={saving}\n onSave={handleSaveScorecard}\n />\n )}\n </CardContent>\n </Card>\n </div>\n </div>\n\n <FormModal\n open={scheduleOpen}\n onOpenChange={setScheduleOpen}\n title=\"Schedule Interview\"\n description=\"Set up a conversation with a candidate in your pipeline.\"\n fields={scheduleFields}\n submitLabel=\"Schedule\"\n onSubmit={handleSchedule}\n />\n </div>\n );\n}\n\ninterface ScorecardEditorProps {\n interview: Interview;\n saving: boolean;\n onSave: (submit: boolean, feedback: string) => void;\n}\n\n/**\n * Editable scorecard for one interview. Re-mounted (via `key={interview.id}`)\n * whenever the selection changes, so its local state initializes from the\n * interview's persisted feedback without a synchronizing effect.\n */\nfunction ScorecardEditor({ interview, saving, onSave }: ScorecardEditorProps) {\n const initial = parseScorecard(interview.feedback);\n const [scores, setScores] = useState<Record<string, number>>(initial.scores);\n const [notes, setNotes] = useState(initial.notes);\n\n const overall = overallScore(scores);\n\n return (\n <>\n <div className=\"grid grid-cols-2 gap-3 rounded-[var(--radius-input)] bg-bg-sunken p-3 text-xs\">\n <div>\n <p className=\"text-text-muted\">Candidate</p>\n <p className=\"font-medium text-text-primary\">{interview.candidateName}</p>\n <p className=\"mt-1 text-text-muted\">Position</p>\n <p className=\"font-medium text-text-primary\">{interview.position}</p>\n </div>\n <div>\n <p className=\"text-text-muted\">Date</p>\n <p className=\"font-medium text-text-primary\">{interview.date}</p>\n <p className=\"mt-1 text-text-muted\">Time</p>\n <p className=\"font-medium text-text-primary\">{interview.time}</p>\n </div>\n </div>\n\n <div className=\"space-y-3\">\n {COMPETENCIES.map((competency) => (\n <div key={competency.key} className=\"flex items-center justify-between gap-2\">\n <span className=\"text-sm font-medium text-text-primary\">{competency.label}</span>\n <StarInput\n label={competency.label}\n value={scores[competency.key] ?? 0}\n onChange={(value) => setScores((prev) => ({ ...prev, [competency.key]: value }))}\n />\n </div>\n ))}\n </div>\n\n <div className=\"flex items-center justify-between border-t border-border-subtle pt-3 text-sm\">\n <span className=\"font-medium text-text-primary\">Overall</span>\n {overall > 0 ? (\n <RatingStars value={overall} size={16} showValue />\n ) : (\n <span className=\"text-xs text-text-muted\">Not scored</span>\n )}\n </div>\n\n <div className=\"space-y-1.5\">\n <label htmlFor=\"scorecard-feedback\" className=\"text-sm font-medium\">\n Feedback\n </label>\n <Textarea\n id=\"scorecard-feedback\"\n rows={5}\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n placeholder=\"Summarize strengths, concerns, and a recommendation…\"\n />\n </div>\n\n <div className=\"flex gap-2\">\n <Button\n className=\"flex-1\"\n disabled={saving}\n onClick={() => onSave(true, serializeScorecard(scores, notes))}\n >\n Submit\n </Button>\n <Button\n variant=\"outline\"\n className=\"flex-1\"\n disabled={saving}\n onClick={() => onSave(false, serializeScorecard(scores, notes))}\n >\n Save Draft\n </Button>\n </div>\n </>\n );\n}\n"],"mappings":"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"}