From f8bf022b54bddf147682a6afdc2fb20b956f6b64 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 5 Aug 2025 15:34:20 +0000 Subject: [PATCH] Fixed staging handlecareerclick. .pems are in this one --- ca.pem | 0 client-cert.pem | 0 client-key.pem | 0 src/components/CareerExplorer.js | 113 +++++++++++++++++-------------- 4 files changed, 61 insertions(+), 52 deletions(-) create mode 100644 ca.pem create mode 100644 client-cert.pem create mode 100644 client-key.pem diff --git a/ca.pem b/ca.pem new file mode 100644 index 0000000..e69de29 diff --git a/client-cert.pem b/client-cert.pem new file mode 100644 index 0000000..e69de29 diff --git a/client-key.pem b/client-key.pem new file mode 100644 index 0000000..e69de29 diff --git a/src/components/CareerExplorer.js b/src/components/CareerExplorer.js index cadbdfa..e88f2fe 100644 --- a/src/components/CareerExplorer.js +++ b/src/components/CareerExplorer.js @@ -339,59 +339,69 @@ function CareerExplorer() { } }, [location.state, userProfile, fetchSuggestions, navigate]); - /* ------------------------------------------------------ - handleCareerClick – fetches all details for one career - ---------------------------------------------------- */ + // ------------------------------------------------------ +// handleCareerClick – fetch & build data for one career +// ------------------------------------------------------ const handleCareerClick = useCallback( async (career) => { const socCode = career.code; if (!socCode) return; + /* Reset modal state & show spinner */ setSelectedCareer(career); - setCareerDetails(null); // reset any previous modal + setCareerDetails(null); setLoading(true); try { /* ---------- 1. CIP lookup ---------- */ let cipCode = null; - const cipRes = await fetch(`/api/cip/${socCode}`); - if (cipRes.ok) { - cipCode = (await cipRes.json()).cipCode ?? null; - } + try { + const cipRes = await fetch(`/api/cip/${socCode}`); + if (cipRes.ok) { + cipCode = (await cipRes.json()).cipCode ?? null; + } + } catch { /* swallow */ } /* ---------- 2. Job description & tasks ---------- */ let description = ''; let tasks = []; - const jobRes = await fetch(`/api/onet/career-description/${socCode}`); - if (jobRes.ok) { - const jd = await jobRes.json(); - description = jd.description ?? ''; - tasks = jd.tasks ?? []; - } + try { + const jobRes = await fetch(`/api/onet/career-description/${socCode}`); + if (jobRes.ok) { + const jd = await jobRes.json(); + description = jd.description ?? ''; + tasks = jd.tasks ?? []; + } + } catch { /* swallow */ } /* ---------- 3. Salary data ---------- */ - const salaryRes = await axios.get('/api/salary', { - params: { socCode: socCode.split('.')[0], area: areaTitle }, - }).catch(() => ({ data: {} })); + const salaryRes = await axios + .get('/api/salary', { + params: { socCode: socCode.split('.')[0], area: areaTitle }, + }) + .catch(() => ({ data: {} })); const s = salaryRes.data; - const salaryDataPoints = s && Object.keys(s).length > 0 ? [ - { percentile: '10th Percentile', regionalSalary: +s.regional?.regional_PCT10 || 0, nationalSalary: +s.national?.national_PCT10 || 0 }, - { percentile: '25th Percentile', regionalSalary: +s.regional?.regional_PCT25 || 0, nationalSalary: +s.national?.national_PCT25 || 0 }, - { percentile: 'Median', regionalSalary: +s.regional?.regional_MEDIAN || 0, nationalSalary: +s.national?.national_MEDIAN || 0 }, - { percentile: '75th Percentile', regionalSalary: +s.regional?.regional_PCT75 || 0, nationalSalary: +s.national?.national_PCT75 || 0 }, - { percentile: '90th Percentile', regionalSalary: +s.regional?.regional_PCT90 || 0, nationalSalary: +s.national?.national_PCT90 || 0 }, - ] : []; + const salaryData = s && Object.keys(s).length + ? [ + { percentile: '10th Percentile', regionalSalary: +s.regional?.regional_PCT10 || 0, nationalSalary: +s.national?.national_PCT10 || 0 }, + { percentile: '25th Percentile', regionalSalary: +s.regional?.regional_PCT25 || 0, nationalSalary: +s.national?.national_PCT25 || 0 }, + { percentile: 'Median', regionalSalary: +s.regional?.regional_MEDIAN || 0, nationalSalary: +s.national?.national_MEDIAN || 0 }, + { percentile: '75th Percentile', regionalSalary: +s.regional?.regional_PCT75 || 0, nationalSalary: +s.national?.national_PCT75 || 0 }, + { percentile: '90th Percentile', regionalSalary: +s.regional?.regional_PCT90 || 0, nationalSalary: +s.national?.national_PCT90 || 0 }, + ] + : []; /* ---------- 4. Economic projections ---------- */ const fullStateName = getFullStateName(userState); - const projRes = await axios.get( - `/api/projections/${socCode.split('.')[0]}`, - { params: { state: fullStateName } } - ).catch(() => ({ data: {} })); + const projRes = await axios + .get(`/api/projections/${socCode.split('.')[0]}`, { + params: { state: fullStateName }, + }) + .catch(() => ({ data: {} })); - /* ---------- 5. Decide if we actually have data ---------- */ - const haveSalary = salaryDataPoints.length > 0; + /* ---------- 5. Do we have *anything* useful? ---------- */ + const haveSalary = salaryData.length > 0; const haveProj = !!(projRes.data.state || projRes.data.national); const haveJobInfo = description || tasks.length > 0; @@ -399,43 +409,43 @@ const handleCareerClick = useCallback( setCareerDetails({ error: `We're sorry, but detailed info for "${career.title}" isn't available right now.`, }); - return; // stops here – nothing useful to show + return; } - /* ---------- 6. AI‑risk (only if job details exist) ---------- */ + /* ---------- 6. AI‑risk (only if job‑info exists) ---------- */ let aiRisk = null; if (haveJobInfo) { try { aiRisk = (await axios.get(`/api/ai-risk/${socCode}`)).data; } catch (err) { if (err.response?.status === 404) { - const aiRes = await axios.post('/api/public/ai-risk-analysis', { - socCode, - careerName : career.title, - jobDescription : description, - tasks, - }); - aiRisk = aiRes.data; - // store for next time (best‑effort) - axios.post('/api/ai-risk', aiRisk).catch(() => {}); + try { + const aiRes = await axios.post('/api/public/ai-risk-analysis', { + socCode, + careerName: career.title, + jobDescription: description, + tasks, + }); + aiRisk = aiRes.data; + // cache for next time (best‑effort) + axios.post('/api/ai-risk', aiRisk).catch(() => {}); + } catch { /* GPT fallback failed – ignore */ } } } } - /* ---------- 7. Build the final object & show modal ---------- */ - const updatedCareerDetails = { + /* ---------- 7. Build & show modal ---------- */ + setCareerDetails({ ...career, - cipCode, // may be null – EducationalPrograms handles it + cipCode, // may be null – downstream handles it jobDescription: description, tasks, - salaryData: salaryDataPoints, + salaryData, economicProjections: projRes.data ?? {}, - aiRisk, - }; - - setCareerDetails(updatedCareerDetails); - } catch (e) { - console.error('[handleCareerClick] fatal:', e); + aiRisk, // can be null + }); + } catch (fatal) { + console.error('[handleCareerClick] fatal:', fatal); setCareerDetails({ error: `We're sorry, but detailed info for "${career.title}" isn't available right now.`, }); @@ -446,7 +456,6 @@ const handleCareerClick = useCallback( [areaTitle, userState] ); - // ------------------------------------------------------ // handleCareerFromSearch // ------------------------------------------------------