UI Update for Premium Onboarding
This commit is contained in:
parent
d207dce5d4
commit
e1f1782b01
@ -1,4 +1,4 @@
|
|||||||
// CareerOnboarding.js (inline implementation of career search)
|
// CareerOnboarding.js
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Input } from '../ui/input.js'; // Ensure path matches your structure
|
import { Input } from '../ui/input.js'; // Ensure path matches your structure
|
||||||
@ -25,24 +25,23 @@ const CareerOnboarding = ({ nextStep, prevStep, data, setData }) => {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Fetch careers exactly once on mount
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchCareerTitles = async () => {
|
const fetchCareerTitles = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/career_clusters.json');
|
const response = await fetch('/career_clusters.json');
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
const careerTitlesSet = new Set();
|
const careerTitlesSet = new Set();
|
||||||
|
|
||||||
const clusters = Object.keys(data);
|
const clusters = Object.keys(data);
|
||||||
for (let i = 0; i < clusters.length; i++) {
|
for (let i = 0; i < clusters.length; i++) {
|
||||||
const cluster = clusters[i];
|
const cluster = clusters[i];
|
||||||
const subdivisions = Object.keys(data[cluster]);
|
const subdivisions = Object.keys(data[cluster]);
|
||||||
|
|
||||||
for (let j = 0; j < subdivisions.length; j++) {
|
for (let j = 0; j < subdivisions.length; j++) {
|
||||||
const subdivision = subdivisions[j];
|
const subdivision = subdivisions[j];
|
||||||
const careersArray = data[cluster][subdivision];
|
const careersArray = data[cluster][subdivision];
|
||||||
|
|
||||||
for (let k = 0; k < careersArray.length; k++) {
|
for (let k = 0; k < careersArray.length; k++) {
|
||||||
const careerObj = careersArray[k];
|
const careerObj = careersArray[k];
|
||||||
if (careerObj.title) {
|
if (careerObj.title) {
|
||||||
@ -51,18 +50,17 @@ const CareerOnboarding = ({ nextStep, prevStep, data, setData }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setCareers([...careerTitlesSet]);
|
setCareers([...careerTitlesSet]);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching or processing career_clusters.json:", error);
|
console.error("Error fetching or processing career_clusters.json:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchCareerTitles();
|
fetchCareerTitles();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Update career selection automatically whenever the searchInput matches a valid career explicitly
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (careers.includes(searchInput)) {
|
if (careers.includes(searchInput)) {
|
||||||
setSelectedCareer(searchInput);
|
setSelectedCareer(searchInput);
|
||||||
@ -77,14 +75,13 @@ const CareerOnboarding = ({ nextStep, prevStep, data, setData }) => {
|
|||||||
const handleCareerInputChange = (e) => {
|
const handleCareerInputChange = (e) => {
|
||||||
const inputValue = e.target.value;
|
const inputValue = e.target.value;
|
||||||
setSearchInput(inputValue);
|
setSearchInput(inputValue);
|
||||||
|
|
||||||
// only set explicitly when an exact match occurs
|
|
||||||
if (careers.includes(inputValue)) {
|
if (careers.includes(inputValue)) {
|
||||||
setSelectedCareer(inputValue);
|
setSelectedCareer(inputValue);
|
||||||
setData(prev => ({ ...prev, career_name: inputValue }));
|
setData(prev => ({ ...prev, career_name: inputValue }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
if (!selectedCareer || !currentlyWorking || !collegeEnrollmentStatus) {
|
if (!selectedCareer || !currentlyWorking || !collegeEnrollmentStatus) {
|
||||||
alert("Please complete all required fields before continuing.");
|
alert("Please complete all required fields before continuing.");
|
||||||
@ -110,31 +107,33 @@ const CareerOnboarding = ({ nextStep, prevStep, data, setData }) => {
|
|||||||
nextStep();
|
nextStep();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="max-w-md mx-auto p-6 space-y-4">
|
||||||
<h2>Career Details</h2>
|
<h2 className="text-2xl font-semibold">Career Details</h2>
|
||||||
|
|
||||||
<label className="block font-medium">
|
<div className="space-y-2">
|
||||||
Are you currently working or earning any income (even part-time)?
|
<label className="block font-medium">
|
||||||
</label>
|
Are you currently working or earning any income (even part-time)?
|
||||||
<select
|
</label>
|
||||||
value={currentlyWorking}
|
<select
|
||||||
onChange={(e) => setCurrentlyWorking(e.target.value)}
|
value={currentlyWorking}
|
||||||
className="w-full border rounded p-2"
|
onChange={(e) => setCurrentlyWorking(e.target.value)}
|
||||||
>
|
className="w-full border rounded p-2"
|
||||||
<option value="">Select one</option>
|
>
|
||||||
<option value="yes">Yes</option>
|
<option value="">Select one</option>
|
||||||
<option value="no">No</option>
|
<option value="yes">Yes</option>
|
||||||
</select>
|
<option value="no">No</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div className="space-y-2">
|
||||||
<h3>Search for Career</h3>
|
<h3 className="font-medium">Search for Career</h3>
|
||||||
<input
|
<input
|
||||||
value={searchInput}
|
value={searchInput}
|
||||||
onChange={handleCareerInputChange}
|
onChange={handleCareerInputChange}
|
||||||
placeholder="Start typing a career..."
|
placeholder="Start typing a career..."
|
||||||
list="career-titles"
|
list="career-titles"
|
||||||
|
className="w-full border rounded p-2"
|
||||||
/>
|
/>
|
||||||
<datalist id="career-titles">
|
<datalist id="career-titles">
|
||||||
{careers.map((career, index) => (
|
{careers.map((career, index) => (
|
||||||
@ -143,38 +142,79 @@ const CareerOnboarding = ({ nextStep, prevStep, data, setData }) => {
|
|||||||
</datalist>
|
</datalist>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{selectedCareer && <p>Selected Career: <strong>{selectedCareer}</strong></p>}
|
{selectedCareer && (
|
||||||
|
<p className="text-gray-700">
|
||||||
|
Selected Career: <strong>{selectedCareer}</strong>
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
|
||||||
<label>Status:</label>
|
<div className="space-y-2">
|
||||||
<select name="status" onChange={handleChange} value={data.status || ''}>
|
<label className="block font-medium">Status:</label>
|
||||||
<option value="">Select Status</option>
|
<select
|
||||||
<option value="Planned">Planned</option>
|
name="status"
|
||||||
<option value="Current">Current</option>
|
onChange={handleChange}
|
||||||
<option value="Exploring">Exploring</option>
|
value={data.status || ''}
|
||||||
</select>
|
className="w-full border rounded p-2"
|
||||||
|
>
|
||||||
|
<option value="">Select Status</option>
|
||||||
|
<option value="Planned">Planned</option>
|
||||||
|
<option value="Current">Current</option>
|
||||||
|
<option value="Exploring">Exploring</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Career Start Date:</label>
|
<div className="space-y-2">
|
||||||
<input name="start_date" type="date" onChange={handleChange} value={data.start_date || ''} />
|
<label className="block font-medium">Career Start Date:</label>
|
||||||
|
<input
|
||||||
|
name="start_date"
|
||||||
|
type="date"
|
||||||
|
onChange={handleChange}
|
||||||
|
value={data.start_date || ''}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Projected End Date (optional):</label>
|
<div className="space-y-2">
|
||||||
<input name="projected_end_date" type="date" onChange={handleChange} value={data.projected_end_date || ''} />
|
<label className="block font-medium">Projected End Date (optional):</label>
|
||||||
|
<input
|
||||||
|
name="projected_end_date"
|
||||||
|
type="date"
|
||||||
|
onChange={handleChange}
|
||||||
|
value={data.projected_end_date || ''}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label className="block font-medium">
|
<div className="space-y-2">
|
||||||
Are you currently enrolled in college or planning to enroll?
|
<label className="block font-medium">
|
||||||
</label>
|
Are you currently enrolled in college or planning to enroll?
|
||||||
<select
|
</label>
|
||||||
value={collegeEnrollmentStatus}
|
<select
|
||||||
onChange={(e) => setCollegeEnrollmentStatus(e.target.value)}
|
value={collegeEnrollmentStatus}
|
||||||
className="w-full border rounded p-2"
|
onChange={(e) => setCollegeEnrollmentStatus(e.target.value)}
|
||||||
>
|
className="w-full border rounded p-2"
|
||||||
<option value="">Select one</option>
|
>
|
||||||
<option value="not_enrolled">Not Enrolled / Not Planning</option>
|
<option value="">Select one</option>
|
||||||
<option value="currently_enrolled">Currently Enrolled</option>
|
<option value="not_enrolled">Not Enrolled / Not Planning</option>
|
||||||
<option value="prospective_student">Planning to Enroll (Prospective Student)</option>
|
<option value="currently_enrolled">Currently Enrolled</option>
|
||||||
</select>
|
<option value="prospective_student">Planning to Enroll (Prospective Student)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button onClick={prevStep}>Back</button>
|
<div className="flex justify-between pt-4">
|
||||||
<button onClick={handleSubmit}>Financial →</button>
|
<button
|
||||||
|
onClick={prevStep}
|
||||||
|
className="bg-gray-200 hover:bg-gray-300 text-gray-700 font-semibold py-2 px-4 rounded"
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleSubmit}
|
||||||
|
className="bg-blue-500 hover:bg-blue-600 text-white font-semibold py-2 px-4 rounded"
|
||||||
|
>
|
||||||
|
Financial →
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
// CollegeOnboarding.js
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import authFetch from '../../utils/authFetch.js';
|
import authFetch from '../../utils/authFetch.js';
|
||||||
|
|
||||||
|
|
||||||
function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId }) {
|
function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId }) {
|
||||||
// CIP / iPEDS local states (purely for CIP data and suggestions)
|
// CIP / iPEDS local states (purely for CIP data and suggestions)
|
||||||
const [schoolData, setSchoolData] = useState([]);
|
const [schoolData, setSchoolData] = useState([]);
|
||||||
@ -11,8 +11,6 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
const [availableProgramTypes, setAvailableProgramTypes] = useState([]);
|
const [availableProgramTypes, setAvailableProgramTypes] = useState([]);
|
||||||
|
|
||||||
// ---- DESCTRUCTURE PARENT DATA FOR ALL FIELDS EXCEPT TUITION/PROGRAM_LENGTH ----
|
// ---- DESCTRUCTURE PARENT DATA FOR ALL FIELDS EXCEPT TUITION/PROGRAM_LENGTH ----
|
||||||
// We'll store user "typed" values for tuition/program_length in local states,
|
|
||||||
// but everything else comes directly from `data`.
|
|
||||||
const {
|
const {
|
||||||
college_enrollment_status = '',
|
college_enrollment_status = '',
|
||||||
selected_school = '',
|
selected_school = '',
|
||||||
@ -34,59 +32,42 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
hours_completed = '',
|
hours_completed = '',
|
||||||
credit_hours_required = '',
|
credit_hours_required = '',
|
||||||
tuition_paid = '',
|
tuition_paid = '',
|
||||||
// We do NOT consume data.tuition or data.program_length directly here
|
|
||||||
// because we store them in local states (manualTuition, manualProgramLength).
|
|
||||||
} = data;
|
} = data;
|
||||||
|
|
||||||
// ---- 1. LOCAL STATES for auto/manual logic on TWO fields ----
|
// ---- 1. LOCAL STATES for auto/manual logic on TWO fields ----
|
||||||
// manualTuition: user typed override
|
const [manualTuition, setManualTuition] = useState('');
|
||||||
// autoTuition: iPEDS calculation
|
|
||||||
const [manualTuition, setManualTuition] = useState(''); // '' means no manual override
|
|
||||||
const [autoTuition, setAutoTuition] = useState(0);
|
const [autoTuition, setAutoTuition] = useState(0);
|
||||||
|
|
||||||
// same approach for program_length
|
|
||||||
const [manualProgramLength, setManualProgramLength] = useState('');
|
const [manualProgramLength, setManualProgramLength] = useState('');
|
||||||
const [autoProgramLength, setAutoProgramLength] = useState('0.00');
|
const [autoProgramLength, setAutoProgramLength] = useState('0.00');
|
||||||
|
|
||||||
// ------------------------------------------
|
// -- universal handleChange for all parent fields except tuition/program_length
|
||||||
// Universal handleChange for all parent fields
|
|
||||||
// ------------------------------------------
|
|
||||||
const handleParentFieldChange = (e) => {
|
const handleParentFieldChange = (e) => {
|
||||||
const { name, value, type, checked } = e.target;
|
const { name, value, type, checked } = e.target;
|
||||||
let val = value;
|
let val = value;
|
||||||
if (type === 'checkbox') {
|
if (type === 'checkbox') {
|
||||||
val = checked;
|
val = checked;
|
||||||
}
|
}
|
||||||
// parse numeric fields that are NOT tuition or program_length
|
|
||||||
if (['interest_rate','loan_term','extra_payment','expected_salary'].includes(name)) {
|
if (['interest_rate','loan_term','extra_payment','expected_salary'].includes(name)) {
|
||||||
val = parseFloat(val) || 0;
|
val = parseFloat(val) || 0;
|
||||||
} else if (
|
} else if (
|
||||||
['annual_financial_aid','existing_college_debt','credit_hours_per_year',
|
['annual_financial_aid','existing_college_debt','credit_hours_per_year',
|
||||||
'hours_completed','credit_hours_required','tuition_paid']
|
'hours_completed','credit_hours_required','tuition_paid'].includes(name)
|
||||||
.includes(name)
|
|
||||||
) {
|
) {
|
||||||
val = val === '' ? '' : parseFloat(val);
|
val = val === '' ? '' : parseFloat(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
setData(prev => ({ ...prev, [name]: val }));
|
setData(prev => ({ ...prev, [name]: val }));
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------
|
|
||||||
// handleManualTuition, handleManualProgramLength
|
|
||||||
// for local fields
|
|
||||||
// ------------------------------------------
|
|
||||||
const handleManualTuitionChange = (e) => {
|
const handleManualTuitionChange = (e) => {
|
||||||
// user typed something => override
|
setManualTuition(e.target.value);
|
||||||
setManualTuition(e.target.value); // store as string for partial typing
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleManualProgramLengthChange = (e) => {
|
const handleManualProgramLengthChange = (e) => {
|
||||||
setManualProgramLength(e.target.value);
|
setManualProgramLength(e.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------
|
// CIP fetch
|
||||||
// CIP Data fetch once
|
|
||||||
// ------------------------------------------
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchCipData() {
|
async function fetchCipData() {
|
||||||
try {
|
try {
|
||||||
@ -104,9 +85,7 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
fetchCipData();
|
fetchCipData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// ------------------------------------------
|
// iPEDS fetch
|
||||||
// iPEDS Data fetch once
|
|
||||||
// ------------------------------------------
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchIpedsData() {
|
async function fetchIpedsData() {
|
||||||
try {
|
try {
|
||||||
@ -125,9 +104,7 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
fetchIpedsData();
|
fetchIpedsData();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// ------------------------------------------
|
// handleSchoolChange
|
||||||
// handleSchoolChange, handleProgramChange, etc. => update parent fields
|
|
||||||
// ------------------------------------------
|
|
||||||
const handleSchoolChange = (e) => {
|
const handleSchoolChange = (e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setData(prev => ({
|
setData(prev => ({
|
||||||
@ -137,7 +114,6 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
program_type: '',
|
program_type: '',
|
||||||
credit_hours_required: '',
|
credit_hours_required: '',
|
||||||
}));
|
}));
|
||||||
// CIP suggestions
|
|
||||||
const filtered = schoolData.filter(s =>
|
const filtered = schoolData.filter(s =>
|
||||||
s.INSTNM.toLowerCase().includes(value.toLowerCase())
|
s.INSTNM.toLowerCase().includes(value.toLowerCase())
|
||||||
);
|
);
|
||||||
@ -163,7 +139,6 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
const handleProgramChange = (e) => {
|
const handleProgramChange = (e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setData(prev => ({ ...prev, selected_program: value }));
|
setData(prev => ({ ...prev, selected_program: value }));
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
setProgramSuggestions([]);
|
setProgramSuggestions([]);
|
||||||
return;
|
return;
|
||||||
@ -188,11 +163,11 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
program_type: val,
|
program_type: val,
|
||||||
credit_hours_required: '',
|
credit_hours_required: '',
|
||||||
}));
|
}));
|
||||||
setManualProgramLength(''); // reset manual override
|
setManualProgramLength('');
|
||||||
setAutoProgramLength('0.00');
|
setAutoProgramLength('0.00');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Once we have school+program, load possible program types
|
// once we have school+program, load possible program types
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selected_program || !selected_school || !schoolData.length) return;
|
if (!selected_program || !selected_school || !schoolData.length) return;
|
||||||
const possibleTypes = schoolData
|
const possibleTypes = schoolData
|
||||||
@ -204,15 +179,11 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
setAvailableProgramTypes([...new Set(possibleTypes)]);
|
setAvailableProgramTypes([...new Set(possibleTypes)]);
|
||||||
}, [selected_program, selected_school, schoolData]);
|
}, [selected_program, selected_school, schoolData]);
|
||||||
|
|
||||||
// ------------------------------------------
|
// auto-calc tuition
|
||||||
// Auto-calc Tuition => store in local autoTuition
|
|
||||||
// ------------------------------------------
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// do we have enough to calc?
|
|
||||||
if (!icTuitionData.length) return;
|
if (!icTuitionData.length) return;
|
||||||
if (!selected_school || !program_type || !credit_hours_per_year) return;
|
if (!selected_school || !program_type || !credit_hours_per_year) return;
|
||||||
|
|
||||||
// find row
|
|
||||||
const found = schoolData.find(s => s.INSTNM.toLowerCase() === selected_school.toLowerCase());
|
const found = schoolData.find(s => s.INSTNM.toLowerCase() === selected_school.toLowerCase());
|
||||||
if (!found) return;
|
if (!found) return;
|
||||||
const unitId = found.UNITID;
|
const unitId = found.UNITID;
|
||||||
@ -221,7 +192,6 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
const match = icTuitionData.find(row => row.UNITID === unitId);
|
const match = icTuitionData.find(row => row.UNITID === unitId);
|
||||||
if (!match) return;
|
if (!match) return;
|
||||||
|
|
||||||
// grad or undergrad
|
|
||||||
const isGradOrProf = [
|
const isGradOrProf = [
|
||||||
"Master's Degree",
|
"Master's Degree",
|
||||||
"Doctoral Degree",
|
"Doctoral Degree",
|
||||||
@ -258,7 +228,6 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
|
|
||||||
const chpy = parseFloat(credit_hours_per_year) || 0;
|
const chpy = parseFloat(credit_hours_per_year) || 0;
|
||||||
let estimate = 0;
|
let estimate = 0;
|
||||||
// threshold
|
|
||||||
if (chpy < 24 && partTimeRate) {
|
if (chpy < 24 && partTimeRate) {
|
||||||
estimate = partTimeRate * chpy;
|
estimate = partTimeRate * chpy;
|
||||||
} else {
|
} else {
|
||||||
@ -266,15 +235,12 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
}
|
}
|
||||||
|
|
||||||
setAutoTuition(Math.round(estimate));
|
setAutoTuition(Math.round(estimate));
|
||||||
|
|
||||||
}, [
|
}, [
|
||||||
icTuitionData, selected_school, program_type,
|
icTuitionData, selected_school, program_type,
|
||||||
credit_hours_per_year, is_in_state, is_in_district, schoolData
|
credit_hours_per_year, is_in_state, is_in_district, schoolData
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// ------------------------------------------
|
// auto-calc program length
|
||||||
// Auto-calc Program Length => store in local autoProgramLength
|
|
||||||
// ------------------------------------------
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!program_type) return;
|
if (!program_type) return;
|
||||||
if (!hours_completed || !credit_hours_per_year) return;
|
if (!hours_completed || !credit_hours_per_year) return;
|
||||||
@ -299,264 +265,315 @@ function CollegeOnboarding({ nextStep, prevStep, data, setData, careerPathId })
|
|||||||
setAutoProgramLength(calcLength);
|
setAutoProgramLength(calcLength);
|
||||||
}, [program_type, hours_completed, credit_hours_per_year, credit_hours_required]);
|
}, [program_type, hours_completed, credit_hours_per_year, credit_hours_required]);
|
||||||
|
|
||||||
// ------------------------------------------
|
// final handleSubmit
|
||||||
// handleSubmit => merges final chosen values
|
|
||||||
// ------------------------------------------
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
const chosenTuition = manualTuition.trim() === ''
|
const chosenTuition = manualTuition.trim() === ''
|
||||||
? autoTuition
|
? autoTuition
|
||||||
: parseFloat(manualTuition);
|
: parseFloat(manualTuition);
|
||||||
const chosenProgramLength = manualProgramLength.trim() === ''
|
const chosenProgramLength = manualProgramLength.trim() === ''
|
||||||
? autoProgramLength
|
? autoProgramLength
|
||||||
: manualProgramLength;
|
: manualProgramLength;
|
||||||
|
|
||||||
// Update parent’s data (collegeData)
|
|
||||||
setData(prev => ({
|
setData(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
tuition: chosenTuition, // match name used by parent or server
|
tuition: chosenTuition,
|
||||||
program_length: chosenProgramLength // match name used by parent
|
program_length: chosenProgramLength
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Then go to the next step in the parent’s wizard
|
|
||||||
nextStep();
|
nextStep();
|
||||||
};
|
};
|
||||||
|
|
||||||
// The displayed tuition => (manualTuition !== '' ? manualTuition : autoTuition)
|
|
||||||
const displayedTuition = (manualTuition.trim() === '' ? autoTuition : manualTuition);
|
const displayedTuition = (manualTuition.trim() === '' ? autoTuition : manualTuition);
|
||||||
|
|
||||||
// The displayed program length => (manualProgramLength !== '' ? manualProgramLength : autoProgramLength)
|
|
||||||
const displayedProgramLength = (manualProgramLength.trim() === '' ? autoProgramLength : manualProgramLength);
|
const displayedProgramLength = (manualProgramLength.trim() === '' ? autoProgramLength : manualProgramLength);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="max-w-md mx-auto p-6 space-y-4">
|
||||||
<h2>College Details</h2>
|
<h2 className="text-2xl font-semibold">College Details</h2>
|
||||||
|
|
||||||
{(college_enrollment_status === 'currently_enrolled' ||
|
{(college_enrollment_status === 'currently_enrolled' ||
|
||||||
college_enrollment_status === 'prospective_student') ? (
|
college_enrollment_status === 'prospective_student') ? (
|
||||||
<>
|
<div className="space-y-4">
|
||||||
<label>
|
<div className="flex items-center space-x-2">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name="is_in_district"
|
name="is_in_district"
|
||||||
checked={is_in_district}
|
checked={is_in_district}
|
||||||
onChange={handleParentFieldChange}
|
onChange={handleParentFieldChange}
|
||||||
|
className="h-4 w-4"
|
||||||
/>
|
/>
|
||||||
In District?
|
<label className="font-medium">In District?</label>
|
||||||
</label>
|
</div>
|
||||||
|
|
||||||
<label>
|
<div className="flex items-center space-x-2">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name="is_in_state"
|
name="is_in_state"
|
||||||
checked={is_in_state}
|
checked={is_in_state}
|
||||||
onChange={handleParentFieldChange}
|
onChange={handleParentFieldChange}
|
||||||
|
className="h-4 w-4"
|
||||||
/>
|
/>
|
||||||
In State Tuition?
|
<label className="font-medium">In State Tuition?</label>
|
||||||
</label>
|
</div>
|
||||||
|
|
||||||
<label>
|
<div className="flex items-center space-x-2">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name="is_online"
|
name="is_online"
|
||||||
checked={is_online}
|
checked={is_online}
|
||||||
onChange={handleParentFieldChange}
|
onChange={handleParentFieldChange}
|
||||||
|
className="h-4 w-4"
|
||||||
/>
|
/>
|
||||||
Program is Fully Online
|
<label className="font-medium">Program is Fully Online</label>
|
||||||
</label>
|
</div>
|
||||||
|
|
||||||
<label>
|
<div className="flex items-center space-x-2">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name="loan_deferral_until_graduation"
|
name="loan_deferral_until_graduation"
|
||||||
checked={loan_deferral_until_graduation}
|
checked={loan_deferral_until_graduation}
|
||||||
onChange={handleParentFieldChange}
|
onChange={handleParentFieldChange}
|
||||||
|
className="h-4 w-4"
|
||||||
/>
|
/>
|
||||||
Defer Loan Payments until Graduation?
|
<label className="font-medium">Defer Loan Payments until Graduation?</label>
|
||||||
</label>
|
</div>
|
||||||
|
|
||||||
<label>School Name*</label>
|
|
||||||
<input
|
|
||||||
name="selected_school"
|
|
||||||
value={selected_school}
|
|
||||||
onChange={handleSchoolChange}
|
|
||||||
list="school-suggestions"
|
|
||||||
placeholder="Enter school name..."
|
|
||||||
/>
|
|
||||||
<datalist id="school-suggestions">
|
|
||||||
{schoolSuggestions.map((sch, idx) => (
|
|
||||||
<option
|
|
||||||
key={idx}
|
|
||||||
value={sch}
|
|
||||||
onClick={() => handleSchoolSelect(sch)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</datalist>
|
|
||||||
|
|
||||||
<label>Program Name*</label>
|
<div className="space-y-1">
|
||||||
<input
|
<label className="block font-medium">School Name*</label>
|
||||||
name="selected_program"
|
<input
|
||||||
value={selected_program}
|
name="selected_school"
|
||||||
onChange={handleProgramChange}
|
value={selected_school}
|
||||||
list="program-suggestions"
|
onChange={handleSchoolChange}
|
||||||
placeholder="Enter program name..."
|
list="school-suggestions"
|
||||||
/>
|
placeholder="Enter school name..."
|
||||||
<datalist id="program-suggestions">
|
className="w-full border rounded p-2"
|
||||||
{programSuggestions.map((prog, idx) => (
|
/>
|
||||||
<option
|
<datalist id="school-suggestions">
|
||||||
key={idx}
|
{schoolSuggestions.map((sch, idx) => (
|
||||||
value={prog}
|
<option
|
||||||
onClick={() => handleProgramSelect(prog)}
|
key={idx}
|
||||||
/>
|
value={sch}
|
||||||
))}
|
onClick={() => handleSchoolSelect(sch)}
|
||||||
</datalist>
|
/>
|
||||||
|
))}
|
||||||
|
</datalist>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Program Type*</label>
|
<div className="space-y-1">
|
||||||
<select
|
<label className="block font-medium">Program Name*</label>
|
||||||
name="program_type"
|
<input
|
||||||
value={program_type}
|
name="selected_program"
|
||||||
onChange={handleProgramTypeSelect}
|
value={selected_program}
|
||||||
>
|
onChange={handleProgramChange}
|
||||||
<option value="">Select Program Type</option>
|
list="program-suggestions"
|
||||||
{availableProgramTypes.map((t, i) => (
|
placeholder="Enter program name..."
|
||||||
<option key={i} value={t}>{t}</option>
|
className="w-full border rounded p-2"
|
||||||
))}
|
/>
|
||||||
</select>
|
<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">Program Type*</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>
|
||||||
|
|
||||||
{(program_type === 'Graduate/Professional Certificate' ||
|
{(program_type === 'Graduate/Professional Certificate' ||
|
||||||
program_type === 'First Professional Degree' ||
|
program_type === 'First Professional Degree' ||
|
||||||
program_type === 'Doctoral Degree') && (
|
program_type === 'Doctoral Degree') && (
|
||||||
<>
|
<div className="space-y-1">
|
||||||
<label>Credit Hours Required</label>
|
<label className="block font-medium">Credit Hours Required</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
name="credit_hours_required"
|
name="credit_hours_required"
|
||||||
value={credit_hours_required}
|
value={credit_hours_required}
|
||||||
onChange={handleParentFieldChange}
|
onChange={handleParentFieldChange}
|
||||||
placeholder="e.g. 30"
|
placeholder="e.g. 30"
|
||||||
|
className="w-full border rounded p-2"
|
||||||
/>
|
/>
|
||||||
</>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<label>Credit Hours Per Year</label>
|
<div className="space-y-1">
|
||||||
<input
|
<label className="block font-medium">Credit Hours Per Year</label>
|
||||||
type="number"
|
<input
|
||||||
name="credit_hours_per_year"
|
type="number"
|
||||||
value={credit_hours_per_year}
|
name="credit_hours_per_year"
|
||||||
onChange={handleParentFieldChange}
|
value={credit_hours_per_year}
|
||||||
placeholder="e.g. 24"
|
onChange={handleParentFieldChange}
|
||||||
/>
|
placeholder="e.g. 24"
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Yearly Tuition</label>
|
<div className="space-y-1">
|
||||||
{/* If user typed a custom value => manualTuition, else autoTuition */}
|
<label className="block font-medium">Yearly Tuition</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={displayedTuition}
|
value={displayedTuition}
|
||||||
onChange={handleManualTuitionChange}
|
onChange={handleManualTuitionChange}
|
||||||
placeholder="Leave blank to use auto, or type an override"
|
placeholder="Leave blank to use auto, or type an override"
|
||||||
/>
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Annual Financial Aid</label>
|
<div className="space-y-1">
|
||||||
<input
|
<label className="block font-medium">Annual Financial Aid</label>
|
||||||
type="number"
|
<input
|
||||||
name="annual_financial_aid"
|
type="number"
|
||||||
value={annual_financial_aid}
|
name="annual_financial_aid"
|
||||||
onChange={handleParentFieldChange}
|
value={annual_financial_aid}
|
||||||
placeholder="e.g. 2000"
|
onChange={handleParentFieldChange}
|
||||||
/>
|
placeholder="e.g. 2000"
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Existing College Loan Debt</label>
|
<div className="space-y-1">
|
||||||
<input
|
<label className="block font-medium">Existing College Loan Debt</label>
|
||||||
type="number"
|
<input
|
||||||
name="existing_college_debt"
|
type="number"
|
||||||
value={existing_college_debt}
|
name="existing_college_debt"
|
||||||
onChange={handleParentFieldChange}
|
value={existing_college_debt}
|
||||||
placeholder="e.g. 2000"
|
onChange={handleParentFieldChange}
|
||||||
/>
|
placeholder="e.g. 2000"
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{college_enrollment_status === 'currently_enrolled' && (
|
{college_enrollment_status === 'currently_enrolled' && (
|
||||||
<>
|
<>
|
||||||
<label>Tuition Paid</label>
|
<div className="space-y-1">
|
||||||
<input
|
<label className="block font-medium">Tuition Paid</label>
|
||||||
type="number"
|
<input
|
||||||
name="tuition_paid"
|
type="number"
|
||||||
value={tuition_paid}
|
name="tuition_paid"
|
||||||
onChange={handleParentFieldChange}
|
value={tuition_paid}
|
||||||
placeholder="Already paid"
|
onChange={handleParentFieldChange}
|
||||||
/>
|
placeholder="Already paid"
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Hours Completed</label>
|
<div className="space-y-1">
|
||||||
<input
|
<label className="block font-medium">Hours Completed</label>
|
||||||
type="number"
|
<input
|
||||||
name="hours_completed"
|
type="number"
|
||||||
value={hours_completed}
|
name="hours_completed"
|
||||||
onChange={handleParentFieldChange}
|
value={hours_completed}
|
||||||
placeholder="Credit hours done"
|
onChange={handleParentFieldChange}
|
||||||
/>
|
placeholder="Credit hours done"
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Program Length</label>
|
<div className="space-y-1">
|
||||||
{/* If user typed a custom => manualProgramLength, else autoProgramLength */}
|
<label className="block font-medium">Program Length</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
value={displayedProgramLength}
|
value={displayedProgramLength}
|
||||||
onChange={handleManualProgramLengthChange}
|
onChange={handleManualProgramLengthChange}
|
||||||
placeholder="Leave blank to use auto, or type an override"
|
placeholder="Leave blank to use auto, or type an override"
|
||||||
/>
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<label>Expected Graduation</label>
|
<div className="space-y-1">
|
||||||
<input
|
<label className="block font-medium">Expected Graduation</label>
|
||||||
type="date"
|
<input
|
||||||
name="expected_graduation"
|
type="date"
|
||||||
value={expected_graduation}
|
name="expected_graduation"
|
||||||
onChange={handleParentFieldChange}
|
value={expected_graduation}
|
||||||
/>
|
onChange={handleParentFieldChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Loan Interest Rate (%)</label>
|
<div className="space-y-1">
|
||||||
<input
|
<label className="block font-medium">Loan Interest Rate (%)</label>
|
||||||
type="number"
|
<input
|
||||||
name="interest_rate"
|
type="number"
|
||||||
value={interest_rate}
|
name="interest_rate"
|
||||||
onChange={handleParentFieldChange}
|
value={interest_rate}
|
||||||
placeholder="e.g. 5.5"
|
onChange={handleParentFieldChange}
|
||||||
/>
|
placeholder="e.g. 5.5"
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Loan Term (years)</label>
|
<div className="space-y-1">
|
||||||
<input
|
<label className="block font-medium">Loan Term (years)</label>
|
||||||
type="number"
|
<input
|
||||||
name="loan_term"
|
type="number"
|
||||||
value={loan_term}
|
name="loan_term"
|
||||||
onChange={handleParentFieldChange}
|
value={loan_term}
|
||||||
placeholder="e.g. 10"
|
onChange={handleParentFieldChange}
|
||||||
/>
|
placeholder="e.g. 10"
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Extra Monthly Payment</label>
|
<div className="space-y-1">
|
||||||
<input
|
<label className="block font-medium">Extra Monthly Payment</label>
|
||||||
type="number"
|
<input
|
||||||
name="extra_payment"
|
type="number"
|
||||||
value={extra_payment}
|
name="extra_payment"
|
||||||
onChange={handleParentFieldChange}
|
value={extra_payment}
|
||||||
placeholder="Optional"
|
onChange={handleParentFieldChange}
|
||||||
/>
|
placeholder="Optional"
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Expected Salary After Graduation</label>
|
<div className="space-y-1">
|
||||||
<input
|
<label className="block font-medium">Expected Salary After Graduation</label>
|
||||||
type="number"
|
<input
|
||||||
name="expected_salary"
|
type="number"
|
||||||
value={expected_salary}
|
name="expected_salary"
|
||||||
onChange={handleParentFieldChange}
|
value={expected_salary}
|
||||||
placeholder="e.g. 65000"
|
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>
|
<p>Not currently enrolled or prospective student. Skipping college onboarding.</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<button onClick={prevStep} style={{ marginRight: '1rem' }}>← Previous</button>
|
<div className="pt-4">
|
||||||
<button onClick={handleSubmit}>Finish Onboarding</button>
|
<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}
|
||||||
|
className="bg-blue-500 hover:bg-blue-600 text-white font-semibold py-2 px-4 rounded"
|
||||||
|
>
|
||||||
|
Finish Onboarding
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// FinancialOnboarding.js
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const FinancialOnboarding = ({ nextStep, prevStep, data, setData, isEditMode = false }) => {
|
const FinancialOnboarding = ({ nextStep, prevStep, data, setData, isEditMode = false }) => {
|
||||||
@ -13,7 +14,6 @@ const FinancialOnboarding = ({ nextStep, prevStep, data, setData, isEditMode = f
|
|||||||
emergency_contribution = 0,
|
emergency_contribution = 0,
|
||||||
extra_cash_emergency_pct = "",
|
extra_cash_emergency_pct = "",
|
||||||
extra_cash_retirement_pct = "",
|
extra_cash_retirement_pct = "",
|
||||||
|
|
||||||
planned_monthly_expenses = '',
|
planned_monthly_expenses = '',
|
||||||
planned_monthly_debt_payments = '',
|
planned_monthly_debt_payments = '',
|
||||||
planned_monthly_retirement_contribution = '',
|
planned_monthly_retirement_contribution = '',
|
||||||
@ -22,7 +22,7 @@ const FinancialOnboarding = ({ nextStep, prevStep, data, setData, isEditMode = f
|
|||||||
planned_surplus_retirement_pct = '',
|
planned_surplus_retirement_pct = '',
|
||||||
planned_additional_income = ''
|
planned_additional_income = ''
|
||||||
} = data;
|
} = data;
|
||||||
|
|
||||||
const handleChange = (e) => {
|
const handleChange = (e) => {
|
||||||
const { name, value } = e.target;
|
const { name, value } = e.target;
|
||||||
let val = parseFloat(value) || 0;
|
let val = parseFloat(value) || 0;
|
||||||
@ -42,172 +42,250 @@ const FinancialOnboarding = ({ nextStep, prevStep, data, setData, isEditMode = f
|
|||||||
extra_cash_emergency_pct: 100 - val
|
extra_cash_emergency_pct: 100 - val
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
setData(prevData => ({
|
setData(prevData => ({ ...prevData, [name]: val }));
|
||||||
...prevData,
|
|
||||||
[name]: val
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="max-w-md mx-auto p-6 space-y-6">
|
||||||
<h2>Financial Details</h2>
|
<h2 className="text-2xl font-semibold">Financial Details</h2>
|
||||||
|
|
||||||
{currently_working === 'yes' && (
|
{currently_working === 'yes' && (
|
||||||
<>
|
<div className="space-y-4">
|
||||||
<input
|
<div>
|
||||||
name="current_salary"
|
<label className="block font-medium">Current Annual Salary</label>
|
||||||
type="number"
|
<input
|
||||||
placeholder="Current Annual Salary"
|
name="current_salary"
|
||||||
value={current_salary || ''} // controlled
|
type="number"
|
||||||
onChange={handleChange}
|
placeholder="Current Annual Salary"
|
||||||
/>
|
value={current_salary || ''}
|
||||||
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<input
|
<div>
|
||||||
name="additional_income"
|
<label className="block font-medium">Additional Annual Income</label>
|
||||||
type="number"
|
<input
|
||||||
placeholder="Additional Annual Income (Investments, annuitites, additional jobs, etc. - optional)"
|
name="additional_income"
|
||||||
value={additional_income || ''}
|
type="number"
|
||||||
onChange={handleChange}
|
placeholder="Investments, side jobs, etc. (optional)"
|
||||||
/>
|
value={additional_income || ''}
|
||||||
</>
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<input
|
<div className="space-y-4">
|
||||||
name="monthly_expenses"
|
<div>
|
||||||
type="number"
|
<label className="block font-medium">Monthly Expenses</label>
|
||||||
placeholder="Monthly Expenses"
|
|
||||||
value={monthly_expenses || ''}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
name="monthly_debt_payments"
|
|
||||||
type="number"
|
|
||||||
placeholder="Monthly Debt Payments (optional)"
|
|
||||||
value={monthly_debt_payments || ''}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
name="retirement_savings"
|
|
||||||
type="number"
|
|
||||||
placeholder="Retirement Savings"
|
|
||||||
value={retirement_savings || ''}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
name="retirement_contribution"
|
|
||||||
type="number"
|
|
||||||
placeholder="Monthly Retirement Contribution"
|
|
||||||
value={retirement_contribution || ''}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
name="emergency_fund"
|
|
||||||
type="number"
|
|
||||||
placeholder="Emergency Fund Savings"
|
|
||||||
value={emergency_fund || ''}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
name="emergency_contribution"
|
|
||||||
type="number"
|
|
||||||
placeholder="Monthly Emergency Fund Contribution (optional)"
|
|
||||||
value={emergency_contribution || ''}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<h3>Extra Monthly Cash Allocation</h3>
|
|
||||||
<p>If you have extra money left each month after expenses, how would you like to allocate it? (Must add to 100%)</p>
|
|
||||||
|
|
||||||
<label>Extra Monthly Cash to Emergency Fund (%)</label>
|
|
||||||
<input
|
|
||||||
name="extra_cash_emergency_pct"
|
|
||||||
type="number"
|
|
||||||
placeholder="% to Emergency Savings (e.g., 30)"
|
|
||||||
value={extra_cash_emergency_pct}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<label>Extra Monthly Cash to Retirement Fund (%)</label>
|
|
||||||
<input
|
|
||||||
name="extra_cash_retirement_pct"
|
|
||||||
type="number"
|
|
||||||
placeholder="% to Retirement Savings (e.g., 70)"
|
|
||||||
value={extra_cash_retirement_pct}
|
|
||||||
onChange={handleChange}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Only show the planned overrides if isEditMode is true */}
|
|
||||||
{isEditMode && (
|
|
||||||
<>
|
|
||||||
<hr />
|
|
||||||
<h2>Planned Scenario Overrides</h2>
|
|
||||||
<p>These fields let you override your real finances for this scenario.</p>
|
|
||||||
|
|
||||||
<label>Planned Monthly Expenses</label>
|
|
||||||
<input
|
<input
|
||||||
|
name="monthly_expenses"
|
||||||
type="number"
|
type="number"
|
||||||
name="planned_monthly_expenses"
|
placeholder="Monthly Expenses"
|
||||||
value={planned_monthly_expenses}
|
value={monthly_expenses || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Planned Monthly Debt Payments</label>
|
<div>
|
||||||
|
<label className="block font-medium">Monthly Debt Payments (optional)</label>
|
||||||
<input
|
<input
|
||||||
|
name="monthly_debt_payments"
|
||||||
type="number"
|
type="number"
|
||||||
name="planned_monthly_debt_payments"
|
placeholder="Monthly Debt Payments"
|
||||||
value={planned_monthly_debt_payments}
|
value={monthly_debt_payments || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Planned Monthly Retirement Contribution</label>
|
<div>
|
||||||
|
<label className="block font-medium">Retirement Savings</label>
|
||||||
<input
|
<input
|
||||||
|
name="retirement_savings"
|
||||||
type="number"
|
type="number"
|
||||||
name="planned_monthly_retirement_contribution"
|
placeholder="Retirement Savings"
|
||||||
value={planned_monthly_retirement_contribution}
|
value={retirement_savings || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Planned Monthly Emergency Contribution</label>
|
<div>
|
||||||
|
<label className="block font-medium">Monthly Retirement Contribution</label>
|
||||||
<input
|
<input
|
||||||
|
name="retirement_contribution"
|
||||||
type="number"
|
type="number"
|
||||||
name="planned_monthly_emergency_contribution"
|
placeholder="Monthly Retirement Contribution"
|
||||||
value={planned_monthly_emergency_contribution}
|
value={retirement_contribution || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Planned Surplus % to Emergency</label>
|
<div>
|
||||||
|
<label className="block font-medium">Emergency Fund Savings</label>
|
||||||
<input
|
<input
|
||||||
|
name="emergency_fund"
|
||||||
type="number"
|
type="number"
|
||||||
name="planned_surplus_emergency_pct"
|
placeholder="Emergency Fund Savings"
|
||||||
value={planned_surplus_emergency_pct}
|
value={emergency_fund || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Planned Surplus % to Retirement</label>
|
<div>
|
||||||
|
<label className="block font-medium">Monthly Emergency Fund Contribution</label>
|
||||||
<input
|
<input
|
||||||
|
name="emergency_contribution"
|
||||||
type="number"
|
type="number"
|
||||||
name="planned_surplus_retirement_pct"
|
placeholder="Monthly Emergency Fund Contribution (optional)"
|
||||||
value={planned_surplus_retirement_pct}
|
value={emergency_contribution || ''}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label>Planned Additional Annual Income</label>
|
<div className="space-y-2">
|
||||||
|
<h3 className="text-lg font-medium">Extra Monthly Cash Allocation</h3>
|
||||||
|
<p className="text-gray-600">
|
||||||
|
If you have extra money left each month after expenses, how would you like to allocate it?
|
||||||
|
(Must add to 100%)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block font-medium">Extra Monthly Cash to Emergency Fund (%)</label>
|
||||||
<input
|
<input
|
||||||
|
name="extra_cash_emergency_pct"
|
||||||
type="number"
|
type="number"
|
||||||
name="planned_additional_income"
|
placeholder="% to Emergency Savings (e.g., 30)"
|
||||||
value={planned_additional_income}
|
value={extra_cash_emergency_pct}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
/>
|
/>
|
||||||
</>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block font-medium">Extra Monthly Cash to Retirement Fund (%)</label>
|
||||||
|
<input
|
||||||
|
name="extra_cash_retirement_pct"
|
||||||
|
type="number"
|
||||||
|
placeholder="% to Retirement Savings (e.g., 70)"
|
||||||
|
value={extra_cash_retirement_pct}
|
||||||
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Only show the planned overrides if isEditMode is true */}
|
||||||
|
{isEditMode && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<hr className="my-4" />
|
||||||
|
<h2 className="text-xl font-medium">Planned Scenario Overrides</h2>
|
||||||
|
<p className="text-gray-600">
|
||||||
|
These fields let you override your real finances for this scenario.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block font-medium">Planned Monthly Expenses</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="planned_monthly_expenses"
|
||||||
|
value={planned_monthly_expenses}
|
||||||
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block font-medium">Planned Monthly Debt Payments</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="planned_monthly_debt_payments"
|
||||||
|
value={planned_monthly_debt_payments}
|
||||||
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block font-medium">Planned Monthly Retirement Contribution</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="planned_monthly_retirement_contribution"
|
||||||
|
value={planned_monthly_retirement_contribution}
|
||||||
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block font-medium">Planned Monthly Emergency Contribution</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="planned_monthly_emergency_contribution"
|
||||||
|
value={planned_monthly_emergency_contribution}
|
||||||
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block font-medium">Planned Surplus % to Emergency</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="planned_surplus_emergency_pct"
|
||||||
|
value={planned_surplus_emergency_pct}
|
||||||
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block font-medium">Planned Surplus % to Retirement</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="planned_surplus_retirement_pct"
|
||||||
|
value={planned_surplus_retirement_pct}
|
||||||
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block font-medium">Planned Additional Annual Income</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="planned_additional_income"
|
||||||
|
value={planned_additional_income}
|
||||||
|
onChange={handleChange}
|
||||||
|
className="w-full border rounded p-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
<button onClick={prevStep}>← Previous: Career</button>
|
|
||||||
<button onClick={nextStep}>Next: College →</button>
|
<div className="flex justify-between pt-4">
|
||||||
|
<button
|
||||||
|
onClick={prevStep}
|
||||||
|
className="bg-gray-200 hover:bg-gray-300 text-gray-700 font-semibold py-2 px-4 rounded"
|
||||||
|
>
|
||||||
|
← Previous: Career
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={nextStep}
|
||||||
|
className="bg-blue-500 hover:bg-blue-600 text-white font-semibold py-2 px-4 rounded"
|
||||||
|
>
|
||||||
|
Next: College →
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2,12 +2,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const PremiumWelcome = ({ nextStep }) => (
|
const PremiumWelcome = ({ nextStep }) => (
|
||||||
<div>
|
<div className="max-w-md mx-auto text-center p-6">
|
||||||
<h2>Welcome to AptivaAI Premium!</h2>
|
<h2 className="text-2xl font-semibold mb-4">Welcome to AptivaAI Premium!</h2>
|
||||||
<p>
|
<p className="mb-6">
|
||||||
Let's get started by gathering some quick information to personalize your experience.
|
Let's get started by gathering some quick information to personalize your experience.
|
||||||
</p>
|
</p>
|
||||||
<button onClick={nextStep}>Get Started</button>
|
<button
|
||||||
|
className="bg-blue-500 hover:bg-blue-600 text-white font-semibold py-2 px-4 rounded"
|
||||||
|
onClick={nextStep}
|
||||||
|
>
|
||||||
|
Get Started
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user