diff --git a/src/components/CareerSuggestions.js b/src/components/CareerSuggestions.js index a20be08..29b9ae1 100644 --- a/src/components/CareerSuggestions.js +++ b/src/components/CareerSuggestions.js @@ -1,29 +1,114 @@ -import React from 'react'; -import './CareerSuggestions.css'; +import React, { useEffect, useState } from 'react'; +import axios from 'axios'; +import './Dashboard.css'; -export function CareerSuggestions({ careerSuggestions = [], onCareerClick }) { - if (!Array.isArray(careerSuggestions) || careerSuggestions.length === 0) { - return

No career suggestions available. Please check back later.

; +const apiUrl = process.env.REACT_APP_API_URL || ''; // ✅ Load API URL directly + +export function CareerSuggestions({ careerSuggestions = [], userState, areaTitle, onCareerClick }) { + const [updatedCareers, setUpdatedCareers] = useState([]); + + useEffect(() => { + if (!careerSuggestions || careerSuggestions.length === 0) return; + + const token = localStorage.getItem('token'); // Get auth token + + const checkCareerDataAvailability = async () => { + const careerPromises = careerSuggestions.map(async (career) => { + try { + console.log(`Checking data for: ${career.title} (${career.code})`); + + console.log(`Fetching CIP Code from: ${apiUrl}/cip/${career.code}`); + console.log(`Fetching Job Description from: ${apiUrl}/onet/career-description/${career.code}`); + console.log(`Fetching Economic Projections from: ${apiUrl}/projections/${career.code.split('.')[0]}`); + console.log(`Fetching Salary Data from: ${apiUrl}/salary?socCode=${career.code.split('.')[0]}`); + const headers = { + Authorization: `Bearer ${token}`, // Match Dashboard.js headers + Accept: 'application/json', // Ensure JSON response + }; + + // Helper function to fetch and check JSON responses + const fetchJSON = async (url) => { + try { + const response = await axios.get(url, { headers }); + return response.data; + } catch (error) { + console.warn(`⚠️ Error fetching ${url}:`, error.response?.status, error.response?.data); + return null; // Return null if request fails + } + }; + + // Step 1: Fetch CIP Code + const cipData = await fetchJSON(`${apiUrl}/cip/${career.code}`); + const isCipMissing = !cipData || Object.keys(cipData).length === 0; + console.log(`CIP Code for ${career.code}:`, cipData); + + // Step 2: Fetch Job Description & Tasks + const jobDetailsData = await fetchJSON(`${apiUrl}/onet/career-description/${career.code}`); + const isJobDetailsMissing = !jobDetailsData || Object.keys(jobDetailsData).length === 0; + console.log(`Job Details for ${career.code}:`, jobDetailsData); + + // Step 3: Fetch Salary & Economic Projections in Parallel + const [economicData, salaryResponse] = await Promise.all([ + fetchJSON(`${apiUrl}/projections/${career.code.split('.')[0]}`), + axios.get(`${apiUrl}/salary`, { + params: { socCode: career.code.split('.')[0], area: areaTitle }, + headers, + }).catch((error) => error.response), // Catch error for 404 handling + ]); + + const isEconomicMissing = !economicData || Object.keys(economicData).length === 0; + console.log(`Economic Data for ${career.code}:`, economicData); + + // Salary check: If it fails with 404, we know it's missing + const isSalaryMissing = salaryResponse?.status === 404; + if (isSalaryMissing) { + console.log(`⚠️ Missing Salary Data for ${career.title} (${career.code})`); + } + + // Debugging: Log when a career is missing data + if (isCipMissing || isJobDetailsMissing || isEconomicMissing || isSalaryMissing) { + console.log(`⚠️ Limited Data for ${career.title} (${career.code})`); + } + + // Set `limitedData` to true if any required data is missing + const isLimitedData = isCipMissing || isJobDetailsMissing || isEconomicMissing || isSalaryMissing; + + return { ...career, limitedData: isLimitedData }; + } catch (error) { + console.error(`Error checking API response for ${career.title}:`, error); + return { ...career, limitedData: true }; // Mark as limited if any request fails + } + }); + + const updatedCareerList = await Promise.all(careerPromises); + + console.log("✅ Final Updated Careers with limitedData:", updatedCareerList); + setUpdatedCareers(updatedCareerList); + }; + + checkCareerDataAvailability(); + }, [careerSuggestions, apiUrl, userState, areaTitle]); + + if (updatedCareers.length === 0) { + return

Loading career suggestions...

; } return (

Career Suggestions

- {careerSuggestions.map((career) => { - return ( - - ); - })} + {updatedCareers.map((career) => ( + + ))}
); } -export default CareerSuggestions; \ No newline at end of file +export default CareerSuggestions; diff --git a/src/components/Dashboard.css b/src/components/Dashboard.css index 965e24b..543e323 100644 --- a/src/components/Dashboard.css +++ b/src/components/Dashboard.css @@ -87,16 +87,20 @@ h2 { border-radius: 3px; /* Less rounded */ } -.career-button.warning { - border: 2px solid black; /* Example warning border */ - background-color: #f8d7da; /* Example background color */ +/* Limited Data Warning: Yellow Button */ +.career-button.limited-data { + background-color: lightblue !important; + color: whitesmoke; + font-weight: bold; + border: 2px solid #ff9800; /* Orange border for emphasis */ } /* Warning Icon */ .warning-icon { margin-left: 6px; font-size: 14px; - color: yellow; /* Yellow to indicate limited data */ + color: yellow; /* Dark orange to indicate caution */ + font-weight: bold; } .career-button:hover { diff --git a/src/components/Dashboard.js b/src/components/Dashboard.js index 9733246..68c5067 100644 --- a/src/components/Dashboard.js +++ b/src/components/Dashboard.js @@ -137,6 +137,7 @@ function Dashboard() { setEconomicProjections({}); // Reset economic projections setTuitionData([]); // Reset tuition data + if (!socCode) { console.error('SOC Code is missing'); setError('SOC Code is missing'); diff --git a/src/components/PopoutPanel.js b/src/components/PopoutPanel.js index 57d2b32..454f9d5 100644 --- a/src/components/PopoutPanel.js +++ b/src/components/PopoutPanel.js @@ -1,7 +1,7 @@ import { ClipLoader } from 'react-spinners'; import LoanRepayment from './LoanRepayment.js'; import './PopoutPanel.css'; -import { useState } from 'react'; +import { useState, useEffect } from 'react'; function PopoutPanel({ data = {}, @@ -16,6 +16,13 @@ function PopoutPanel({ const [results, setResults] = useState([]); // Store loan repayment calculation results const [loadingCalculation, setLoadingCalculation] = useState(false); + // ✅ Reset `results` when a new career is selected +useEffect(() => { + console.log(`Career changed to: ${data?.title}, clearing previous loan results.`); + setResults([]); // ✅ Clears results when a new career is selected + setIsCalculated(false); // ✅ Reset calculation state +}, [data]); // Runs whenever `data` changes (i.e., new career is selected) + // Handle loading state if (loading) { return ( @@ -153,7 +160,7 @@ function PopoutPanel({ {/* Results Display */} {results.length > 0 && (
-

Comparisons by School over the life of the loan - assumes a starting salary in the lowest 10%

+

Comparisons by School over the life of the loan

{results.map((result, index) => (

{result.schoolName} - {result.degreeType || 'Degree type not available'}