import React, { useState, useEffect } from 'react'; import Modal from '../../components/ui/modal.js'; import FinancialAidWizard from '../../components/FinancialAidWizard.js'; function CollegeOnboarding({ nextStep, prevStep, data, setData, careerProfileId }) { // CIP / iPEDS local states (purely for CIP data and suggestions) const [schoolData, setSchoolData] = useState([]); const [icTuitionData, setIcTuitionData] = useState([]); const [schoolSuggestions, setSchoolSuggestions] = useState([]); const [programSuggestions, setProgramSuggestions] = useState([]); const [availableProgramTypes, setAvailableProgramTypes] = useState([]); // Show/hide the financial aid wizard const [showAidWizard, setShowAidWizard] = useState(false); // Destructure parent data const { college_enrollment_status = '', selected_school = '', selected_program = '', program_type = '', academic_calendar = 'semester', // <-- ACADEMIC CALENDAR annual_financial_aid = '', is_online = false, existing_college_debt = '', 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.00'); // -- universal handleChange for all parent fields except tuition/program_length const handleParentFieldChange = (e) => { const { name, value, type, checked } = e.target; let val = value; if (type === 'checkbox') { val = checked; } if (['interest_rate','loan_term','extra_payment','expected_salary'].includes(name)) { val = parseFloat(val) || 0; } else if ( ['annual_financial_aid','existing_college_debt','credit_hours_per_year', 'hours_completed','credit_hours_required','tuition_paid'].includes(name) ) { val = val === '' ? '' : parseFloat(val); } setData(prev => ({ ...prev, [name]: val })); }; const handleManualTuitionChange = (e) => { setManualTuition(e.target.value); }; const handleManualProgramLengthChange = (e) => { setManualProgramLength(e.target.value); }; // Fetch CIP data (example) 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(); }, []); // Fetch iPEDS data (example) 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(); }, []); // Handle school name input const handleSchoolChange = (e) => { const value = e.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([]); }; 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) return; if (!hours_completed || !credit_hours_per_year) return; 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 = 60; break; case "Doctoral Degree": required = 120; break; case "First Professional Degree": required = 180; break; case "Graduate/Professional Certificate": required = parseInt(credit_hours_required, 10) || 0; break; default: required = parseInt(credit_hours_required, 10) || 0; break; } const remain = required - (parseInt(hours_completed, 10) || 0); const yrs = remain / (parseFloat(credit_hours_per_year) || 1); const calcLength = yrs.toFixed(2); setAutoProgramLength(calcLength); }, [program_type, hours_completed, credit_hours_per_year, credit_hours_required]); // final handleSubmit 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); return (

College Details

{(college_enrollment_status === 'currently_enrolled' || college_enrollment_status === 'prospective_student') ? (
{/* In District, In State, Online, etc. */}
{/* School / Program */}
{schoolSuggestions.map((sch, idx) => (
{programSuggestions.map((prog, idx) => (
{/* Academic Calendar (just re-added) */}
{/* If Grad/Professional or other that needs credit_hours_required */} {(program_type === 'Graduate/Professional Certificate' || program_type === 'First Professional Degree' || program_type === 'Doctoral Degree') && (
)}
{/* Tuition (auto or override) */}
{/* Annual Financial Aid with "Need Help?" Wizard button */}
{/* If "currently_enrolled" show Hours Completed + Program Length */} {college_enrollment_status === 'currently_enrolled' && ( <>
)}
) : (

Not currently enrolled or prospective student. Skipping college onboarding.

)}
{/* RENDER THE MODAL WITH FINANCIAL AID WIZARD IF showAidWizard === true */} {showAidWizard && ( setShowAidWizard(false)}> { // Update the annual_financial_aid with the wizard's result setData(prev => ({ ...prev, annual_financial_aid: estimate })); }} onClose={() => setShowAidWizard(false)} /> )}
); } export default CollegeOnboarding;