Added AI Risk to MilestoneTracker.js

This commit is contained in:
Josh 2025-05-29 13:49:01 +00:00
parent 7a31b722c5
commit 1e84c8b38a
2 changed files with 104 additions and 10 deletions

View File

@ -276,6 +276,9 @@ export default function MilestoneTracker({ selectedCareer: initialCareer }) {
const [selectedCareer, setSelectedCareer] = useState(initialCareer || null); const [selectedCareer, setSelectedCareer] = useState(initialCareer || null);
const [careerProfileId, setCareerProfileId] = useState(null); const [careerProfileId, setCareerProfileId] = useState(null);
const [scenarioRow, setScenarioRow] = useState(null); const [scenarioRow, setScenarioRow] = useState(null);
const [aiRisk, setAiRisk] = useState(null);
const [aiRiskLoading, setAiRiskLoading] = useState(false);
const [aiRiskError, setAiRiskError] = useState(null);
const [collegeProfile, setCollegeProfile] = useState(null); const [collegeProfile, setCollegeProfile] = useState(null);
const [strippedSocCode, setStrippedSocCode] = useState(null); const [strippedSocCode, setStrippedSocCode] = useState(null);
@ -455,6 +458,81 @@ export default function MilestoneTracker({ selectedCareer: initialCareer }) {
setStrippedSocCode(stripSocCode(found.soc_code)); setStrippedSocCode(stripSocCode(found.soc_code));
}, [scenarioRow, masterCareerRatings]); }, [scenarioRow, masterCareerRatings]);
useEffect(() => {
// If we have no SOC code or scenarioRow is missing, reset
if (!strippedSocCode || !scenarioRow?.career_name) {
setAiRisk(null);
return;
}
async function fetchAiRisk() {
setAiRiskLoading(true);
setAiRiskError(null);
try {
// 1) Attempt local DB first
const localRes = await fetch(`${apiURL}/ai-risk/${strippedSocCode}`);
if (localRes.ok) {
const localData = await localRes.json();
setAiRisk(localData);
} else if (localRes.status === 404) {
// 2) If not found => call GPT route
// We'll pass minimal data if we don't have job description or tasks
const chatPayload = {
socCode: strippedSocCode,
careerName: scenarioRow.career_name,
jobDescription: '', // or optionally fetch from O*NET / tasks
tasks: []
};
// POST to your server3 public route
const gptRes = await fetch(`${apiURL}/public/ai-risk-analysis`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(chatPayload),
});
if (!gptRes.ok) {
throw new Error('GPT call failed');
}
const gptData = await gptRes.json();
// 3) Store in server2 so we skip GPT next time
await fetch(`${apiURL}/ai-risk`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
socCode: strippedSocCode,
careerName: gptData.careerName,
jobDescription: gptData.jobDescription,
tasks: gptData.tasks,
riskLevel: gptData.riskLevel,
reasoning: gptData.reasoning,
})
});
// 4) Set it in state
setAiRisk({
socCode: strippedSocCode,
careerName: scenarioRow.career_name,
riskLevel: gptData.riskLevel,
reasoning: gptData.reasoning
});
} else {
// Some other error code
throw new Error(`AI Risk fetch error: ${localRes.status}`);
}
} catch (err) {
console.error('Error fetching AI risk =>', err);
setAiRiskError('Failed to load AI risk data.');
setAiRisk(null);
} finally {
setAiRiskLoading(false);
}
}
fetchAiRisk();
}, [strippedSocCode, scenarioRow?.career_name, apiURL]);
// 6) Salary // 6) Salary
useEffect(() => { useEffect(() => {
if (!strippedSocCode) { if (!strippedSocCode) {
@ -898,6 +976,22 @@ if (aiLoading || clickCount >= DAILY_CLICK_LIMIT) {
{yearsInCareer === '<1' ? 'year' : 'years'} {yearsInCareer === '<1' ? 'year' : 'years'}
</p> </p>
)} )}
<div className="mt-2">
{aiRiskLoading ? (
<p className="text-sm text-gray-500">Loading AI risk...</p>
) : aiRiskError ? (
<p className="text-sm text-red-500">{aiRiskError}</p>
) : aiRisk ? (
<div className="text-sm text-gray-700">
<strong>AI Risk Level:</strong> {aiRisk.riskLevel}
<br />
<em>{aiRisk.reasoning}</em>
</div>
) : (
<p className="text-sm text-gray-500">No AI risk data available</p>
)}
</div>
</div> </div>
{/* 2) Salary Benchmarks */} {/* 2) Salary Benchmarks */}

Binary file not shown.