commit before mass find + replace
This commit is contained in:
707
src/pages/EmployeeQuestionnaireNew.tsx
Normal file
707
src/pages/EmployeeQuestionnaireNew.tsx
Normal file
@@ -0,0 +1,707 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useNavigate, useLocation, useParams } from 'react-router-dom';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { useOrg } from '../contexts/OrgContext';
|
||||
import { EMPLOYEE_QUESTIONS, EmployeeSubmissionAnswers } from '../employeeQuestions';
|
||||
import { API_URL } from '../constants';
|
||||
import {
|
||||
WelcomeScreen,
|
||||
SectionIntro,
|
||||
PersonalInfoForm,
|
||||
TextAreaQuestion,
|
||||
RatingScaleQuestion,
|
||||
YesNoChoice,
|
||||
ThankYouPage
|
||||
} from '../components/figma/FigmaEmployeeForms';
|
||||
|
||||
/**
|
||||
* Enhanced Employee Questionnaire with Exact Figma Design Implementation
|
||||
*
|
||||
* Features:
|
||||
* - Exact Figma design system styling
|
||||
* - Invite-based flow (no authentication required)
|
||||
* - Company owner can invite employees with metadata
|
||||
* - LLM processing via cloud functions
|
||||
* - Report generation with company context
|
||||
* - Firestore storage for reports
|
||||
*/
|
||||
|
||||
const EmployeeQuestionnaire: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const params = useParams();
|
||||
const { user } = useAuth();
|
||||
|
||||
// Check if this is an invite-based flow (no auth/org needed)
|
||||
const inviteCode = params.inviteCode;
|
||||
const isInviteFlow = !!inviteCode;
|
||||
|
||||
// Only use org context for authenticated flows
|
||||
let submitEmployeeAnswers, generateEmployeeReport, employees;
|
||||
if (!isInviteFlow) {
|
||||
const orgContext = useOrg();
|
||||
({ submitEmployeeAnswers, generateEmployeeReport, employees } = orgContext);
|
||||
} else {
|
||||
// For invite flows, we don't need these functions from org context
|
||||
submitEmployeeAnswers = null;
|
||||
generateEmployeeReport = null;
|
||||
employees = [];
|
||||
}
|
||||
|
||||
const [currentStep, setCurrentStep] = useState(1);
|
||||
const [formData, setFormData] = useState<any>({});
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
const [inviteEmployee, setInviteEmployee] = useState<any>(null);
|
||||
const [isLoadingInvite, setIsLoadingInvite] = useState(false);
|
||||
|
||||
// Load invite details if this is an invite flow
|
||||
useEffect(() => {
|
||||
if (inviteCode) {
|
||||
loadInviteDetails(inviteCode);
|
||||
}
|
||||
}, [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 multiple sources
|
||||
const invitedEmployee = location.state?.invitedEmployee;
|
||||
|
||||
// Determine current employee - for invite flow, use invite employee data
|
||||
let currentEmployee;
|
||||
if (isInviteFlow) {
|
||||
currentEmployee = inviteEmployee;
|
||||
} else {
|
||||
// Original auth-based logic
|
||||
currentEmployee = invitedEmployee || employees.find(emp => emp.email === user?.email);
|
||||
|
||||
if (!currentEmployee && user?.email) {
|
||||
// Try case-insensitive email matching
|
||||
currentEmployee = employees.find(emp =>
|
||||
emp.email?.toLowerCase() === user.email?.toLowerCase()
|
||||
);
|
||||
|
||||
if (!currentEmployee && invitedEmployee) {
|
||||
currentEmployee = employees.find(emp =>
|
||||
emp.name === invitedEmployee.name || emp.id === invitedEmployee.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Demo mode fallbacks
|
||||
if (!currentEmployee && user?.email === 'demo@auditly.local' && employees.length > 0) {
|
||||
currentEmployee = employees[employees.length - 1];
|
||||
}
|
||||
|
||||
if (!currentEmployee && employees.length === 1) {
|
||||
currentEmployee = employees[0];
|
||||
}
|
||||
}
|
||||
|
||||
const submitViaInvite = async (answers: EmployeeSubmissionAnswers, inviteCode: string) => {
|
||||
try {
|
||||
// First, consume the invite to mark it as used
|
||||
const consumeResponse = await fetch(`${API_URL}/consumeInvitation`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ code: inviteCode })
|
||||
});
|
||||
|
||||
if (!consumeResponse.ok) {
|
||||
throw new Error('Failed to process invitation');
|
||||
}
|
||||
|
||||
// Get orgId from the consume response
|
||||
const consumeData = await consumeResponse.json();
|
||||
const orgId = consumeData.orgId;
|
||||
|
||||
// Submit the questionnaire answers using Cloud Function
|
||||
// This will include company onboarding questions and answers for LLM context
|
||||
const submitResponse = await fetch(`${API_URL}/submitEmployeeAnswers`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
inviteCode: inviteCode,
|
||||
answers: answers,
|
||||
orgId: orgId,
|
||||
includeCompanyContext: true // Flag to include company Q&A in LLM processing
|
||||
})
|
||||
});
|
||||
|
||||
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: !!result.report };
|
||||
} 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 EMPLOYEE_QUESTIONS 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 - different logic for invite vs auth flow
|
||||
let result;
|
||||
if (isInviteFlow) {
|
||||
// Direct API submission for invite flow (no auth needed)
|
||||
result = await submitViaInvite(answers, inviteCode);
|
||||
} else {
|
||||
// Use org context for authenticated flow
|
||||
if (!currentEmployee) {
|
||||
// Enhanced fallback logic for authenticated users
|
||||
if (employees.length > 0) {
|
||||
let fallbackEmployee = employees.find(emp =>
|
||||
emp.email?.toLowerCase().includes(user?.email?.toLowerCase().split('@')[0] || '')
|
||||
);
|
||||
|
||||
if (!fallbackEmployee) {
|
||||
const userDomain = user?.email?.split('@')[1];
|
||||
fallbackEmployee = employees.find(emp =>
|
||||
emp.email?.split('@')[1] === userDomain
|
||||
) || employees[employees.length - 1];
|
||||
}
|
||||
|
||||
const success = await submitEmployeeAnswers(fallbackEmployee.id, answers);
|
||||
if (success) {
|
||||
try {
|
||||
const report = await generateEmployeeReport(fallbackEmployee);
|
||||
console.log('Report generated successfully:', report);
|
||||
} catch (reportError) {
|
||||
console.error('Failed to generate report:', reportError);
|
||||
}
|
||||
|
||||
// Navigate to completion
|
||||
setCurrentStep(999); // Thank you page
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setError(`We couldn't match your account (${user?.email}) with an employee record. Please contact your administrator.`);
|
||||
setIsSubmitting(false);
|
||||
return;
|
||||
}
|
||||
|
||||
result = await submitEmployeeAnswers(currentEmployee.id, answers);
|
||||
}
|
||||
|
||||
if (result.success) {
|
||||
// Show thank you page
|
||||
setCurrentStep(999);
|
||||
} else {
|
||||
setError(result.message || '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 invite flow loading state
|
||||
if (isInviteFlow && isLoadingInvite) {
|
||||
return (
|
||||
<div className="min-h-screen bg-Neutrals-NeutralSlate0 py-8 px-4 flex items-center justify-center">
|
||||
<div className="max-w-4xl mx-auto text-center">
|
||||
<div className="w-16 h-16 bg-Brand-Orange rounded-full flex items-center justify-center font-bold text-Other-White text-2xl mx-auto mb-4">
|
||||
A
|
||||
</div>
|
||||
<h1 className="text-3xl font-bold text-Neutrals-NeutralSlate950 mb-4">Loading Your Invitation...</h1>
|
||||
<p className="text-Neutrals-NeutralSlate500">Please wait while we verify your invitation.</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Early return for invite flow error state
|
||||
if (isInviteFlow && error && currentStep === 1) {
|
||||
return (
|
||||
<div className="min-h-screen bg-Neutrals-NeutralSlate0 py-8 px-4 flex items-center justify-center">
|
||||
<div className="max-w-4xl mx-auto text-center">
|
||||
<div className="w-16 h-16 bg-red-500 rounded-full flex items-center justify-center font-bold text-Other-White text-2xl mx-auto mb-4">
|
||||
!
|
||||
</div>
|
||||
<h1 className="text-3xl font-bold text-Neutrals-NeutralSlate950 mb-4">Invitation Error</h1>
|
||||
<p className="text-Neutrals-NeutralSlate500 mb-6">{error}</p>
|
||||
<button
|
||||
onClick={() => window.location.href = '/'}
|
||||
className="px-6 py-3 bg-Brand-Orange text-Other-White rounded-lg hover:bg-orange-600"
|
||||
>
|
||||
Return to Homepage
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const renderStep = () => {
|
||||
switch (currentStep) {
|
||||
case 1:
|
||||
return (
|
||||
<WelcomeScreen
|
||||
onStart={() => handleNext()}
|
||||
/>
|
||||
);
|
||||
|
||||
case 2:
|
||||
return (
|
||||
<PersonalInfoForm
|
||||
formData={{
|
||||
email: formData.email || '',
|
||||
name: formData.name || '',
|
||||
company: formData.company || ''
|
||||
}}
|
||||
onChange={(data) => setFormData({ ...formData, ...data })}
|
||||
onNext={() => handleNext()}
|
||||
/>
|
||||
);
|
||||
|
||||
case 3:
|
||||
return (
|
||||
<SectionIntro
|
||||
sectionNumber="1 of 6"
|
||||
title="Your Role & Responsibilities"
|
||||
description="Let's start by understanding your current role and daily responsibilities."
|
||||
onStart={() => handleNext()}
|
||||
/>
|
||||
);
|
||||
|
||||
case 4:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="What is your current title and department?"
|
||||
value={formData.titleAndDepartment || ''}
|
||||
onChange={(value) => setFormData({ ...formData, titleAndDepartment: value })}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={1}
|
||||
totalSteps={7}
|
||||
sectionName="Your Role & Responsibilities"
|
||||
/>
|
||||
);
|
||||
|
||||
case 5:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="Describe your core daily responsibilities"
|
||||
value={formData.dailyResponsibilities || ''}
|
||||
onChange={(value) => 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 (
|
||||
<RatingScaleQuestion
|
||||
question="How clearly do you understand your role and responsibilities?"
|
||||
leftLabel="Not clear"
|
||||
rightLabel="Very clear"
|
||||
value={formData.roleClarity}
|
||||
onChange={(value) => setFormData({ ...formData, roleClarity: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={3}
|
||||
totalSteps={7}
|
||||
sectionName="Your Role & Responsibilities"
|
||||
scale={10}
|
||||
/>
|
||||
);
|
||||
|
||||
case 7:
|
||||
return (
|
||||
<SectionIntro
|
||||
sectionNumber="2 of 6"
|
||||
title="Output & Accountability"
|
||||
description="Let's explore your work output, goals, and accountability measures."
|
||||
onStart={() => handleNext()}
|
||||
/>
|
||||
);
|
||||
|
||||
case 8:
|
||||
return (
|
||||
<RatingScaleQuestion
|
||||
question="How would you rate your weekly output (volume & quality)?"
|
||||
leftLabel="Very little"
|
||||
rightLabel="Very High"
|
||||
value={formData.weeklyOutput}
|
||||
onChange={(value) => setFormData({ ...formData, weeklyOutput: value })}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={1}
|
||||
totalSteps={7}
|
||||
sectionName="Output & Accountability"
|
||||
scale={10}
|
||||
/>
|
||||
);
|
||||
|
||||
case 9:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="What are your top 2–3 recurring deliverables?"
|
||||
value={formData.topDeliverables || ''}
|
||||
onChange={(value) => setFormData({ ...formData, topDeliverables: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={2}
|
||||
totalSteps={7}
|
||||
sectionName="Output & Accountability"
|
||||
/>
|
||||
);
|
||||
|
||||
case 10:
|
||||
return (
|
||||
<YesNoChoice
|
||||
question="Do you have weekly KPIs or goals?"
|
||||
value={formData.hasKPIs}
|
||||
onChange={(value) => setFormData({ ...formData, hasKPIs: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={3}
|
||||
totalSteps={7}
|
||||
sectionName="Output & Accountability"
|
||||
/>
|
||||
);
|
||||
|
||||
case 11:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="Who do you report to? How often do you meet/check-in?"
|
||||
value={formData.reportingStructure || ''}
|
||||
onChange={(value) => setFormData({ ...formData, reportingStructure: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={4}
|
||||
totalSteps={7}
|
||||
sectionName="Output & Accountability"
|
||||
/>
|
||||
);
|
||||
|
||||
case 12:
|
||||
return (
|
||||
<SectionIntro
|
||||
sectionNumber="3 of 6"
|
||||
title="Team & Collaboration"
|
||||
description="Let's understand your team dynamics and collaboration patterns."
|
||||
onStart={() => handleNext()}
|
||||
/>
|
||||
);
|
||||
|
||||
case 13:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="Who do you work most closely with?"
|
||||
value={formData.closeCollaborators || ''}
|
||||
onChange={(value) => setFormData({ ...formData, closeCollaborators: value })}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={1}
|
||||
totalSteps={7}
|
||||
sectionName="Team & Collaboration"
|
||||
/>
|
||||
);
|
||||
|
||||
case 14:
|
||||
return (
|
||||
<RatingScaleQuestion
|
||||
question="How would you rate team communication overall?"
|
||||
leftLabel="Poor"
|
||||
rightLabel="Excellent"
|
||||
value={formData.teamCommunication}
|
||||
onChange={(value) => setFormData({ ...formData, teamCommunication: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={2}
|
||||
totalSteps={7}
|
||||
sectionName="Team & Collaboration"
|
||||
scale={10}
|
||||
/>
|
||||
);
|
||||
|
||||
case 15:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="Do you feel supported by your team? How?"
|
||||
value={formData.teamSupport || ''}
|
||||
onChange={(value) => setFormData({ ...formData, teamSupport: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={3}
|
||||
totalSteps={7}
|
||||
sectionName="Team & Collaboration"
|
||||
/>
|
||||
);
|
||||
|
||||
case 16:
|
||||
return (
|
||||
<SectionIntro
|
||||
sectionNumber="4 of 6"
|
||||
title="Tools & Resources"
|
||||
description="Let's examine the tools and resources available to support your work."
|
||||
onStart={() => handleNext()}
|
||||
/>
|
||||
);
|
||||
|
||||
case 17:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="What tools and software do you currently use?"
|
||||
value={formData.currentTools || ''}
|
||||
onChange={(value) => setFormData({ ...formData, currentTools: value })}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={1}
|
||||
totalSteps={7}
|
||||
sectionName="Tools & Resources"
|
||||
/>
|
||||
);
|
||||
|
||||
case 18:
|
||||
return (
|
||||
<RatingScaleQuestion
|
||||
question="How effective are your current tools?"
|
||||
leftLabel="Not effective"
|
||||
rightLabel="Very effective"
|
||||
value={formData.toolEffectiveness}
|
||||
onChange={(value) => setFormData({ ...formData, toolEffectiveness: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={2}
|
||||
totalSteps={7}
|
||||
sectionName="Tools & Resources"
|
||||
scale={10}
|
||||
/>
|
||||
);
|
||||
|
||||
case 19:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="What tools or resources are you missing to do your job more effectively?"
|
||||
value={formData.missingTools || ''}
|
||||
onChange={(value) => setFormData({ ...formData, missingTools: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={3}
|
||||
totalSteps={7}
|
||||
sectionName="Tools & Resources"
|
||||
/>
|
||||
);
|
||||
|
||||
case 20:
|
||||
return (
|
||||
<SectionIntro
|
||||
sectionNumber="5 of 6"
|
||||
title="Skills & Development"
|
||||
description="Let's explore your skills, growth opportunities, and career development."
|
||||
onStart={() => handleNext()}
|
||||
/>
|
||||
);
|
||||
|
||||
case 21:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="What are your key skills and strengths?"
|
||||
value={formData.keySkills || ''}
|
||||
onChange={(value) => setFormData({ ...formData, keySkills: value })}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={1}
|
||||
totalSteps={7}
|
||||
sectionName="Skills & Development"
|
||||
/>
|
||||
);
|
||||
|
||||
case 22:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="What skills would you like to develop or improve?"
|
||||
value={formData.skillDevelopment || ''}
|
||||
onChange={(value) => setFormData({ ...formData, skillDevelopment: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={2}
|
||||
totalSteps={7}
|
||||
sectionName="Skills & Development"
|
||||
/>
|
||||
);
|
||||
|
||||
case 23:
|
||||
return (
|
||||
<YesNoChoice
|
||||
question="Are you aware of current training opportunities?"
|
||||
value={formData.awareOfTraining}
|
||||
onChange={(value) => setFormData({ ...formData, awareOfTraining: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={3}
|
||||
totalSteps={7}
|
||||
sectionName="Skills & Development"
|
||||
/>
|
||||
);
|
||||
|
||||
case 24:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="What are your career goals within the company?"
|
||||
value={formData.careerGoals || ''}
|
||||
onChange={(value) => setFormData({ ...formData, careerGoals: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={4}
|
||||
totalSteps={7}
|
||||
sectionName="Skills & Development"
|
||||
/>
|
||||
);
|
||||
|
||||
case 25:
|
||||
return (
|
||||
<SectionIntro
|
||||
sectionNumber="6 of 6"
|
||||
title="Feedback & Improvement"
|
||||
description="Finally, let's gather your thoughts on company improvements and overall satisfaction."
|
||||
onStart={() => handleNext()}
|
||||
/>
|
||||
);
|
||||
|
||||
case 26:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="What improvements would you suggest for the company?"
|
||||
value={formData.companyImprovements || ''}
|
||||
onChange={(value) => setFormData({ ...formData, companyImprovements: value })}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={1}
|
||||
totalSteps={7}
|
||||
sectionName="Feedback & Improvement"
|
||||
/>
|
||||
);
|
||||
|
||||
case 27:
|
||||
return (
|
||||
<RatingScaleQuestion
|
||||
question="How satisfied are you with your current job overall?"
|
||||
leftLabel="Not satisfied"
|
||||
rightLabel="Very satisfied"
|
||||
value={formData.jobSatisfaction}
|
||||
onChange={(value) => setFormData({ ...formData, jobSatisfaction: value })}
|
||||
onBack={() => handleBack()}
|
||||
onNext={() => handleNext()}
|
||||
currentStep={2}
|
||||
totalSteps={7}
|
||||
sectionName="Feedback & Improvement"
|
||||
scale={10}
|
||||
/>
|
||||
);
|
||||
|
||||
case 28:
|
||||
return (
|
||||
<TextAreaQuestion
|
||||
question="Any additional feedback or suggestions for the company?"
|
||||
value={formData.additionalFeedback || ''}
|
||||
onChange={(value) => 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 <ThankYouPage />;
|
||||
|
||||
default:
|
||||
return <ThankYouPage />;
|
||||
}
|
||||
};
|
||||
|
||||
if (isSubmitting) {
|
||||
return (
|
||||
<div className="min-h-screen bg-Neutrals-NeutralSlate0 py-8 px-4 flex items-center justify-center">
|
||||
<div className="max-w-4xl mx-auto text-center">
|
||||
<div className="w-16 h-16 bg-Brand-Orange rounded-full flex items-center justify-center font-bold text-Other-White text-2xl mx-auto mb-4 animate-pulse">
|
||||
A
|
||||
</div>
|
||||
<h1 className="text-3xl font-bold text-Neutrals-NeutralSlate950 mb-4">Submitting Your Responses...</h1>
|
||||
<p className="text-Neutrals-NeutralSlate500">Please wait while we process your assessment and generate your report.</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
{renderStep()}
|
||||
{error && (
|
||||
<div className="fixed bottom-4 right-4 bg-red-500 text-white p-4 rounded-lg shadow-lg z-50">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmployeeQuestionnaire;
|
||||
Reference in New Issue
Block a user