dev1/src/components/PremiumOnboarding/CollegeOnboarding.js

859 lines
31 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from 'react';
import Modal from '../../components/ui/modal.js';
import FinancialAidWizard from '../../components/FinancialAidWizard.js';
import { useLocation } from 'react-router-dom';
const Req = () => <span className="text-red-600 ml-0.5">*</span>;
function CollegeOnboarding({ nextStep, prevStep, data, setData }) {
// CIP / iPEDS local states
const [schoolData, setSchoolData] = useState([]);
const [icTuitionData, setIcTuitionData] = useState([]);
const [schoolSuggestions, setSchoolSuggestions] = useState([]);
const [programSuggestions, setProgramSuggestions] = useState([]);
const [availableProgramTypes, setAvailableProgramTypes] = useState([]);
const [schoolValid, setSchoolValid] = useState(false);
const [programValid, setProgramValid] = useState(false);
const [enrollmentDate, setEnrollmentDate] = useState(
data.enrollment_date || '' // carry forward if the user goes back
);
const [expectedGraduation, setExpectedGraduation] = useState(data.expected_graduation || '');
// Show/hide the financial aid wizard
const [showAidWizard, setShowAidWizard] = useState(false);
const location = useLocation();
const navSelectedSchoolRaw = location.state?.selectedSchool;
const navSelectedSchool = toSchoolName(navSelectedSchoolRaw);
function dehydrate(schObj) {
if (!schObj || typeof schObj !== 'object') return null;
/* keep only the fields you really need */
const { INSTNM, CIPDESC, CREDDESC, ...rest } = schObj;
return { INSTNM, CIPDESC, CREDDESC, ...rest };
}
const [selectedSchool, setSelectedSchool] = useState(() =>
dehydrate(navSelectedSchool) ||
dehydrate(JSON.parse(localStorage.getItem('premiumOnboardingState') || '{}'
).collegeData?.selectedSchool)
);
function toSchoolName(objOrStr) {
if (!objOrStr) return '';
if (typeof objOrStr === 'object') return objOrStr.INSTNM || '';
return objOrStr; // already a string
}
const infoIcon = (msg) => (
<span
className="ml-1 inline-flex h-4 w-4 items-center justify-center rounded-full bg-blue-500 text-white text-xs cursor-help"
title={msg}
>
i
</span>
);
// Destructure parent data
const {
college_enrollment_status = '',
selected_school = selectedSchool,
selected_program = '',
program_type = '',
academic_calendar = 'semester',
annual_financial_aid = '',
is_online = false,
existing_college_debt = '',
enrollment_date = '',
expected_graduation = '',
interest_rate = 5.5,
loan_term = 10,
extra_payment = '',
expected_salary = '',
is_in_state = false,
is_in_district = false,
loan_deferral_until_graduation = false,
credit_hours_per_year = '',
hours_completed = '',
credit_hours_required = '',
tuition_paid = '',
} = data;
// Local states for auto/manual logic on tuition & program length
const [manualTuition, setManualTuition] = useState('');
const [autoTuition, setAutoTuition] = useState(0);
const [manualProgramLength, setManualProgramLength] = useState('');
const [autoProgramLength, setAutoProgramLength] = useState(0);
const inSchool = ['currently_enrolled','prospective_student']
.includes(college_enrollment_status);
useEffect(() => {
if (selectedSchool) {
setData(prev => ({
...prev,
selected_school : selectedSchool.INSTNM,
selected_program: selectedSchool.CIPDESC || prev.selected_program,
program_type : selectedSchool.CREDDESC || prev.program_type
}));
}
}, [selectedSchool, setData]);
useEffect(() => {
if (data.expected_graduation && !expectedGraduation)
setExpectedGraduation(data.expected_graduation);
}, [data.expected_graduation]);
/**
* handleParentFieldChange
* If user leaves numeric fields blank, store '' in local state, not 0.
* Only parseFloat if there's an actual numeric value.
*/
const handleParentFieldChange = (e) => {
const { name, value, type, checked } = e.target;
let val = value;
if (type === 'checkbox') {
val = checked;
setData(prev => ({ ...prev, [name]: val }));
return;
}
// If the user typed an empty string, store '' so they can see it's blank
if (val.trim() === '') {
setData(prev => ({ ...prev, [name]: '' }));
return;
}
// Otherwise, parse it if it's one of the numeric fields
if (['interest_rate', 'loan_term', 'extra_payment', 'expected_salary'].includes(name)) {
const parsed = parseFloat(val);
// If parse fails => store '' (or fallback to old value)
if (isNaN(parsed)) {
setData(prev => ({ ...prev, [name]: '' }));
} else {
setData(prev => ({ ...prev, [name]: parsed }));
}
} else if ([
'annual_financial_aid','existing_college_debt','credit_hours_per_year',
'hours_completed','credit_hours_required','tuition_paid'
].includes(name)) {
const parsed = parseFloat(val);
setData(prev => ({ ...prev, [name]: isNaN(parsed) ? '' : parsed }));
} else {
// For non-numeric or strings
setData(prev => ({ ...prev, [name]: val }));
}
};
const handleManualTuitionChange = (e) => {
setManualTuition(e.target.value);
};
const handleManualProgramLengthChange = (e) => {
setManualProgramLength(e.target.value);
};
// CIP data
useEffect(() => {
async function fetchCipData() {
try {
const res = await fetch('/cip_institution_mapping_new.json');
const text = await res.text();
const lines = text.split('\n');
const parsed = lines.map(line => {
try { return JSON.parse(line); } catch { return null; }
}).filter(Boolean);
setSchoolData(parsed);
} catch (err) {
console.error("Failed to load CIP data:", err);
}
}
fetchCipData();
}, []);
// iPEDS data
useEffect(() => {
async function fetchIpedsData() {
try {
const res = await fetch('/ic2023_ay.csv');
const text = await res.text();
const rows = text.split('\n').map(line => line.split(','));
const headers = rows[0];
const dataRows = rows.slice(1).map(row =>
Object.fromEntries(row.map((val, idx) => [headers[idx], val]))
);
setIcTuitionData(dataRows);
} catch (err) {
console.error("Failed to load iPEDS data:", err);
}
}
fetchIpedsData();
}, []);
useEffect(() => {
if (college_enrollment_status !== 'prospective_student') return;
const lenYears = Number(data.program_length || '');
if (!enrollmentDate || !lenYears) return;
const start = new Date(enrollmentDate);
const est = new Date(start.getFullYear() + lenYears, start.getMonth(), start.getDate());
const iso = firstOfNextMonth(est);
setExpectedGraduation(iso);
setData(prev => ({ ...prev, expected_graduation: iso }));
}, [college_enrollment_status, enrollmentDate, data.program_length, setData]);
// School Name
const handleSchoolChange = (eOrVal) => {
const value =
typeof eOrVal === 'string' ? eOrVal : eOrVal?.target?.value || '';
setData(prev => ({
...prev,
selected_school: value,
selected_program: '',
program_type: '',
credit_hours_required: '',
}));
const filtered = schoolData.filter(s =>
s.INSTNM.toLowerCase().includes(value.toLowerCase())
);
const uniqueSchools = [...new Set(filtered.map(s => s.INSTNM))];
setSchoolSuggestions(uniqueSchools.slice(0, 10));
setProgramSuggestions([]);
setAvailableProgramTypes([]);
};
const handleSchoolSelect = (schoolName) => {
setData(prev => ({
...prev,
selected_school: schoolName,
selected_program: '',
program_type: '',
credit_hours_required: '',
}));
setSchoolSuggestions([]);
setProgramSuggestions([]);
setAvailableProgramTypes([]);
};
// Program
const handleProgramChange = (e) => {
const value = e.target.value;
setData(prev => ({ ...prev, selected_program: value }));
if (!value) {
setProgramSuggestions([]);
return;
}
const filtered = schoolData.filter(
s => s.INSTNM.toLowerCase() === selected_school.toLowerCase() &&
s.CIPDESC.toLowerCase().includes(value.toLowerCase())
);
const uniquePrograms = [...new Set(filtered.map(s => s.CIPDESC))];
setProgramSuggestions(uniquePrograms.slice(0, 10));
};
const handleProgramSelect = (prog) => {
setData(prev => ({ ...prev, selected_program: prog }));
setProgramSuggestions([]);
};
const handleProgramTypeSelect = (e) => {
const val = e.target.value;
setData(prev => ({
...prev,
program_type: val,
credit_hours_required: '',
}));
setManualProgramLength('');
setAutoProgramLength('0.00');
};
// once we have school+program => load possible program types
useEffect(() => {
if (!selected_program || !selected_school || !schoolData.length) return;
const possibleTypes = schoolData
.filter(
s => s.INSTNM.toLowerCase() === selected_school.toLowerCase() &&
s.CIPDESC === selected_program
)
.map(s => s.CREDDESC);
setAvailableProgramTypes([...new Set(possibleTypes)]);
}, [selected_program, selected_school, schoolData]);
// auto-calc tuition
useEffect(() => {
if (!icTuitionData.length) return;
if (!selected_school || !program_type || !credit_hours_per_year) return;
const found = schoolData.find(
s => s.INSTNM.toLowerCase() === selected_school.toLowerCase()
);
if (!found) return;
const unitId = found.UNITID;
if (!unitId) return;
const match = icTuitionData.find(row => row.UNITID === unitId);
if (!match) return;
const isGradOrProf = [
"Master's Degree",
"Doctoral Degree",
"Graduate/Professional Certificate",
"First Professional Degree"
].includes(program_type);
let partTimeRate = 0;
let fullTimeTuition = 0;
if (isGradOrProf) {
if (is_in_district) {
partTimeRate = parseFloat(match.HRCHG5 || 0);
fullTimeTuition = parseFloat(match.TUITION5 || 0);
} else if (is_in_state) {
partTimeRate = parseFloat(match.HRCHG6 || 0);
fullTimeTuition = parseFloat(match.TUITION6 || 0);
} else {
partTimeRate = parseFloat(match.HRCHG7 || 0);
fullTimeTuition = parseFloat(match.TUITION7 || 0);
}
} else {
// undergrad
if (is_in_district) {
partTimeRate = parseFloat(match.HRCHG1 || 0);
fullTimeTuition = parseFloat(match.TUITION1 || 0);
} else if (is_in_state) {
partTimeRate = parseFloat(match.HRCHG2 || 0);
fullTimeTuition = parseFloat(match.TUITION2 || 0);
} else {
partTimeRate = parseFloat(match.HRCHG3 || 0);
fullTimeTuition = parseFloat(match.TUITION3 || 0);
}
}
const chpy = parseFloat(credit_hours_per_year) || 0;
let estimate = 0;
if (chpy < 24 && partTimeRate) {
estimate = partTimeRate * chpy;
} else {
estimate = fullTimeTuition;
}
setAutoTuition(Math.round(estimate));
}, [
icTuitionData, selected_school, program_type,
credit_hours_per_year, is_in_state, is_in_district, schoolData
]);
// auto-calc program length
useEffect(() => {
if (!program_type || !credit_hours_per_year) return;
const completed = parseInt(hours_completed, 10) || 0;
const perYear = parseFloat(credit_hours_per_year) || 1;
let required = 0;
switch (program_type) {
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":
required = parseInt(credit_hours_required, 10) || 0;
break;
case "Undergraduate Certificate or Diploma":
required = parseInt(credit_hours_required, 10) || 30; // sensible default
break;
default:
required = parseInt(credit_hours_required, 10) || 0;
}
/* never negative */
const remain = Math.max(0, required - completed);
const yrs = remain / perYear;
setAutoProgramLength(parseFloat(yrs.toFixed(2)));
}, [
program_type,
hours_completed,
credit_hours_per_year,
credit_hours_required,
]);
/* ------------------------------------------------------------------ */
/* Whenever the user changes enrollmentDate OR programLength */
/* (program_length is already in parent data), compute grad date. */
/* ------------------------------------------------------------------ */
useEffect(() => {
/* decide which “length” the user is looking at right now */
const lenRaw =
manualProgramLength.trim() !== ''
? manualProgramLength
: autoProgramLength;
const len = parseFloat(lenRaw); // years (may be fractional)
const startISO = pickStartDate(); // '' or yyyymmdd
if (!startISO || !len) return; // nothing to do yet
const start = new Date(startISO);
/* naïve add assuming program_length is years; *
* adjust if you store months instead */
/* 1year = 12months preserve fractions (e.g. 1.75y = 21m) */
const monthsToAdd = Math.round(len * 12);
const estGrad = new Date(start); // clone
estGrad.setMonth(estGrad.getMonth() + monthsToAdd);
const gradISO = firstOfNextMonth(estGrad);
setExpectedGraduation(gradISO);
setData(prev => ({ ...prev, expected_graduation: gradISO }));
}, [college_enrollment_status,
enrollmentDate,
manualProgramLength,
autoProgramLength,
setData]);
// final handleSubmit => we store chosen tuition + program_length, then move on
const handleSubmit = () => {
const chosenTuition = manualTuition.trim() === ''
? autoTuition
: parseFloat(manualTuition);
const chosenProgramLength = manualProgramLength.trim() === ''
? autoProgramLength
: manualProgramLength;
setData(prev => ({
...prev,
tuition: chosenTuition,
program_length: chosenProgramLength
}));
nextStep();
};
// displayedTuition / displayedProgramLength
const displayedTuition = (manualTuition.trim() === '' ? autoTuition : manualTuition);
const displayedProgramLength = (manualProgramLength.trim() === '' ? autoProgramLength : manualProgramLength);
function pickStartDate() {
if (college_enrollment_status === 'prospective_student') {
return enrollmentDate; // may still be ''
}
if (college_enrollment_status === 'currently_enrolled') {
return firstOfNextMonth(new Date()); // today → 1st next month
}
return ''; // anybody else
}
function firstOfNextMonth(dateObj) {
return new Date(dateObj.getFullYear(), dateObj.getMonth() + 1, 1)
.toISOString()
.slice(0, 10); // yyyymmdd
}
const ready =
(!inSchool || expectedGraduation) && // grad date iff in school
selected_school && program_type;
return (
<div className="max-w-md mx-auto p-6 space-y-4">
<h2 className="text-2xl font-semibold">College Details</h2>
{(college_enrollment_status === 'currently_enrolled' ||
college_enrollment_status === 'prospective_student') ? (
<div className="space-y-4">
{/* In District, In State, Online, etc. */}
<div className="flex items-center space-x-2">
<input
type="checkbox"
name="is_in_district"
checked={is_in_district}
onChange={handleParentFieldChange}
className="h-4 w-4"
/>
<label className="font-medium">In District? {infoIcon("Used by Community Colleges usually - local discounts")}</label>
</div>
<div className="flex items-center space-x-2">
<input
type="checkbox"
name="is_in_state"
checked={is_in_state}
onChange={handleParentFieldChange}
className="h-4 w-4"
/>
<label className="font-medium">In State Tuition? {infoIcon("Students can qualify for discounted tuition if they are a resident of the same state as the college - private institutions rarely have this discounts")}</label>
</div>
<div className="flex items-center space-x-2">
<input
type="checkbox"
name="is_online"
checked={is_online}
onChange={handleParentFieldChange}
className="h-4 w-4"
/>
<label className="font-medium">Program is Fully Online {infoIcon("Tuition rates for fully online programs are usually different than traditional")}</label>
</div>
<div className="flex items-center space-x-2">
<input
type="checkbox"
name="loan_deferral_until_graduation"
checked={loan_deferral_until_graduation}
onChange={handleParentFieldChange}
className="h-4 w-4"
/>
<label className="font-medium">Defer Loan Payments until Graduation? {infoIcon("You can delay paying tuition loans while still in college, but they will still accrue interest during this time")}</label>
</div>
{/* School */}
<div className="space-y-1">
<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"
className={`w-full border rounded p-2 ${schoolValid ? '' : 'border-red-500'}`}
placeholder="Start typing and choose…"
/>
<datalist id="school-suggestions">
{schoolSuggestions.map((sch, idx) => (
<option
key={idx}
value={sch}
onClick={() => handleSchoolSelect(sch)}
/>
))}
</datalist>
</div>
<div className="space-y-1">
<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"
className={`w-full border rounded p-2 ${programValid ? '' : 'border-red-500'}`}
placeholder="Start typing and choose…"
/>
<datalist id="program-suggestions">
{programSuggestions.map((prog, idx) => (
<option
key={idx}
value={prog}
onClick={() => handleProgramSelect(prog)}
/>
))}
</datalist>
</div>
<div className="space-y-1">
<label className="block font-medium">Degree Type* {infoIcon("What level of degree are you/will you be persuing?")}</label>
<select
name="program_type"
value={program_type}
onChange={handleProgramTypeSelect}
className="w-full border rounded p-2"
>
<option value="">Select Program Type</option>
{availableProgramTypes.map((t, i) => (
<option key={i} value={t}>{t}</option>
))}
</select>
</div>
{/* Academic Calendar */}
<div className="space-y-1">
<label className="block font-medium">Academic Calendar {infoIcon("What annual calendar type does the college operate under - pick semester if you are unsure.")}</label>
<select
name="academic_calendar"
value={academic_calendar}
onChange={handleParentFieldChange}
className="w-full border rounded p-2"
>
<option value="semester">Semester</option>
<option value="quarter">Quarter</option>
<option value="trimester">Trimester</option>
<option value="other">Other</option>
</select>
</div>
{/* If Grad/Professional => credit_hours_required */}
{(program_type === 'Graduate/Professional Certificate' ||
program_type === 'First Professional 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 Certificate, Graduate, and Professional Programs differ on number of hours required.")}</label>
<input
type="number"
name="credit_hours_required"
value={credit_hours_required}
onChange={handleParentFieldChange}
placeholder="e.g. 120"
className="w-full border rounded p-2"
/>
</div>
)}
<div className="space-y-1">
<label className="block font-medium">Credit Hours Per Year {infoIcon("How many hours do you plan to take each year? 24 is usually considered full-time, but to finish a Bachelor's in 4 you need to take 30.")}</label>
<input
type="number"
name="credit_hours_per_year"
value={credit_hours_per_year}
onChange={handleParentFieldChange}
placeholder="e.g. 24"
className="w-full border rounded p-2"
/>
</div>
{/* Tuition (auto or override) */}
<div className="space-y-1">
<label className="block font-medium">Yearly Tuition</label>
<input
type="number"
value={displayedTuition}
onChange={handleManualTuitionChange}
placeholder="Leave blank to use auto-calculated, or type an override"
className="w-full border rounded p-2"
/>
</div>
{/* Annual Financial Aid */}
<div className="space-y-1">
<label className="block font-medium">(Estimated) Annual Financial Aid {infoIcon("You usually won't know this exact value until right before you start college. Use estimates in AptivaAI.")}</label>
<div className="flex space-x-2">
<input
type="number"
name="annual_financial_aid"
value={annual_financial_aid}
onChange={handleParentFieldChange}
placeholder="e.g. 2000"
className="w-full border rounded p-2"
/>
<button
type="button"
onClick={() => setShowAidWizard(true)}
className="bg-blue-600 text-center px-3 py-2 rounded text-white"
>
Need Help?
</button>
</div>
</div>
<div className="space-y-1">
<label className="block font-medium">Existing College Loan Debt {infoIcon("If you have existing student loans, enter the value here. Estimates are just fine here, but detailed forecasts require detailed inputs.")}</label>
<input
type="number"
name="existing_college_debt"
value={existing_college_debt}
onChange={handleParentFieldChange}
placeholder="e.g. 2000"
className="w-full border rounded p-2"
/>
</div>
{/* Show Program Length for both "currently_enrolled" & "prospective_student" */}
{(college_enrollment_status === 'currently_enrolled' ||
college_enrollment_status === 'prospective_student') && (
<div className="space-y-1">
<label className="block font-medium">Program Length {infoIcon("How many years it will take you to complete the degree/program given the number of hours you plan to take")}</label>
<input
type="number"
value={displayedProgramLength}
onChange={handleManualProgramLengthChange}
placeholder="Leave blank to use auto, or type an override"
className="w-full border rounded p-2"
/>
</div>
)}
{/* If currently_enrolled => hours_completed */}
{college_enrollment_status === 'currently_enrolled' && (
<div className="space-y-1">
<label className="block font-medium">
Completed Credit Hours (that count towards program completion) {infoIcon("If you have already completed some college credits that apply to the selected Program above, enter them here. Bachelor's = 120")}
</label>
<input
type="number"
name="hours_completed"
value={hours_completed}
onChange={handleParentFieldChange}
placeholder="Credit hours done"
className="w-full border rounded p-2"
/>
</div>
)}
{['currently_enrolled','prospective_student'].includes(college_enrollment_status) && (
<>
{/* A) Enrollment date prospective only */}
{college_enrollment_status === 'prospective_student' && (
<div className="space-y-2">
<label className="block font-medium">
Anticipated Enrollment Date <Req />
</label>
<input
type="date"
value={enrollmentDate}
onChange={e => {
setEnrollmentDate(e.target.value);
setData(p => ({ ...p, enrollment_date: e.target.value }));
}}
className="w-full border rounded p-2"
required
/>
</div>
)}
{/* B) Expected graduation always editable */}
<div className="space-y-2">
<label className="block font-medium">
Expected Graduation Date <Req />
{college_enrollment_status === 'prospective_student' &&
enrollmentDate && data.program_length && (
<span
className="ml-1 cursor-help text-blue-600"
title="Automatically estimated from your enrollment date and program length. Adjust if needed—actual calendars vary by institution."
>&#9432;</span>
)}
</label>
<input
type="date"
value={expectedGraduation}
onChange={e => {
setExpectedGraduation(e.target.value);
setData(p => ({ ...p, expected_graduation: e.target.value }));
}}
className="w-full border rounded p-2"
required
/>
</div>
</>
)}
<div className="space-y-1">
<label className="block font-medium">Loan Interest Rate (%) {infoIcon("These can vary, enter the best blended rate you can approximate if you have multiple.")}</label>
<input
type="number"
name="interest_rate"
value={interest_rate}
onChange={handleParentFieldChange}
placeholder="e.g. 5.5"
className="w-full border rounded p-2"
/>
</div>
<div className="space-y-1">
<label className="block font-medium">Loan Term (years) {infoIcon("Education loans typically have a 10-year payback period, but can vary.")}</label>
<input
type="number"
name="loan_term"
value={loan_term}
onChange={handleParentFieldChange}
placeholder="e.g. 10"
className="w-full border rounded p-2"
/>
</div>
<div className="space-y-1">
<label className="block font-medium">Extra Monthly Payment {infoIcon("Extra money you plan to pay towards the loans each month.")}</label>
<input
type="number"
name="extra_payment"
value={extra_payment}
onChange={handleParentFieldChange}
placeholder="Optional"
className="w-full border rounded p-2"
/>
</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. Can be found using Career Explorer if needed or input later.")}</label>
<input
type="number"
name="expected_salary"
value={expected_salary}
onChange={handleParentFieldChange}
placeholder="e.g. 65000"
className="w-full border rounded p-2"
/>
</div>
</div>
) : (
<p>Not currently enrolled or prospective student. Skipping college onboarding.</p>
)}
<div className="pt-4">
<button
onClick={prevStep}
style={{ marginRight: '1rem' }}
className="bg-gray-200 hover:bg-gray-300 text-gray-700 font-semibold py-2 px-4 rounded"
>
Previous
</button>
<button
onClick={handleSubmit}
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>
</div>
{showAidWizard && (
<Modal onClose={() => setShowAidWizard(false)}>
<FinancialAidWizard
onAidEstimated={(estimate) => {
setData(prev => ({
...prev,
annual_financial_aid: estimate
}));
}}
onClose={() => setShowAidWizard(false)}
/>
</Modal>
)}
</div>
);
}
export default CollegeOnboarding;