import React, { useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; import { EmployeeSubmissionAnswers } from '../employeeQuestions'; import { API_URL } from '../constants'; import { WelcomeScreen, SectionIntro, PersonalInfoForm, TextAreaQuestion, RatingScaleQuestion, YesNoChoice, ThankYouPage } from '../components/figma/FigmaEmployeeForms'; /** * Employee Questionnaire with Invite-Only Flow * * Features: * - Invite-based flow (no authentication required) * - Company owner invites employees with metadata * - Employee uses invite code to access questionnaire * - LLM processing via cloud functions with company context * - Report generation and Firestore storage */ const EmployeeQuestionnaire: React.FC = () => { const params = useParams(); const inviteCode = params.inviteCode; // Component state const [currentStep, setCurrentStep] = useState(1); const [formData, setFormData] = useState({}); const [isSubmitting, setIsSubmitting] = useState(false); const [error, setError] = useState(''); const [inviteEmployee, setInviteEmployee] = useState(null); const [isLoadingInvite, setIsLoadingInvite] = useState(false); // Load invite details on component mount useEffect(() => { if (inviteCode) { loadInviteDetails(inviteCode); } else { setError('No invite code provided'); } }, [inviteCode]); const loadInviteDetails = async (code: string) => { setIsLoadingInvite(true); try { const response = await fetch(`${API_URL}/getInvitationStatus?code=${code}`); if (response.ok) { const data = await response.json(); if (data.used) { setError('This invitation has already been used'); } else if (data.employee) { setInviteEmployee(data.employee); // Pre-populate form data with invite metadata setFormData({ name: data.employee.name || '', email: data.employee.email || '', company: data.employee.company || data.employee.department || '' }); setError(''); } else { setError('Invalid invitation data'); } } else { const errorData = await response.json().catch(() => ({ error: 'Unknown error' })); setError(errorData.error || 'Invalid or expired invitation link'); } } catch (err) { console.error('Error loading invite details:', err); setError('Failed to load invitation details'); } finally { setIsLoadingInvite(false); } }; // Get employee info from invite data const currentEmployee = inviteEmployee; const submitViaInvite = async (answers: EmployeeSubmissionAnswers, inviteCode: string) => { try { // Submit the questionnaire answers directly using Cloud Function // The cloud function will handle invite consumption and report generation const submitResponse = await fetch(`${API_URL}/submitEmployeeAnswers`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ inviteCode: inviteCode, answers: answers }) }); if (!submitResponse.ok) { const errorData = await submitResponse.json(); throw new Error(errorData.error || 'Failed to submit questionnaire'); } const result = await submitResponse.json(); return { success: true, reportGenerated: true }; } catch (error) { console.error('Invite submission error:', error); return { success: false, error: error.message }; } }; const handleSubmit = async () => { setIsSubmitting(true); setError(''); try { // Convert form data to answers format for backend const answers: EmployeeSubmissionAnswers = {}; // Map form data to question IDs if (formData.name) answers['full_name'] = formData.name; if (formData.email) answers['email'] = formData.email; if (formData.company) answers['company_department'] = formData.company; // Add all other form data fields Object.keys(formData).forEach(key => { if (formData[key] && !answers[key]) { answers[key] = formData[key]; } }); // Submit answers via invite flow const result = await submitViaInvite(answers, inviteCode!); if (result.success) { // Show thank you page setCurrentStep(999); } else { setError(result.error || 'Failed to submit questionnaire'); } } catch (error) { console.error('Submission error:', error); setError('Failed to submit questionnaire. Please try again.'); } finally { setIsSubmitting(false); } }; const handleNext = (stepData?: any) => { if (stepData) { const newFormData = { ...formData, ...stepData }; setFormData(newFormData); } setCurrentStep(currentStep + 1); }; const handleBack = () => { setCurrentStep(currentStep - 1); }; // Early return for loading state if (isLoadingInvite) { return (
A

Loading Your Invitation...

Please wait while we verify your invitation.

); } // Early return for error state if (error && currentStep === 1) { return (
!

Invitation Error

