dev1/src/components/MultiScenarioView.js

249 lines
8.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

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.

// src/components/MultiScenarioView.js
import React, { useEffect, useState } from 'react';
import authFetch from '../utils/authFetch.js';
import ScenarioContainer from './ScenarioContainer.js';
import { Button } from './ui/button.js';
export default function MultiScenarioView() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
// The users single overall financial profile
const [financialProfile, setFinancialProfile] = useState(null);
// The list of scenario "headers" (rows from career_profiles)
const [scenarios, setScenarios] = useState([]);
useEffect(() => {
loadScenariosAndFinancial();
}, []);
/**
* Fetch users financial profile + scenario list
*/
async function loadScenariosAndFinancial() {
setLoading(true);
setError(null);
try {
// 1) fetch users global financialProfile
const finRes = await authFetch('/api/premium/financial-profile');
if (!finRes.ok) throw new Error(`FinancialProfile error: ${finRes.status}`);
const finData = await finRes.json();
// 2) fetch scenario list
const scenRes = await authFetch('/api/premium/career-profile/all');
if (!scenRes.ok) throw new Error(`Scenarios error: ${scenRes.status}`);
const scenData = await scenRes.json();
setFinancialProfile(finData);
setScenarios(scenData.careerProfiles || []);
} catch (err) {
console.error('MultiScenarioView load error:', err);
setError(err.message || 'Failed to load multi-scenarios');
} finally {
setLoading(false);
}
}
/**
* Create a brand-new scenario with minimal defaults
*/
async function handleAddScenario() {
try {
const body = {
career_name: 'New Scenario ' + new Date().toLocaleDateString(),
status: 'planned',
start_date: new Date().toISOString(),
college_enrollment_status: 'not_enrolled',
currently_working: 'no'
};
const res = await authFetch('/api/premium/career-profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
if (!res.ok) throw new Error(`Add scenario error: ${res.status}`);
// reload
await loadScenariosAndFinancial();
} catch (err) {
alert(err.message);
}
}
/**
* Clone a scenario:
* (A) create new scenario row from old scenario fields
* (B) also clone old scenarios college_profile
*/
async function handleCloneScenario(oldScenario) {
try {
// 1) create the new scenario row
const scenarioPayload = {
scenario_title: oldScenario.scenario_title
? oldScenario.scenario_title + ' (Copy)'
: null,
career_name: oldScenario.career_name
? oldScenario.career_name + ' (Copy)'
: 'Untitled (Copy)',
status: oldScenario.status,
start_date: oldScenario.start_date,
projected_end_date: oldScenario.projected_end_date,
college_enrollment_status: oldScenario.college_enrollment_status,
currently_working: oldScenario.currently_working || 'no',
planned_monthly_expenses: oldScenario.planned_monthly_expenses,
planned_monthly_debt_payments: oldScenario.planned_monthly_debt_payments,
planned_monthly_retirement_contribution:
oldScenario.planned_monthly_retirement_contribution,
planned_monthly_emergency_contribution:
oldScenario.planned_monthly_emergency_contribution,
planned_surplus_emergency_pct: oldScenario.planned_surplus_emergency_pct,
planned_surplus_retirement_pct:
oldScenario.planned_surplus_retirement_pct,
planned_additional_income: oldScenario.planned_additional_income
};
const res = await authFetch('/api/premium/career-profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(scenarioPayload)
});
if (!res.ok) throw new Error(`Clone scenario error: ${res.status}`);
// parse the newly created scenario_id
const newScenarioData = await res.json();
const newScenarioId = newScenarioData.career_profile_id;
// 2) Clone the old scenarios college_profile => new scenario
await cloneCollegeProfile(oldScenario.id, newScenarioId);
// 3) reload
await loadScenariosAndFinancial();
} catch (err) {
alert(`Clone scenario failed: ${err.message}`);
}
}
async function cloneCollegeProfile(oldScenarioId, newScenarioId) {
try {
// fetch old scenarios college_profile
const getRes = await authFetch(
`/api/premium/college-profile?careerProfileId=${oldScenarioId}`
);
if (!getRes.ok) {
console.warn(
'Could not fetch old college profile for scenarioId=' + oldScenarioId
);
return;
}
let oldCollegeData = await getRes.json();
if (Array.isArray(oldCollegeData)) {
oldCollegeData = oldCollegeData[0] || null;
}
if (!oldCollegeData || !oldCollegeData.id) {
// no old college profile => nothing to clone
return;
}
// build new payload
const clonePayload = {
career_profile_id: newScenarioId,
selected_school: oldCollegeData.selected_school,
selected_program: oldCollegeData.selected_program,
program_type: oldCollegeData.program_type,
academic_calendar: oldCollegeData.academic_calendar,
is_in_state: oldCollegeData.is_in_state,
is_in_district: oldCollegeData.is_in_district,
is_online: oldCollegeData.is_online,
college_enrollment_status: oldCollegeData.college_enrollment_status,
annual_financial_aid: oldCollegeData.annual_financial_aid,
existing_college_debt: oldCollegeData.existing_college_debt,
tuition_paid: oldCollegeData.tuition_paid,
tuition: oldCollegeData.tuition,
loan_deferral_until_graduation: oldCollegeData.loan_deferral_until_graduation,
loan_term: oldCollegeData.loan_term,
interest_rate: oldCollegeData.interest_rate,
extra_payment: oldCollegeData.extra_payment,
credit_hours_per_year: oldCollegeData.credit_hours_per_year,
hours_completed: oldCollegeData.hours_completed,
program_length: oldCollegeData.program_length,
credit_hours_required: oldCollegeData.credit_hours_required,
expected_graduation: oldCollegeData.expected_graduation,
expected_salary: oldCollegeData.expected_salary
};
// insert new row in college_profiles
const postRes = await authFetch('/api/premium/college-profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(clonePayload)
});
if (!postRes.ok) {
console.warn(
'Could not clone old collegeProfile => new scenario',
postRes.status
);
}
} catch (err) {
console.error('Error cloning college profile:', err);
}
}
async function handleRemoveScenario(id) {
const confirmDel = window.confirm('Delete this scenario?');
if (!confirmDel) return;
try {
const res = await authFetch(`/api/premium/career-profile/${id}`, {
method: 'DELETE'
});
if (!res.ok) throw new Error(`Delete scenario error: ${res.status}`);
await loadScenariosAndFinancial();
} catch (err) {
alert(err.message);
}
}
if (loading) return <p>Loading scenarios...</p>;
if (error) return <p style={{ color: 'red' }}>{error}</p>;
// show only first 2 scenarios
const visibleScenarios = scenarios.slice(0, 2);
return (
<div style={{ margin: '1rem' }}>
{/* Add Scenario button */}
<div style={{ marginBottom: '1rem' }}>
<Button onClick={handleAddScenario}>+ Add Scenario</Button>
</div>
{/* Display 1 or 2 scenarios side by side */}
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '1rem' }}>
{visibleScenarios.map((sc) => (
<ScenarioContainer
key={sc.id}
scenario={sc}
financialProfile={financialProfile}
onClone={handleCloneScenario} // <--- pass down
onRemove={handleRemoveScenario} // <--- pass down
onEdit={(sc) => {
console.log('Edit scenario clicked:', sc);
// or open a modal if you prefer
}}
hideMilestones // if you want to hide milestone details
/>
))}
</div>
</div>
);
}