update 9/23

This commit is contained in:
Ra
2025-09-23 09:53:05 -07:00
parent b41f489fe6
commit 5b5bf76c9a
22 changed files with 8769 additions and 8316 deletions

View File

@@ -1,5 +1,5 @@
import React, { useState, useEffect, useCallback } from 'react';
import { useLocation } from 'react-router-dom';
import { useLocation, useNavigate } from 'react-router-dom';
import { useOrg } from '../contexts/OrgContext';
import { secureApi } from '../services/secureApi';
import { CompanyReport, Employee, EmployeeReport } from '../types';
@@ -8,12 +8,153 @@ import RadarPerformanceChart from '../components/charts/RadarPerformanceChart';
import { downloadCompanyReportPDF, downloadEmployeeReportPDF } from '../utils/pdfUtils';
import FigmaPrimaryButton from '../components/figma/FigmaButton';
import { DownloadIcon } from '../components/figma/figmaIcon';
import MarkdownRenderer from '../components/MarkdownRenderer';
const Reports: React.FC = () => {
const location = useLocation();
const navigate = useNavigate();
// Helper function to extract company report context for AI
const extractCompanyReportContext = (report: CompanyReport, orgName: string): string => {
const sections = [];
if (report.overview) {
sections.push(`Company Overview:
- Total Employees: ${report.overview.totalEmployees}
- Average Performance Score: ${report.overview.averagePerformanceScore}
- Risk Level: ${report.overview.riskLevel}
- Submission Rate: ${report.overview.submissionRate}%`);
if (report.overview.departmentBreakdown?.length > 0) {
const deptInfo = report.overview.departmentBreakdown
.map(dept => `${dept.department}: ${dept.count} employees`)
.join(', ');
sections.push(`Department Breakdown: ${deptInfo}`);
}
}
if (report.strengths?.length > 0) {
sections.push(`Company Strengths:\n${report.strengths.map(s => `- ${s}`).join('\n')}`);
}
if (report.weaknesses?.length > 0) {
sections.push(`Company Weaknesses:\n${report.weaknesses.map(w => `- ${w.title}: ${w.description}`).join('\n')}`);
}
if (report.immediateHiringNeeds?.length > 0) {
sections.push(`Immediate Hiring Needs:\n${report.immediateHiringNeeds.map(need => `- ${need.role}: ${need.priority} priority - ${need.reasoning}`).join('\n')}`);
}
if (report.personnelChanges) {
const changes = [];
if (report.personnelChanges.newHires?.length > 0) {
changes.push(`New Hires: ${report.personnelChanges.newHires.map(hire => `${hire.name} (${hire.role} in ${hire.department})`).join(', ')}`);
}
if (report.personnelChanges.promotions?.length > 0) {
changes.push(`Promotions: ${report.personnelChanges.promotions.map(promo => `${promo.name}: ${promo.fromRole}${promo.toRole}`).join(', ')}`);
}
if (report.personnelChanges.departures?.length > 0) {
changes.push(`Departures: ${report.personnelChanges.departures.map(dep => `${dep.name} (${dep.department}) - ${dep.reason}`).join(', ')}`);
}
if (changes.length > 0) {
sections.push(`Personnel Changes:\n${changes.join('\n')}`);
}
}
if (report.forwardOperatingPlan?.length > 0) {
sections.push(`Forward Operating Plan:\n${report.forwardOperatingPlan.map(plan => `- ${plan.title}: ${plan.details.join(', ')}`).join('\n')}`);
}
if (report.gradingBreakdown?.length > 0) {
const gradingInfo = report.gradingBreakdown.map(dept =>
`${dept.departmentName}: ${dept.departmentGrade} (Lead: ${dept.lead})`
).join('\n');
sections.push(`Performance Grading by Department:\n${gradingInfo}`);
}
return sections.join('\n\n');
};
// Helper function to extract employee report context for AI
const extractEmployeeReportContext = (report: EmployeeReport, employeeName: string, companyReport?: CompanyReport): { employeeContext: string; companyContext?: string } => {
const employeeSections = [];
if (report.roleAndOutput) {
employeeSections.push(`Role & Responsibilities: ${report.roleAndOutput.responsibilities}`);
if (report.roleAndOutput.selfRatedOutput) {
employeeSections.push(`Self-Rated Output: ${report.roleAndOutput.selfRatedOutput}`);
}
}
if (report.insights) {
employeeSections.push(`Personality Traits: ${report.insights.personalityTraits}`);
if (report.insights.selfAwareness) {
employeeSections.push(`Self-Awareness: ${report.insights.selfAwareness}`);
}
if (report.insights.growthDesire) {
employeeSections.push(`Growth Desire: ${report.insights.growthDesire}`);
}
}
if (report.strengths?.length > 0) {
employeeSections.push(`Strengths:\n${report.strengths.map(s => `- ${s}`).join('\n')}`);
}
if (report.weaknesses?.length > 0) {
employeeSections.push(`Areas for Improvement:\n${report.weaknesses.map(w => `- ${w}`).join('\n')}`);
}
if (report.recommendations?.length > 0) {
employeeSections.push(`Recommendations:\n${report.recommendations.map(r => `- ${r}`).join('\n')}`);
}
if (report.gradingOverview) {
const gradingInfo = `Grade: ${report.gradingOverview.grade}, Reliability: ${report.gradingOverview.reliability}, Role Fit: ${report.gradingOverview.roleFit}, Scalability: ${report.gradingOverview.scalability}, Output: ${report.gradingOverview.output}, Initiative: ${report.gradingOverview.initiative}`;
employeeSections.push(`Performance Scores: ${gradingInfo}`);
}
const employeeContext = employeeSections.join('\n\n');
let companyContext;
if (companyReport && org?.companyName) {
companyContext = extractCompanyReportContext(companyReport, org.companyName);
}
return { employeeContext, companyContext };
};
// Handle Chat with AI navigation for company reports
const handleCompanyChatWithAI = () => {
if (!companyReport || !org?.companyName) return;
const context = extractCompanyReportContext(companyReport, org.companyName);
navigate('/chat', {
state: {
initialContext: context,
contextType: 'company',
companyName: org.companyName
}
});
};
// Handle Chat with AI navigation for employee reports
const handleEmployeeChatWithAI = (employeeName: string, employeeReport: EmployeeReport) => {
const { employeeContext, companyContext } = extractEmployeeReportContext(employeeReport, employeeName, companyReport);
navigate('/chat', {
state: {
initialContext: employeeContext,
companyContext: companyContext,
contextType: 'employee',
employeeName: employeeName,
companyName: org?.companyName
}
});
};
const { employees, reports, submissions, user, isOwner, getFullCompanyReportHistory, generateEmployeeReport, generateCompanyReport, orgId, org } = useOrg();
const [companyReport, setCompanyReport] = useState<CompanyReport | null>(null);
const [selectedReport, setSelectedReport] = useState<{ report: CompanyReport | EmployeeReport; type: 'company' | 'employee'; employeeName?: string } | null>(null);
const [selectedReport, setSelectedReport] = useState<{ report: CompanyReport | EmployeeReport; type: 'company' | 'employee'; employeeName?: string; employeeEmail?: string } | null>(null);
const [searchQuery, setSearchQuery] = useState('');
const [generatingEmployeeReport, setGeneratingEmployeeReport] = useState<string | null>(null);
const [generatingCompanyReport, setGeneratingCompanyReport] = useState(false);
@@ -23,6 +164,16 @@ const Reports: React.FC = () => {
// Get selected employee ID from navigation state (from Submissions page)
const selectedEmployeeId = location.state?.selectedEmployeeId;
console.log('Reports page state:', {
employeesCount: employees.length,
reportsCount: Object.keys(reports).length,
submissionsCount: Object.keys(submissions).length,
currentUserIsOwner,
companyReport: !!companyReport,
selectedReport: selectedReport?.type,
employeesList: employees.map(emp => ({ id: emp.id, name: emp.name }))
});
const handleGenerateEmployeeReport = async (employee: Employee) => {
if (generatingEmployeeReport === employee.id) return; // Prevent double-click
@@ -49,29 +200,39 @@ const Reports: React.FC = () => {
// Load company report on component mount
useEffect(() => {
const loadCompanyReport = async () => {
if (currentUserIsOwner) {
try {
const history = await getFullCompanyReportHistory();
if (history.length > 0) {
setCompanyReport(history[0]);
// Auto-select company report by default
setSelectedReport({ report: history[0], type: 'company' });
} else {
// FIXED: No automatic generation - only load existing reports
// Use sample data when no real reports exist
console.log('No company reports found, using sample data. Click "Refresh Report" to generate a new one.');
setCompanyReport(SAMPLE_COMPANY_REPORT);
setSelectedReport({ report: SAMPLE_COMPANY_REPORT, type: 'company' });
}
} catch (error) {
console.error('Failed to load company report:', error);
setCompanyReport(SAMPLE_COMPANY_REPORT);
setSelectedReport({ report: SAMPLE_COMPANY_REPORT, type: 'company' });
try {
console.log('Loading company report history...');
const history = await getFullCompanyReportHistory();
console.log('Company report history loaded:', history.length, 'reports');
if (history.length > 0) {
console.log('Setting existing company report as default');
setCompanyReport(history[0]);
// Auto-select company report by default
setSelectedReport({ report: history[0], type: 'company' });
} else {
console.log('No company reports found, setting placeholder report');
// Create a placeholder that shows generate button
const placeholderReport = {
...SAMPLE_COMPANY_REPORT,
isPlaceholder: true
} as CompanyReport;
setCompanyReport(placeholderReport);
setSelectedReport({ report: placeholderReport, type: 'company' });
}
} catch (error) {
console.error('Failed to load company report:', error);
// On error, show placeholder with generate option
const placeholderReport = {
...SAMPLE_COMPANY_REPORT,
isPlaceholder: true
} as CompanyReport;
setCompanyReport(placeholderReport);
setSelectedReport({ report: placeholderReport, type: 'company' });
}
};
loadCompanyReport();
}, [currentUserIsOwner, getFullCompanyReportHistory]); // FIXED: Removed generateCompanyReport and submissions dependencies
}, [currentUserIsOwner, getFullCompanyReportHistory, employees, user?.uid]);
const handleEmployeeSelect = useCallback(async (employee: Employee) => {
const employeeReport = reports[employee.id];
@@ -79,7 +240,8 @@ const Reports: React.FC = () => {
setSelectedReport({
report: employeeReport,
type: 'employee',
employeeName: employee.name
employeeName: employee.name,
employeeEmail: employee.email
});
} else {
// FIXED: Only check if employee has submission - do NOT auto-generate
@@ -102,7 +264,8 @@ const Reports: React.FC = () => {
recommendations: ['Generate the report to view detailed analysis and recommendations']
} as EmployeeReport,
type: 'employee',
employeeName: employee.name
employeeName: employee.name,
employeeEmail: employee.email
});
} else {
// No submission available - show message
@@ -122,7 +285,8 @@ const Reports: React.FC = () => {
recommendations: ['Employee should complete the questionnaire first']
} as EmployeeReport,
type: 'employee',
employeeName: employee.name
employeeName: employee.name,
employeeEmail: employee.email
});
}
}
@@ -139,11 +303,11 @@ const Reports: React.FC = () => {
}, [selectedEmployeeId, employees, handleEmployeeSelect]);
// Filter and sort employees
const visibleEmployees = currentUserIsOwner
? employees.filter(emp =>
emp.name.toLowerCase().includes(searchQuery.toLowerCase())
).sort((a, b) => a.name.localeCompare(b.name))
: employees.filter(emp => emp.id === user?.uid);
const visibleEmployees = employees;
console.log('Visible employees:', visibleEmployees.length, 'out of', employees.length, 'total employees');
console.log('Search query:', searchQuery);
console.log('Current user is owner:', currentUserIsOwner);
const handleCompanyReportSelect = () => {
if (companyReport) {
@@ -171,7 +335,7 @@ const Reports: React.FC = () => {
return (
<>
{/* Middle Section - Employee List */}
<div className="h-100vh flex-1 self-stretch bg-[--Neutrals-NeutralSlate0] flex justify-start items-center">
<div className="h-full flex-1 self-stretch bg-[--Neutrals-NeutralSlate0] flex justify-start items-center">
<div className="flex-1 self-stretch max-w-64 min-w-64 border-r border-[--Neutrals-NeutralSlate200] inline-flex flex-col justify-start items-start">
<div className="self-stretch p-5 inline-flex justify-start items-center gap-2.5">
<div className="flex-1 justify-start text-[--Text-Gray-950] text-base font-medium font-['Inter'] leading-normal">Employees</div>
@@ -199,8 +363,8 @@ const Reports: React.FC = () => {
{/* Employee List */}
<div className="self-stretch px-3 flex flex-col justify-start items-start">
{/* Company Report Item */}
{currentUserIsOwner && (
{/* Company Report Item - Always show for consistency */}
{companyReport && (
<div
className={`self-stretch p-2 rounded-full shadow-[0px_1px_2px_0px_rgba(10,13,20,0.03)] inline-flex justify-start items-center gap-2 overflow-hidden cursor-pointer ${selectedReport?.type === 'company' ? 'bg-[--Neutrals-NeutralSlate100]' : ''
}`}
@@ -208,10 +372,18 @@ const Reports: React.FC = () => {
>
<div className="w-7 h-7 p-1 bg-[--Brand-Orange] rounded-[666.67px] flex justify-center items-center">
<div className="text-center justify-start text-[--Text-Gray-0] text-xs font-medium font-['Inter'] leading-none">
C
{org?.companyName?.charAt(0)?.toUpperCase() || 'C'}
</div>
</div>
<div className="flex-1 justify-start text-[--Text-Gray-950] text-sm font-normal font-['Inter'] leading-tight">Company Report</div>
<div className="flex-1 justify-start text-[--Text-Gray-950] text-sm font-normal font-['Inter'] leading-tight">
{org?.companyName || 'Company Report'}
</div>
{/* Status indicator for company report */}
{(companyReport as any)?.isPlaceholder ? (
<div className="w-3 h-3 bg-gray-300 rounded-full" title="Report not generated yet" />
) : (
<div className="w-3 h-3 bg-green-400 rounded-full" title="Report available" />
)}
</div>
)}
@@ -224,12 +396,12 @@ const Reports: React.FC = () => {
return (
<div
key={employee.id}
className={`self-stretch p-2 rounded-full shadow-[0px_1px_2px_0px_rgba(10,13,20,0.03)] inline-flex justify-start items-center gap-2 overflow-hidden cursor-pointer ${selectedReport?.type === 'employee' && selectedReport?.employeeName === employee.name ? 'bg-[--Neutrals-NeutralSlate100]' : ''
className={`self-stretch p-2 rounded-full shadow-[0px_1px_2px_0px_rgba(10,13,20,0.03)] inline-flex justify-start items-center gap-2 overflow-hidden cursor-pointer ${selectedReport?.type === 'employee' && selectedReport?.employeeEmail === employee.email ? 'bg-[--Neutrals-NeutralSlate100]' : ''
}`}
onClick={() => handleEmployeeSelect(employee)}
>
<div className="w-7 h-7 p-1 bg-[--Neutrals-NeutralSlate100] rounded-[666.67px] flex justify-center items-center relative">
<div className="text-center justify-start text-[--Text-Gray-500] text-xs font-medium font-['Inter'] leading-none">
<div className={`w-7 h-7 p-1 ${selectedReport?.type === 'employee' && selectedReport?.employeeEmail === employee.email ? 'bg-[--Neutrals-NeutralSlate700] text-[--Neutrals-NeutralSlate0]' : 'bg-[--Neutrals-NeutralSlate100] text-[--Neutrals-NeutralSlate500]'} rounded-[666.67px] flex justify-center items-center relative`}>
<div className="text-center justify-start text-xs font-medium font-['Inter'] leading-none">
{employee.initials}
</div>
{/* Status indicator */}
@@ -265,6 +437,7 @@ const Reports: React.FC = () => {
onRegenerate={handleGenerateCompanyReport}
isGenerating={generatingCompanyReport}
org={org}
onChatWithAI={handleCompanyChatWithAI}
/>
) : (
(() => {
@@ -274,8 +447,9 @@ const Reports: React.FC = () => {
<EmployeeReportContent
report={employeeReport}
employeeName={selectedReport.employeeName!}
employeeEmail={selectedReport.employeeEmail!}
onGenerateReport={() => {
const employee = employees.find(emp => emp.name === selectedReport.employeeName);
const employee = employees.find(emp => emp.email === selectedReport.employeeEmail);
if (employee) handleGenerateEmployeeReport(employee);
}}
isGenerating={generatingEmployeeReport === employeeId}
@@ -283,6 +457,7 @@ const Reports: React.FC = () => {
showGenerateButton={!reports[employeeId] && !!submissions[employeeId]}
employees={employees}
org={org}
onChatWithAI={() => handleEmployeeChatWithAI(selectedReport.employeeName!, employeeReport)}
/>
);
})()
@@ -311,7 +486,8 @@ const CompanyReportContent: React.FC<{
onRegenerate: () => void;
isGenerating: boolean;
org?: any;
}> = ({ report, onRegenerate, isGenerating, org }) => {
onChatWithAI?: () => void;
}> = ({ report, onRegenerate, isGenerating, org, onChatWithAI }) => {
// Default to the first department in the array
const [activeDepartmentTab, setActiveDepartmentTab] = useState(() =>
report?.gradingBreakdown?.[0]?.departmentNameShort || 'Campaigns'
@@ -349,6 +525,22 @@ const CompanyReportContent: React.FC<{
</div>
</div>
</button>
<button
onClick={onChatWithAI}
className="px-3 py-2.5 bg-[--Brand-Orange] rounded-[999px] flex justify-center items-center gap-1 overflow-hidden hover:bg-orange-600 transition-colors"
>
<div className="relative">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.6667 7.33333C14.6667 10.647 11.9804 13.3333 8.66667 13.3333C7.95 13.3333 7.27333 13.18 6.66667 12.9067L2 14L3.09333 9.33333C2.82 8.72667 2.66667 8.05 2.66667 7.33333C2.66667 4.01967 5.353 1.33333 8.66667 1.33333C11.9804 1.33333 14.6667 4.01967 14.6667 7.33333Z" stroke="white" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M6 6.66667H6.00667M8.66667 6.66667H8.67333M11.3333 6.66667H11.34" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</div>
<div className="px-1 flex justify-center items-center">
<div className="justify-center text-white text-sm font-medium font-['Inter'] leading-tight">
Chat with AI
</div>
</div>
</button>
<FigmaPrimaryButton
onClick={() => downloadCompanyReportPDF(report, org?.companyName || 'Company')}
text="Download as PDF"
@@ -361,7 +553,7 @@ const CompanyReportContent: React.FC<{
{/* Content */}
<div className="self-stretch flex flex-col justify-start items-start gap-4 px-5 pb-6 overflow-y-auto">
{/* Company Weaknesses */}
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Gray-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Company Weaknesses</div>
</div>
@@ -391,7 +583,7 @@ const CompanyReportContent: React.FC<{
{/* Personnel Changes */}
{report?.personnelChanges && (
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Gray-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Personnel Changes</div>
</div>
@@ -453,7 +645,7 @@ const CompanyReportContent: React.FC<{
{/* Hiring Needs */}
{report?.immediateHiringNeeds && report.immediateHiringNeeds.length > 0 && (
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Gray-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Immediate Hiring Needs</div>
</div>
@@ -479,7 +671,7 @@ const CompanyReportContent: React.FC<{
{/* Forward Plan */}
{report?.forwardOperatingPlan && (
<div className="w-full self-stretch p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="w-full self-stretch p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Gray-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Forward Plan</div>
</div>
@@ -512,7 +704,7 @@ const CompanyReportContent: React.FC<{
Strengths goes here
*/}
{report?.strengths && (
<div className="self-stretch p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] inline-flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="self-stretch p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] inline-flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Gray-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Strengths</div>
</div>
@@ -609,7 +801,7 @@ const CompanyReportContent: React.FC<{
)}
**/}
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Gray-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Organizational Impact Summary</div>
</div>
@@ -675,7 +867,7 @@ const CompanyReportContent: React.FC<{
{/* Grading Overview */}
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Gray-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Grading Overview</div>
</div>
@@ -784,13 +976,15 @@ const CompanyReportContent: React.FC<{
const EmployeeReportContent: React.FC<{
report: EmployeeReport;
employeeName: string;
employeeEmail: string;
onGenerateReport?: () => void;
isGenerating?: boolean;
hasSubmission?: boolean;
showGenerateButton?: boolean;
employees?: Employee[];
org?: any;
}> = ({ report, employeeName, onGenerateReport, isGenerating = false, hasSubmission = false, showGenerateButton = false, employees, org }) => {
onChatWithAI?: () => void;
}> = ({ report, employeeName, onGenerateReport, isGenerating = false, hasSubmission = false, showGenerateButton = false, employees, org, onChatWithAI }) => {
return (
<>
{/* Header */}
@@ -823,13 +1017,33 @@ const EmployeeReportContent: React.FC<{
</button>
)}
{/* Chat with AI Button - only show for actual reports */}
{!showGenerateButton && onChatWithAI && (
<button
onClick={onChatWithAI}
className="px-3 py-2.5 bg-[--Brand-Orange] rounded-[999px] flex justify-center items-center gap-1 overflow-hidden hover:bg-orange-600 transition-colors"
>
<div className="relative">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.6667 7.33333C14.6667 10.647 11.9804 13.3333 8.66667 13.3333C7.95 13.3333 7.27333 13.18 6.66667 12.9067L2 14L3.09333 9.33333C2.82 8.72667 2.66667 8.05 2.66667 7.33333C2.66667 4.01967 5.353 1.33333 8.66667 1.33333C11.9804 1.33333 14.6667 4.01967 14.6667 7.33333Z" stroke="white" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
<path d="M6 6.66667H6.00667M8.66667 6.66667H8.67333M11.3333 6.66667H11.34" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
</div>
<div className="px-1 flex justify-center items-center">
<div className="justify-center text-white text-sm font-medium font-['Inter'] leading-tight">
Chat with AI
</div>
</div>
</button>
)}
{/* Download PDF Button - only show for actual reports */}
{!showGenerateButton && (
<FigmaPrimaryButton
containerExtra='h-9.5'
text="Download as PDF"
onClick={() => {
const employee = employees.find(emp => emp.name === employeeName);
const employee = employees.find(emp => emp.email === employeeName);
if (employee) {
downloadEmployeeReportPDF(employee, report, org?.companyName || 'Company');
}
@@ -844,7 +1058,7 @@ const EmployeeReportContent: React.FC<{
{/* Content */}
<div className="self-stretch flex flex-col justify-start items-start gap-4 px-5 pb-6 overflow-y-auto">
{/* Role & Responsibilities */}
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Dark-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Role & Responsibilities</div>
</div>
@@ -857,7 +1071,7 @@ const EmployeeReportContent: React.FC<{
{/* Self-Rated Output */}
{report.roleAndOutput && report.roleAndOutput?.selfRatedOutput && (
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Dark-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Self-Rated Output</div>
</div>
@@ -871,7 +1085,7 @@ const EmployeeReportContent: React.FC<{
{/* Insights */}
{report.insights && (
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Dark-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Insights & Traits</div>
</div>
@@ -906,7 +1120,7 @@ const EmployeeReportContent: React.FC<{
{/* Strengths */}
{report.strengths && report.strengths.length > 0 && (
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Dark-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Strengths</div>
</div>
@@ -930,14 +1144,14 @@ const EmployeeReportContent: React.FC<{
{/* Recommendations */}
{report.recommendations && report.recommendations.length > 0 && (
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1 overflow-hidden">
<div className="w-full p-3 bg-[--Neutrals-NeutralSlate100] rounded-[20px] shadow-[0px_1px_2px_0px_rgba(0,0,0,0.02)] flex flex-col justify-center items-start gap-1">
<div className="self-stretch px-3 py-2 inline-flex justify-start items-center gap-2">
<div className="justify-start text-[--Text-Dark-950] text-xl font-medium font-['Neue_Montreal'] leading-normal">Recommendations</div>
</div>
<div className="self-stretch p-6 bg-Light-Grays-l-gray08 rounded-2xl outline outline-1 outline-offset-[-1px] outline-Text-Gray-200 flex flex-col justify-start items-start gap-4">
{report.recommendations.map((recommendation, index) => (
<div key={index} className="self-stretch text-[--Text-Gray-800] text-base font-normal font-['Inter'] leading-normal">
{recommendation}
<MarkdownRenderer content={recommendation} />
</div>
))}
</div>