Added data flow fixes for Confirm Career Selection button and rendering logic fix

This commit is contained in:
Josh 2025-03-25 15:55:30 +00:00
parent b3ff06c0fc
commit dd1d6bec88
4 changed files with 78 additions and 41 deletions

View File

@ -1,13 +1,14 @@
import React, { useState, useEffect } from "react";
import { Input } from "./ui/input.js"; // Assuming Input is a basic text input component
const CareerSearch = ({ onSelectCareer, initialCareer }) => {
const CareerSearch = ({ onSelectCareer, existingCareerPaths }) => {
const [careerClusters, setCareerClusters] = useState({});
const [selectedCluster, setSelectedCluster] = useState("");
const [selectedSubdivision, setSelectedSubdivision] = useState("");
const [selectedCareer, setSelectedCareer] = useState("");
const [careerSearch, setCareerSearch] = useState("");
useEffect(() => {
const fetchCareerClusters = async () => {
try {
@ -62,6 +63,12 @@ const CareerSearch = ({ onSelectCareer, initialCareer }) => {
// Get careers based on selected subdivision
const careers = selectedSubdivision ? careerClusters[selectedCluster]?.[selectedSubdivision] || [] : [];
// Check if the selected career already has an existing career path
const hasCareerPath = existingCareerPaths.some(career => career.title === selectedCareer);
// Check if the selected career is the current one
const isCurrentCareer = selectedCareer === selectedCareer?.career_name;
return (
<div>
{/* Career Cluster Selection */}
@ -119,8 +126,35 @@ const CareerSearch = ({ onSelectCareer, initialCareer }) => {
)}
{/* Display selected career */}
{selectedCareer && <div>Selected Career: {selectedCareer}</div>}
{selectedCareer && (
<div style={{ marginTop: '10px' }}>
<div>Selected Career: {selectedCareer}</div>
{!hasCareerPath && (
<button
onClick={() => {
const matchedCareer = careers.find(
(c) => c.title.toLowerCase() === selectedCareer.toLowerCase()
);
if (matchedCareer) {
onSelectCareer(matchedCareer.title, matchedCareer.soc); // 🔥 this triggers the update upstream
} else {
alert("Please select a valid career from the list.");
}
}}
>
Confirm Career Selection
</button>
)}
</div>
)}
{hasCareerPath && (
<p>This career already has a career path. Do you want to reload it or create a new one?</p>
)}
{isCurrentCareer && (
<p>You are already on this career path.</p>
)}
</div>
);
};

View File

@ -38,7 +38,7 @@ function GettingStarted() {
<div className="premium-access">
<h3>Already know your path?</h3>
<p>You can skip ahead and begin planning your milestones now.</p>
<button className="premium-button" onClick={() => navigate('/milestone-tracker')}>
<button className="premium-button" onClick={() => navigate('/milestone-tracker', { state: { fromGettingStarted: true } })}>
Access Milestone Tracker <span className="premium-label">(Premium)</span>
</button>
</div>

View File

@ -31,6 +31,9 @@ const MilestoneTracker = ({ selectedCareer: initialCareer, careerClusters }) =>
const [careerSubdivision, setCareerSubdivision] = useState('');
const [loading, setLoading] = useState(false);
const [sessionHandled, setSessionHandled] = useState(false);
const [hasHandledCareerPath, setHasHandledCareerPath] = useState(false);
const [existingCareerPaths, setExistingCareerPaths] = useState([]); // To store existing career paths
const handleUnauthorized = () => {
@ -42,23 +45,28 @@ const MilestoneTracker = ({ selectedCareer: initialCareer, careerClusters }) =>
const apiURL = process.env.REACT_APP_API_URL;
useEffect(() => {
if (selectedCareer) {
// First check when user navigates to this page
handleCareerPathDecision(selectedCareer);
}
}, [selectedCareer]);
const fetchExistingPaths = async () => {
const response = await fetch('/api/career-paths'); // Replace with the actual API endpoint
const data = await response.json();
setExistingCareerPaths(data);
};
fetchExistingPaths();
}, []);
useEffect(() => {
if (location.state?.selectedCareer) {
setSelectedCareer(location.state.selectedCareer);
setCareerPathId(location.state.selectedCareer.career_path_id);
loadMilestonesFromServer(location.state.selectedCareer.career_path_id);
} else {
console.warn('No career selected; prompting user to select one.');
setCareerPathId(null);
const fromState = location.state?.selectedCareer;
if (fromState && !hasHandledCareerPath) {
setSelectedCareer(fromState);
setCareerPathId(fromState.career_path_id);
loadMilestonesFromServer(fromState.career_path_id);
handleCareerPathDecision(fromState.career_name);
setHasHandledCareerPath(true);
}
}, [location.state]);
useEffect(() => {
loadMilestonesFromServer();
}, [selectedCareer]);
@ -85,10 +93,12 @@ const MilestoneTracker = ({ selectedCareer: initialCareer, careerClusters }) =>
})
.then(data => {
if (data && data.id) {
if (!location.state?.selectedCareer && data && data.id) {
setCareerPathId(data.id);
} else {
setCareerPathId(null); // No existing career path for new user
setSelectedCareer({
career_name: data.career_name,
career_path_id: data.id,
});
}
})
.catch((error) => {
@ -129,8 +139,11 @@ const MilestoneTracker = ({ selectedCareer: initialCareer, careerClusters }) =>
};
const handleCareerPathDecision = async (careerName) => {
if (hasHandledCareerPath || !careerName || careerName === 'Not Selected') return; // ✅ already processed, do nothing
setHasHandledCareerPath(true); // ✅ prevent duplicate handling
setLoading(true);
const token = localStorage.getItem('token');
const response = await authFetch('/api/premium/planned-path', {
method: 'POST',
body: JSON.stringify({ career_name: careerName }),
@ -142,6 +155,8 @@ const MilestoneTracker = ({ selectedCareer: initialCareer, careerClusters }) =>
const data = await response.json();
setLoading(false);
const fromGettingStarted = location?.state?.fromGettingStarted;
if (data.action_required === 'reload_or_create') {
const decision = window.confirm( `A career path for "${data.title}" already exists.\n\nClick OK to RELOAD the existing path.\nClick Cancel to CREATE a new one.`);
@ -153,8 +168,12 @@ const MilestoneTracker = ({ selectedCareer: initialCareer, careerClusters }) =>
} else if (data.action_required === 'new_created') {
setCareerPathId(data.career_path_id);
}
if (fromGettingStarted) {
navigate(location.pathname, { replace: true, state: {} }); // clear state
}
};
const reloadExistingCareerPath = (careerPathId) => {
console.log('Reloading career path with ID:', careerPathId);
setCareerPathId(careerPathId);
@ -217,26 +236,9 @@ const MilestoneTracker = ({ selectedCareer: initialCareer, careerClusters }) =>
useEffect(() => {
if (selectedCareer) {
fetchAISuggestedMilestones(selectedCareer?.career_name);
prepopulateCareerFields(selectedCareer?.career_name);
}
}, [selectedCareer]);
const prepopulateCareerFields = (career) => {
if (!careerClusters) return;
for (const cluster in careerClusters) {
for (const subdivision in careerClusters[cluster]) {
if (careerClusters[cluster][subdivision].some(job => job.title === career)) {
setCareerCluster(cluster);
setCareerSubdivision(subdivision);
return;
}
}
}
setCareerCluster('');
setCareerSubdivision('');
};
const handleAddMilestone = async () => {
if (!careerPathId) {
console.error('No career_path_id available for milestone.');
@ -328,7 +330,6 @@ const MilestoneTracker = ({ selectedCareer: initialCareer, careerClusters }) =>
const handleCareerSelection = async (career, socCode) => {
setSelectedCareer(career);
setSelectedSocCode(socCode);
prepopulateCareerFields(career);
const token = localStorage.getItem('token');
try {
@ -559,17 +560,19 @@ const MilestoneTracker = ({ selectedCareer: initialCareer, careerClusters }) =>
<p>Not sure about this career path? Choose a different one here.</p>
<CareerSearch
onSelectCareer={handleCareerSelection}
existingCareerPaths={existingCareerPaths}
initialCareer={selectedCareer}
cluster={careerCluster}
subdivision={careerSubdivision}
/>
{selectedCareer && !careerPathId && (
{selectedCareer && (
<>
{selectedCareer !== selectedCareer?.career_name && (
<button onClick={() => setShowModal(true)} style={{ marginTop: '10px' }}>
Confirm Career Selection
</button>
)}
{showModal && (
<div className="modal-overlay">
<div className="modal">

Binary file not shown.