milestone tracker UI improvements - untested due to navigation issues
This commit is contained in:
parent
e1f1782b01
commit
9404135915
@ -1,5 +1,4 @@
|
|||||||
// src/components/MilestoneTracker.js
|
// src/components/MilestoneTracker.js
|
||||||
|
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
@ -22,8 +21,8 @@ import CareerSearch from './CareerSearch.js';
|
|||||||
import MilestoneTimeline from './MilestoneTimeline.js';
|
import MilestoneTimeline from './MilestoneTimeline.js';
|
||||||
import AISuggestedMilestones from './AISuggestedMilestones.js';
|
import AISuggestedMilestones from './AISuggestedMilestones.js';
|
||||||
import ScenarioEditModal from './ScenarioEditModal.js';
|
import ScenarioEditModal from './ScenarioEditModal.js';
|
||||||
import './MilestoneTracker.css';
|
import './MilestoneTracker.css'; // keeps your local styles
|
||||||
import './MilestoneTimeline.css';
|
import './MilestoneTimeline.css'; // keeps your local styles
|
||||||
import { simulateFinancialProjection } from '../utils/FinancialProjectionService.js';
|
import { simulateFinancialProjection } from '../utils/FinancialProjectionService.js';
|
||||||
|
|
||||||
ChartJS.register(
|
ChartJS.register(
|
||||||
@ -53,7 +52,7 @@ const MilestoneTracker = ({ selectedCareer: initialCareer }) => {
|
|||||||
// Real user snapshot
|
// Real user snapshot
|
||||||
const [financialProfile, setFinancialProfile] = useState(null);
|
const [financialProfile, setFinancialProfile] = useState(null);
|
||||||
|
|
||||||
// Scenario row (with planned_* overrides) from GET /api/premium/career-profile/:careerPathId
|
// Scenario row (with planned_* overrides)
|
||||||
const [scenarioRow, setScenarioRow] = useState(null);
|
const [scenarioRow, setScenarioRow] = useState(null);
|
||||||
|
|
||||||
// scenario's collegeProfile row
|
// scenario's collegeProfile row
|
||||||
@ -151,8 +150,7 @@ const MilestoneTracker = ({ selectedCareer: initialCareer }) => {
|
|||||||
}, [careerPathId, apiURL]);
|
}, [careerPathId, apiURL]);
|
||||||
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
// 3) Once we have (financialProfile, scenarioRow, collegeProfile),
|
// 3) Once we have (financialProfile, scenarioRow, collegeProfile), run initial simulation
|
||||||
// run initial simulation with the scenario's milestones + impacts
|
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!financialProfile || !scenarioRow || !collegeProfile) return;
|
if (!financialProfile || !scenarioRow || !collegeProfile) return;
|
||||||
@ -168,7 +166,7 @@ const MilestoneTracker = ({ selectedCareer: initialCareer }) => {
|
|||||||
const milestonesData = await milRes.json();
|
const milestonesData = await milRes.json();
|
||||||
const allMilestones = milestonesData.milestones || [];
|
const allMilestones = milestonesData.milestones || [];
|
||||||
|
|
||||||
// 2) fetch impacts for each
|
// 2) fetch impacts for each milestone
|
||||||
const impactPromises = allMilestones.map(m =>
|
const impactPromises = allMilestones.map(m =>
|
||||||
authFetch(`${apiURL}/premium/milestone-impacts?milestone_id=${m.id}`)
|
authFetch(`${apiURL}/premium/milestone-impacts?milestone_id=${m.id}`)
|
||||||
.then(r => r.ok ? r.json() : null)
|
.then(r => r.ok ? r.json() : null)
|
||||||
@ -185,7 +183,7 @@ const MilestoneTracker = ({ selectedCareer: initialCareer }) => {
|
|||||||
}));
|
}));
|
||||||
const allImpacts = milestonesWithImpacts.flatMap(m => m.impacts);
|
const allImpacts = milestonesWithImpacts.flatMap(m => m.impacts);
|
||||||
|
|
||||||
// 3) Build the merged profile w/ scenario overrides
|
// 3) Build the merged profile
|
||||||
const mergedProfile = buildMergedProfile(
|
const mergedProfile = buildMergedProfile(
|
||||||
financialProfile,
|
financialProfile,
|
||||||
scenarioRow,
|
scenarioRow,
|
||||||
@ -377,7 +375,8 @@ const MilestoneTracker = ({ selectedCareer: initialCareer }) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="milestone-tracker">
|
<div className="milestone-tracker max-w-screen-lg mx-auto px-4 py-6 space-y-6">
|
||||||
|
{/* Career Select */}
|
||||||
<CareerSelectDropdown
|
<CareerSelectDropdown
|
||||||
existingCareerPaths={existingCareerPaths}
|
existingCareerPaths={existingCareerPaths}
|
||||||
selectedCareer={selectedCareer}
|
selectedCareer={selectedCareer}
|
||||||
@ -389,6 +388,7 @@ const MilestoneTracker = ({ selectedCareer: initialCareer }) => {
|
|||||||
authFetch={authFetch}
|
authFetch={authFetch}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Milestone Timeline */}
|
||||||
<MilestoneTimeline
|
<MilestoneTimeline
|
||||||
careerPathId={careerPathId}
|
careerPathId={careerPathId}
|
||||||
authFetch={authFetch}
|
authFetch={authFetch}
|
||||||
@ -397,6 +397,7 @@ const MilestoneTracker = ({ selectedCareer: initialCareer }) => {
|
|||||||
onMilestoneUpdated={reSimulate}
|
onMilestoneUpdated={reSimulate}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* AI-Suggested Milestones */}
|
||||||
<AISuggestedMilestones
|
<AISuggestedMilestones
|
||||||
career={selectedCareer?.career_name}
|
career={selectedCareer?.career_name}
|
||||||
careerPathId={careerPathId}
|
careerPathId={careerPathId}
|
||||||
@ -405,9 +406,10 @@ const MilestoneTracker = ({ selectedCareer: initialCareer }) => {
|
|||||||
projectionData={projectionData}
|
projectionData={projectionData}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Chart Section */}
|
||||||
{projectionData.length > 0 && (
|
{projectionData.length > 0 && (
|
||||||
<div className="bg-white p-4 mt-6 rounded shadow">
|
<div className="bg-white p-4 rounded shadow space-y-4">
|
||||||
<h3 className="text-lg font-semibold mb-2">Financial Projection</h3>
|
<h3 className="text-lg font-semibold">Financial Projection</h3>
|
||||||
<Line
|
<Line
|
||||||
data={{
|
data={{
|
||||||
labels: projectionData.map((p) => p.month),
|
labels: projectionData.map((p) => p.month),
|
||||||
@ -485,22 +487,26 @@ const MilestoneTracker = ({ selectedCareer: initialCareer }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="mt-4">
|
{/* Simulation Length Input */}
|
||||||
<label>Simulation Length (years): </label>
|
<div className="space-x-2">
|
||||||
|
<label className="font-medium">Simulation Length (years):</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={simulationYearsInput}
|
value={simulationYearsInput}
|
||||||
onChange={handleSimulationYearsChange}
|
onChange={handleSimulationYearsChange}
|
||||||
onBlur={handleSimulationYearsBlur}
|
onBlur={handleSimulationYearsBlur}
|
||||||
|
className="border rounded p-1 w-16"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Career Search */}
|
||||||
<CareerSearch
|
<CareerSearch
|
||||||
onCareerSelected={(careerObj) => {
|
onCareerSelected={(careerObj) => {
|
||||||
setPendingCareerForModal(careerObj.title);
|
setPendingCareerForModal(careerObj.title);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Modal */}
|
||||||
<ScenarioEditModal
|
<ScenarioEditModal
|
||||||
show={showEditModal}
|
show={showEditModal}
|
||||||
onClose={() => setShowEditModal(false)}
|
onClose={() => setShowEditModal(false)}
|
||||||
@ -512,15 +518,15 @@ const MilestoneTracker = ({ selectedCareer: initialCareer }) => {
|
|||||||
authFetch={authFetch}
|
authFetch={authFetch}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Confirm new career scenario */}
|
||||||
{pendingCareerForModal && (
|
{pendingCareerForModal && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// Example: Actually adopt this career as a new scenario or update the DB
|
// Example action
|
||||||
console.log('User confirmed new career path:', pendingCareerForModal);
|
console.log('User confirmed new career path:', pendingCareerForModal);
|
||||||
// Perhaps you open another modal or POST to your API
|
|
||||||
// Then reset pendingCareerForModal:
|
|
||||||
setPendingCareerForModal(null);
|
setPendingCareerForModal(null);
|
||||||
}}
|
}}
|
||||||
|
className="bg-blue-500 hover:bg-blue-600 text-white font-semibold px-4 py-2 rounded"
|
||||||
>
|
>
|
||||||
Confirm Career Change to {pendingCareerForModal}
|
Confirm Career Change to {pendingCareerForModal}
|
||||||
</button>
|
</button>
|
||||||
|
Loading…
Reference in New Issue
Block a user