166 lines
5.1 KiB
JavaScript
166 lines
5.1 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import PremiumWelcome from './PremiumWelcome.js';
|
|
import CareerOnboarding from './CareerOnboarding.js';
|
|
import FinancialOnboarding from './FinancialOnboarding.js';
|
|
import CollegeOnboarding from './CollegeOnboarding.js';
|
|
import ReviewPage from './ReviewPage.js';
|
|
|
|
import authFetch from '../../utils/authFetch.js';
|
|
|
|
const OnboardingContainer = () => {
|
|
console.log('OnboardingContainer MOUNT');
|
|
|
|
const navigate = useNavigate();
|
|
|
|
// 1. Local state for multi-step onboarding
|
|
const [step, setStep] = useState(0);
|
|
const [careerData, setCareerData] = useState({});
|
|
const [financialData, setFinancialData] = useState({});
|
|
const [collegeData, setCollegeData] = useState({});
|
|
|
|
// 2. On mount, check if localStorage has onboarding data
|
|
useEffect(() => {
|
|
const stored = localStorage.getItem('premiumOnboardingState');
|
|
if (stored) {
|
|
try {
|
|
const parsed = JSON.parse(stored);
|
|
// Restore step and data if they exist
|
|
if (parsed.step !== undefined) setStep(parsed.step);
|
|
if (parsed.careerData) setCareerData(parsed.careerData);
|
|
if (parsed.financialData) setFinancialData(parsed.financialData);
|
|
if (parsed.collegeData) setCollegeData(parsed.collegeData);
|
|
} catch (err) {
|
|
console.warn('Failed to parse premiumOnboardingState:', err);
|
|
}
|
|
}
|
|
}, []);
|
|
|
|
// 3. Whenever any key pieces of state change, save to localStorage
|
|
useEffect(() => {
|
|
const stateToStore = {
|
|
step,
|
|
careerData,
|
|
financialData,
|
|
collegeData
|
|
};
|
|
localStorage.setItem('premiumOnboardingState', JSON.stringify(stateToStore));
|
|
}, [step, careerData, financialData, collegeData]);
|
|
|
|
// Move user to next or previous step
|
|
const nextStep = () => setStep((prev) => prev + 1);
|
|
const prevStep = () => setStep((prev) => prev - 1);
|
|
|
|
function parseFloatOrNull(value) {
|
|
if (value == null || value === '') {
|
|
return null;
|
|
}
|
|
const parsed = parseFloat(value);
|
|
return isNaN(parsed) ? null : parsed;
|
|
}
|
|
|
|
console.log('Final collegeData in OnboardingContainer:', collegeData);
|
|
|
|
// 4. Final “all done” submission
|
|
const handleFinalSubmit = async () => {
|
|
try {
|
|
const scenarioPayload = {
|
|
...careerData,
|
|
};
|
|
|
|
// 1) POST career-profile (scenario)
|
|
const careerRes = await authFetch('/api/premium/career-profile', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(scenarioPayload),
|
|
});
|
|
if (!careerRes.ok) throw new Error('Failed to save career profile');
|
|
const careerJson = await careerRes.json();
|
|
const { career_profile_id } = careerJson;
|
|
if (!career_profile_id) {
|
|
throw new Error('No career_profile_id returned by server');
|
|
}
|
|
|
|
// 2) POST financial-profile
|
|
const financialRes = await authFetch('/api/premium/financial-profile', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(financialData),
|
|
});
|
|
if (!financialRes.ok) throw new Error('Failed to save financial profile');
|
|
|
|
// 3) Possibly POST college-profile
|
|
if (
|
|
careerData.college_enrollment_status === 'currently_enrolled' ||
|
|
careerData.college_enrollment_status === 'prospective_student'
|
|
) {
|
|
const mergedCollege = {
|
|
...collegeData,
|
|
career_profile_id,
|
|
college_enrollment_status: careerData.college_enrollment_status,
|
|
};
|
|
const collegeRes = await authFetch('/api/premium/college-profile', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(mergedCollege),
|
|
});
|
|
if (!collegeRes.ok) throw new Error('Failed to save college profile');
|
|
} else {
|
|
console.log('Skipping college-profile upsert because user is not enrolled/planning.');
|
|
}
|
|
|
|
// 4) Clear localStorage so next onboarding starts fresh (optional)
|
|
localStorage.removeItem('premiumOnboardingState');
|
|
|
|
// 5) Navigate away
|
|
navigate('/career-roadmap');
|
|
} catch (err) {
|
|
console.error(err);
|
|
// Optionally show error to user
|
|
}
|
|
};
|
|
|
|
// 5. Array of steps
|
|
const onboardingSteps = [
|
|
<PremiumWelcome nextStep={nextStep} />,
|
|
|
|
<CareerOnboarding
|
|
nextStep={nextStep}
|
|
data={careerData}
|
|
setData={setCareerData}
|
|
/>,
|
|
|
|
<FinancialOnboarding
|
|
nextStep={nextStep}
|
|
prevStep={prevStep}
|
|
data={{
|
|
...financialData,
|
|
currently_working: careerData.currently_working,
|
|
}}
|
|
setData={setFinancialData}
|
|
/>,
|
|
|
|
<CollegeOnboarding
|
|
prevStep={prevStep}
|
|
nextStep={nextStep}
|
|
data={{
|
|
...collegeData,
|
|
college_enrollment_status: careerData.college_enrollment_status,
|
|
}}
|
|
setData={setCollegeData}
|
|
/>,
|
|
|
|
<ReviewPage
|
|
careerData={careerData}
|
|
financialData={financialData}
|
|
collegeData={collegeData}
|
|
onSubmit={handleFinalSubmit}
|
|
onBack={prevStep}
|
|
/>,
|
|
];
|
|
|
|
return <div>{onboardingSteps[step]}</div>;
|
|
};
|
|
|
|
export default OnboardingContainer;
|