{error}

); } const renderStep = () => { switch (currentStep) { case 1: return ( handleNext()} /> ); case 2: return ( setFormData({ ...formData, ...data })} onNext={() => handleNext()} /> ); case 3: return ( handleNext()} /> ); case 4: return ( setFormData({ ...formData, titleAndDepartment: value })} onNext={() => handleNext()} currentStep={1} totalSteps={7} sectionName="Your Role & Responsibilities" /> ); case 5: return ( setFormData({ ...formData, dailyResponsibilities: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={2} totalSteps={7} sectionName="Your Role & Responsibilities" placeholder="Describe what you do on a typical day..." /> ); case 6: return ( setFormData({ ...formData, roleClarity: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={3} totalSteps={7} sectionName="Your Role & Responsibilities" scale={10} /> ); case 7: return ( handleNext()} /> ); case 8: return ( setFormData({ ...formData, weeklyOutput: value })} onNext={() => handleNext()} currentStep={1} totalSteps={7} sectionName="Output & Accountability" scale={10} /> ); case 9: return ( setFormData({ ...formData, topDeliverables: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={2} totalSteps={7} sectionName="Output & Accountability" /> ); case 10: return ( setFormData({ ...formData, hasKPIs: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={3} totalSteps={7} sectionName="Output & Accountability" /> ); case 11: return ( setFormData({ ...formData, reportingStructure: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={4} totalSteps={7} sectionName="Output & Accountability" /> ); case 12: return ( handleNext()} /> ); case 13: return ( setFormData({ ...formData, closeCollaborators: value })} onNext={() => handleNext()} currentStep={1} totalSteps={7} sectionName="Team & Collaboration" /> ); case 14: return ( setFormData({ ...formData, teamCommunication: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={2} totalSteps={7} sectionName="Team & Collaboration" scale={10} /> ); case 15: return ( setFormData({ ...formData, teamSupport: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={3} totalSteps={7} sectionName="Team & Collaboration" /> ); case 16: return ( handleNext()} /> ); case 17: return ( setFormData({ ...formData, currentTools: value })} onNext={() => handleNext()} currentStep={1} totalSteps={7} sectionName="Tools & Resources" /> ); case 18: return ( setFormData({ ...formData, toolEffectiveness: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={2} totalSteps={7} sectionName="Tools & Resources" scale={10} /> ); case 19: return ( setFormData({ ...formData, missingTools: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={3} totalSteps={7} sectionName="Tools & Resources" /> ); case 20: return ( handleNext()} /> ); case 21: return ( setFormData({ ...formData, keySkills: value })} onNext={() => handleNext()} currentStep={1} totalSteps={7} sectionName="Skills & Development" /> ); case 22: return ( setFormData({ ...formData, skillDevelopment: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={2} totalSteps={7} sectionName="Skills & Development" /> ); case 23: return ( setFormData({ ...formData, awareOfTraining: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={3} totalSteps={7} sectionName="Skills & Development" /> ); case 24: return ( setFormData({ ...formData, careerGoals: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={4} totalSteps={7} sectionName="Skills & Development" /> ); case 25: return ( handleNext()} /> ); case 26: return ( setFormData({ ...formData, companyImprovements: value })} onNext={() => handleNext()} currentStep={1} totalSteps={7} sectionName="Feedback & Improvement" /> ); case 27: return ( setFormData({ ...formData, jobSatisfaction: value })} onBack={() => handleBack()} onNext={() => handleNext()} currentStep={2} totalSteps={7} sectionName="Feedback & Improvement" scale={10} /> ); case 28: return ( setFormData({ ...formData, additionalFeedback: value })} onBack={() => handleBack()} onNext={() => handleSubmit()} currentStep={3} totalSteps={7} sectionName="Feedback & Improvement" placeholder="Share any thoughts, suggestions, or feedback..." /> ); case 999: // Thank you page return ; default: return ; } }; if (isSubmitting) { return (
A

Submitting Your Responses...

Please wait while we process your assessment and generate your report.

); } return (
{renderStep()} {error && (
{error}
)}
); }; export default EmployeeQuestionnaire;