dev1/src/components/CareerSuggestions.js

124 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useState } from 'react';
import axios from 'axios';
import './Dashboard.css';
const apiUrl = process.env.REACT_APP_API_URL || ''; // ✅ Load API URL directly
export function CareerSuggestions({ careerSuggestions = [], userState, areaTitle, onCareerClick }) {
const [updatedCareers, setUpdatedCareers] = useState([]);
const [loading, setLoading] = useState(true);
const [progress, setProgress] = useState(0);
useEffect(() => {
if (!careerSuggestions || careerSuggestions.length === 0) {
setLoading(false);
return;
}
const token = localStorage.getItem('token'); // Get auth token
const checkCareerDataAvailability = async () => {
setLoading(true);
setProgress(0);
const totalSteps = careerSuggestions.length * 4; // Each career has 4 API checks
let completedSteps = 0;
const updateProgress = () => {
completedSteps += 1;
setProgress((completedSteps / totalSteps) * 100);
};
const careerPromises = careerSuggestions.map(async (career) => {
try {
console.log(`Checking data for: ${career.title} (${career.code})`);
const headers = {
Authorization: `Bearer ${token}`,
Accept: 'application/json',
};
const fetchJSON = async (url) => {
try {
const response = await axios.get(url, { headers });
updateProgress(); // ✅ Update progress on success
return response.data;
} catch (error) {
console.warn(`⚠️ Error fetching ${url}:`, error.response?.status);
updateProgress(); // ✅ Update progress even if failed
return null;
}
};
// Step 1: Fetch CIP Code
const cipData = await fetchJSON(`${apiUrl}/cip/${career.code}`);
const isCipMissing = !cipData || Object.keys(cipData).length === 0;
// Step 2: Fetch Job Description & Tasks
const jobDetailsData = await fetchJSON(`${apiUrl}/onet/career-description/${career.code}`);
const isJobDetailsMissing = !jobDetailsData || Object.keys(jobDetailsData).length === 0;
// 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,
}).then((res) => {
updateProgress();
return res.data;
}).catch((error) => {
updateProgress();
return error.response?.status === 404 ? null : error.response;
}),
]);
const isEconomicMissing = !economicData || Object.keys(economicData).length === 0;
const isSalaryMissing = !salaryResponse;
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 };
}
});
const updatedCareerList = await Promise.all(careerPromises);
setUpdatedCareers(updatedCareerList);
setLoading(false);
};
checkCareerDataAvailability();
}, [careerSuggestions, apiUrl, userState, areaTitle]);
return (
<div>
<h2>Career Suggestions</h2>
{loading ? (
<div className="progress-container">
<div className="progress-bar" style={{ width: `${progress}%` }}>
{Math.round(progress)}%
</div>
<p>Loading Career Suggestions...</p>
</div>
) : (
<div className="career-suggestions-grid">
{updatedCareers.map((career) => (
<button
key={career.code}
className={`career-button ${career.limitedData ? 'limited-data' : ''}`}
onClick={() => onCareerClick(career)}
>
{career.title} {career.limitedData && <span className="warning-icon"></span>}
</button>
))}
</div>
)}
</div>
);
}
export default CareerSuggestions;