Fixed skipping Financial Onboarding. and Program Length calc for Undergrad Cert.

This commit is contained in:
Josh 2025-07-18 13:11:29 +00:00
parent a8b028993a
commit fdcae3bdfb
3 changed files with 85 additions and 58 deletions

View File

@ -79,7 +79,12 @@ const CareerOnboarding = ({ nextStep, prevStep, data, setData }) => {
projected_end_date: prevData.projected_end_date || null
}));
nextStep();
if (!showFinPrompt || financialReady) {
nextStep();
} else {
}
};
return (
@ -111,7 +116,7 @@ const CareerOnboarding = ({ nextStep, prevStep, data, setData }) => {
{/* 2) Replace old local “Search for Career” with <CareerSearch/> */}
<div className="space-y-2">
<h3 className="font-medium">
What career are you planning to pursue? <Req />
What career are you planning to pursue? (Please select from drop-down suggestions after typing)<Req />
</h3>
<p className="text-sm text-gray-600">
This should be your <strong>target career path</strong> whether its a new goal or the one you're already in.
@ -206,9 +211,11 @@ const CareerOnboarding = ({ nextStep, prevStep, data, setData }) => {
<button
className="bg-gray-200 hover:bg-gray-300 text-gray-800 py-1 px-3 rounded"
onClick={() => {
setFinancialReady(false); // they chose to skip
setShowFinPrompt(false);
nextStep(); // continue onboarding
/* mark intent to skip the finance step */
setData(prev => ({ ...prev, skipFinancialStep: true }));
setFinancialReady(false);
setShowFinPrompt(false); // hide the prompt, stay on page
}}
>
Skip for Now

View File

@ -9,6 +9,8 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData }) {
const [schoolSuggestions, setSchoolSuggestions] = useState([]);
const [programSuggestions, setProgramSuggestions] = useState([]);
const [availableProgramTypes, setAvailableProgramTypes] = useState([]);
const [schoolValid, setSchoolValid] = useState(false);
const [programValid, setProgramValid] = useState(false);
// Show/hide the financial aid wizard
const [showAidWizard, setShowAidWizard] = useState(false);
@ -283,49 +285,34 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData }) {
]);
// auto-calc program length
useEffect(() => {
// If user hasn't selected a program type or credit_hours_per_year is missing, skip
if (!program_type) return;
if (!credit_hours_per_year) return;
useEffect(() => {
if (!program_type || !credit_hours_per_year) return;
// If hours_completed is blank, treat as 0
const completed = parseInt(hours_completed, 10) || 0;
const perYear = parseFloat(credit_hours_per_year) || 1;
const perYear = parseFloat(credit_hours_per_year) || 1;
let required = 0;
switch (program_type) {
case "Associate's Degree":
required = 60; // total for an associate's
break;
case "Bachelor's Degree":
required = 120; // total for a bachelor's
break;
case "Master's Degree":
required = 180; // e.g. 120 undergrad + 60 grad
break;
case "Doctoral Degree":
required = 240; // e.g. 120 undergrad + 120 grad
break;
case "First Professional Degree":
// If you want 180 or 240, up to you
required = 180;
break;
case "Associate's Degree": required = 60; break;
case "Bachelor's Degree": required = 120; break;
case "Master's Degree": required = 180; break;
case "Doctoral Degree": required = 240; break;
case "First Professional Degree": required = 180; break;
case "Graduate/Professional Certificate":
// Possibly read from credit_hours_required
required = parseInt(credit_hours_required, 10) || 0;
break;
case "Undergraduate Certificate or Diploma":
required = parseInt(credit_hours_required, 10) || 30; // sensible default
break;
default:
// For any other program type, use whatever is in credit_hours_required
required = parseInt(credit_hours_required, 10) || 0;
break;
}
// Subtract however many credits they've already completed (that count)
const remain = required - completed;
const yrs = remain / perYear;
const calcLength = yrs.toFixed(2);
/* never negative */
const remain = Math.max(0, required - completed);
const yrs = remain / perYear;
setAutoProgramLength(calcLength);
setAutoProgramLength(yrs.toFixed(2));
}, [
program_type,
hours_completed,
@ -333,9 +320,6 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData }) {
credit_hours_required
]);
// final handleSubmit => we store chosen tuition + program_length, then move on
const handleSubmit = () => {
const chosenTuition = manualTuition.trim() === ''
@ -358,6 +342,12 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData }) {
const displayedTuition = (manualTuition.trim() === '' ? autoTuition : manualTuition);
const displayedProgramLength = (manualProgramLength.trim() === '' ? autoProgramLength : manualProgramLength);
const ready =
(college_enrollment_status === 'currently_enrolled' ||
college_enrollment_status === 'prospective_student')
? schoolValid && programValid && program_type
: true;
return (
<div className="max-w-md mx-auto p-6 space-y-4">
<h2 className="text-2xl font-semibold">College Details</h2>
@ -412,14 +402,21 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData }) {
{/* School */}
<div className="space-y-1">
<label className="block font-medium">School Name* {infoIcon("Start typing and click from auto-suggest")}</label>
<label className="block font-medium">School Name* (Please select from drop-down after typing){infoIcon("Start typing and click from auto-suggest")}</label>
<input
name="selected_school"
value={selected_school}
onChange={handleSchoolChange}
onBlur={() => {
const ok = schoolData.some(
s => s.INSTNM.toLowerCase() === selected_school.toLowerCase()
);
setSchoolValid(ok);
if (!ok) alert("Please pick a school from the list.");
}}
list="school-suggestions"
placeholder="Enter school name..."
className="w-full border rounded p-2"
className={`w-full border rounded p-2 ${schoolValid ? '' : 'border-red-500'}`}
placeholder="Start typing and choose…"
/>
<datalist id="school-suggestions">
{schoolSuggestions.map((sch, idx) => (
@ -433,14 +430,25 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData }) {
</div>
<div className="space-y-1">
<label className="block font-medium">Marjor/Program Name* {infoIcon("Search and click from auto-suggest. If for some reason your major isn't listed, please send us a note.")}</label>
<label className="block font-medium">Marjor/Program Name* (Please select from drop-down after typing){infoIcon("Search and click from auto-suggest. If for some reason your major isn't listed, please send us a note.")}</label>
<input
name="selected_program"
value={selected_program}
onChange={handleProgramChange}
onBlur={() => {
const ok =
selected_school && // need a school first
schoolData.some(
s =>
s.INSTNM.toLowerCase() === selected_school.toLowerCase() &&
s.CIPDESC.toLowerCase() === selected_program.toLowerCase()
);
setProgramValid(ok);
if (!ok) alert("Please pick a program from the list.");
}}
list="program-suggestions"
placeholder="Enter program name..."
className="w-full border rounded p-2"
className={`w-full border rounded p-2 ${programValid ? '' : 'border-red-500'}`}
placeholder="Start typing and choose…"
/>
<datalist id="program-suggestions">
{programSuggestions.map((prog, idx) => (
@ -487,9 +495,11 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData }) {
{/* If Grad/Professional => credit_hours_required */}
{(program_type === 'Graduate/Professional Certificate' ||
program_type === 'First Professional Degree' ||
program_type === 'Doctoral Degree') && (
program_type === 'Doctoral Degree' ||
program_type === 'Undergraduate Certificate or Diploma'
) && (
<div className="space-y-1">
<label className="block font-medium">Credit Hours Required {infoIcon("Some Graduate and Professional Programs differ on number of hours required.")}</label>
<label className="block font-medium">Credit Hours Required {infoIcon("Some Certificate, Graduate, and Professional Programs differ on number of hours required.")}</label>
<input
type="number"
name="credit_hours_required"
@ -639,7 +649,7 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData }) {
</div>
<div className="space-y-1">
<label className="block font-medium">Expected Salary After Graduation {infoIcon("If you're just starting out, expect towards the 10th percentile values for your targeted career.")}</label>
<label className="block font-medium">Expected Salary After Graduation {infoIcon("If you're just starting out, expect towards the 10th percentile values for your targeted career. Can be found using Career Explorer if needed or input later.")}</label>
<input
type="number"
name="expected_salary"
@ -664,7 +674,11 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData }) {
</button>
<button
onClick={handleSubmit}
className="bg-blue-500 hover:bg-blue-600 text-white font-semibold py-2 px-4 rounded"
disabled={!ready}
className={`py-2 px-4 rounded font-semibold
${ready
? 'bg-blue-500 hover:bg-blue-600 text-white'
: 'bg-gray-300 text-gray-500 cursor-not-allowed'}`}
>
Finish Onboarding
</button>

View File

@ -24,6 +24,7 @@ const OnboardingContainer = () => {
const [financialData, setFinancialData] = useState({});
const [collegeData, setCollegeData] = useState({});
const [lastSelectedCareerProfileId, setLastSelectedCareerProfileId] = useState();
const skipFin = careerData.skipFinancialStep;
useEffect(() => {
// 1) Load premiumOnboardingState
@ -60,7 +61,6 @@ const OnboardingContainer = () => {
setCollegeData(localCollegeData);
}, []);
// 3. Whenever any key pieces of state change, save to localStorage
useEffect(() => {
const stateToStore = {
@ -213,15 +213,21 @@ navigate(`/career-roadmap/${finalCareerProfileId}`, {
setData={setCareerData}
/>,
<FinancialOnboarding
nextStep={nextStep}
prevStep={prevStep}
data={{
...financialData,
currently_working: careerData.currently_working,
}}
setData={setFinancialData}
/>,
/* insert **only if** the user did NOT press “Skip for now” */
...(!skipFin
? [
<FinancialOnboarding
key="fin"
nextStep={nextStep}
prevStep={prevStep}
data={{
...financialData,
currently_working: careerData.currently_working,
}}
setData={setFinancialData}
/>,
]
: []),
<CollegeOnboarding
prevStep={prevStep}