diff --git a/src/components/ScenarioEditModal.js b/src/components/ScenarioEditModal.js new file mode 100644 index 0000000..52dbf4c --- /dev/null +++ b/src/components/ScenarioEditModal.js @@ -0,0 +1,244 @@ +// src/components/ScenarioEditModal.js +import React, { useState, useEffect } from 'react'; +import authFetch from '../utils/authFetch'; + +const ScenarioEditModal = ({ + show, + onClose, + financialProfile, + setFinancialProfile, + collegeProfile, + setCollegeProfile, + apiURL, + authFetch, +}) => { + const [formData, setFormData] = useState({}); + + // Populate local formData whenever show=true + useEffect(() => { + if (!show) return; + + setFormData({ + // From financialProfile: + currentSalary: financialProfile?.current_salary ?? 0, + monthlyExpenses: financialProfile?.monthly_expenses ?? 0, + monthlyDebtPayments: financialProfile?.monthly_debt_payments ?? 0, + retirementSavings: financialProfile?.retirement_savings ?? 0, + emergencySavings: financialProfile?.emergency_fund ?? 0, + monthlyRetirementContribution: financialProfile?.retirement_contribution ?? 0, + monthlyEmergencyContribution: financialProfile?.emergency_contribution ?? 0, + surplusEmergencyAllocation: financialProfile?.extra_cash_emergency_pct ?? 50, + surplusRetirementAllocation: financialProfile?.extra_cash_retirement_pct ?? 50, + + // From collegeProfile: + studentLoanAmount: collegeProfile?.existing_college_debt ?? 0, + interestRate: collegeProfile?.interest_rate ?? 5, + loanTerm: collegeProfile?.loan_term ?? 10, + loanDeferralUntilGraduation: !!collegeProfile?.loan_deferral_until_graduation, + academicCalendar: collegeProfile?.academic_calendar ?? 'monthly', + annualFinancialAid: collegeProfile?.annual_financial_aid ?? 0, + calculatedTuition: collegeProfile?.tuition ?? 0, + extraPayment: collegeProfile?.extra_payment ?? 0, + partTimeIncome: 0, // or fetch from DB if you store it + gradDate: collegeProfile?.expected_graduation ?? '', + programType: collegeProfile?.program_type ?? '', + creditHoursPerYear: collegeProfile?.credit_hours_per_year ?? 0, + hoursCompleted: collegeProfile?.hours_completed ?? 0, + programLength: collegeProfile?.program_length ?? 0, + inCollege: + collegeProfile?.college_enrollment_status === 'currently_enrolled' || + collegeProfile?.college_enrollment_status === 'prospective_student', + expectedSalary: collegeProfile?.expected_salary ?? financialProfile?.current_salary ?? 0, + }); + }, [show, financialProfile, collegeProfile]); + + // Handle form changes in local state + const handleChange = (e) => { + const { name, type, value, checked } = e.target; + setFormData((prev) => ({ + ...prev, + [name]: + type === 'checkbox' + ? checked + : type === 'number' + ? parseFloat(value) || 0 + : value + })); + }; + + // SAVE: Update DB and local states, then close + const handleSave = async () => { + try { + // 1) Update the backend (financialProfile + collegeProfile): + // (Adjust endpoints/methods as needed in your codebase) + await authFetch(`${apiURL}/premium/financial-profile`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + current_salary: formData.currentSalary, + monthly_expenses: formData.monthlyExpenses, + monthly_debt_payments: formData.monthlyDebtPayments, + retirement_savings: formData.retirementSavings, + emergency_fund: formData.emergencySavings, + retirement_contribution: formData.monthlyRetirementContribution, + emergency_contribution: formData.monthlyEmergencyContribution, + extra_cash_emergency_pct: formData.surplusEmergencyAllocation, + extra_cash_retirement_pct: formData.surplusRetirementAllocation + }) + }); + + await authFetch(`${apiURL}/premium/college-profile`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + existing_college_debt: formData.studentLoanAmount, + interest_rate: formData.interestRate, + loan_term: formData.loanTerm, + loan_deferral_until_graduation: formData.loanDeferralUntilGraduation, + academic_calendar: formData.academicCalendar, + annual_financial_aid: formData.annualFinancialAid, + tuition: formData.calculatedTuition, + extra_payment: formData.extraPayment, + expected_graduation: formData.gradDate, + program_type: formData.programType, + credit_hours_per_year: formData.creditHoursPerYear, + hours_completed: formData.hoursCompleted, + program_length: formData.programLength, + college_enrollment_status: formData.inCollege + ? 'currently_enrolled' + : 'not_enrolled', + expected_salary: formData.expectedSalary + }) + }); + + // 2) Update local React state so your useEffect triggers re-simulation + setFinancialProfile((prev) => ({ + ...prev, + current_salary: formData.currentSalary, + monthly_expenses: formData.monthlyExpenses, + monthly_debt_payments: formData.monthlyDebtPayments, + retirement_savings: formData.retirementSavings, + emergency_fund: formData.emergencySavings, + retirement_contribution: formData.monthlyRetirementContribution, + emergency_contribution: formData.monthlyEmergencyContribution, + extra_cash_emergency_pct: formData.surplusEmergencyAllocation, + extra_cash_retirement_pct: formData.surplusRetirementAllocation + })); + + setCollegeProfile((prev) => ({ + ...prev, + existing_college_debt: formData.studentLoanAmount, + interest_rate: formData.interestRate, + loan_term: formData.loanTerm, + loan_deferral_until_graduation: formData.loanDeferralUntilGraduation, + academic_calendar: formData.academicCalendar, + annual_financial_aid: formData.annualFinancialAid, + tuition: formData.calculatedTuition, + extra_payment: formData.extraPayment, + expected_graduation: formData.gradDate, + program_type: formData.programType, + credit_hours_per_year: formData.creditHoursPerYear, + hours_completed: formData.hoursCompleted, + program_length: formData.programLength, + college_enrollment_status: formData.inCollege + ? 'currently_enrolled' + : 'not_enrolled', + expected_salary: formData.expectedSalary + })); + + // 3) Close the modal + onClose(); + } catch (err) { + console.error('Error saving scenario changes:', err); + // Optionally show a toast or error UI + } + }; + + // If show=false, don't render anything + if (!show) return null; + + return ( +
+
+

Edit Scenario Inputs

+ + {/* EXAMPLE FIELDS: Add all the fields you actually want visible */} +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + {/* Example checkbox for loan deferral */} +
+ + +
+ + {/* Add all other fields you want to expose... */} + + {/* Modal Buttons */} +
+ + +
+
+
+ ); +}; + +export default ScenarioEditModal; diff --git a/src/utils/FinancialProjectionService.js b/src/utils/FinancialProjectionService.js index e710c85..3532458 100644 --- a/src/utils/FinancialProjectionService.js +++ b/src/utils/FinancialProjectionService.js @@ -4,6 +4,64 @@ import moment from 'moment'; * Single-filer federal tax calculation (2023). * Includes standard deduction ($13,850). */ +const APPROX_STATE_TAX_RATES = { + AL: 0.05, + AK: 0.00, + AZ: 0.025, + AR: 0.05, + CA: 0.07, + CO: 0.045, + CT: 0.055, + DE: 0.05, + FL: 0.00, + GA: 0.05, + HI: 0.06, + ID: 0.058, + IL: 0.05, + IN: 0.035, + IA: 0.05, + KS: 0.05, + KY: 0.05, + LA: 0.04, + ME: 0.055, + MD: 0.05, + MA: 0.05, + MI: 0.0425, + MN: 0.06, + MS: 0.04, + MO: 0.05, + MT: 0.05, + NE: 0.05, + NV: 0.00, + NH: 0.00, // ignoring interest/dividend nuance + NJ: 0.057, + NM: 0.045, + NY: 0.06, + NC: 0.0475, + ND: 0.02, + OH: 0.04, + OK: 0.045, + OR: 0.07, + PA: 0.03, + RI: 0.045, + SC: 0.04, + SD: 0.00, + TN: 0.00, + TX: 0.00, + UT: 0.045, + VT: 0.055, + VA: 0.05, + WA: 0.00, + WV: 0.05, + WI: 0.05, + WY: 0.00, + DC: 0.05 +}; + +/** + * 2) Single-filer federal tax calculation (2023). + * Includes standard deduction ($13,850). + */ function calculateAnnualFederalTaxSingle(annualIncome) { const STANDARD_DEDUCTION_SINGLE = 13850; const taxableIncome = Math.max(0, annualIncome - STANDARD_DEDUCTION_SINGLE); @@ -35,20 +93,13 @@ function calculateAnnualFederalTaxSingle(annualIncome) { } /** - * Example state tax calculation. - * Currently a simple flat rate based on `stateCode` from a small dictionary. - * You can replace with bracket-based logic if desired. + * 3) Example approximate state tax calculation. + * Retrieves a single "effective" tax rate from the dictionary + * and returns a simple multiplication of annualIncome * rate. */ function calculateAnnualStateTax(annualIncome, stateCode) { - // Example dictionary of flat rates (not real data!) - const stateTaxInfo = { - CA: 0.08, // 8% - NY: 0.06, // 6% - TX: 0.00, - FL: 0.00, - GA: 0.05 - }; - const rate = stateTaxInfo[stateCode] ?? 0.05; // default 5% if not found + // Default to 5% if not found in dictionary + const rate = APPROX_STATE_TAX_RATES[stateCode] ?? 0.05; return annualIncome * rate; } diff --git a/user_profile.db b/user_profile.db index 8b437d7..a3a7644 100644 Binary files a/user_profile.db and b/user_profile.db differ