Passed data from popoutpanel & Dashboard to chatbot - will be obsolete when moving data to BQ

This commit is contained in:
Josh 2025-03-18 15:20:08 +00:00
parent eb01d5578c
commit b0d82af280
3 changed files with 117 additions and 34 deletions

View File

@ -25,11 +25,39 @@ const Chatbot = ({ context }) => {
Use the following user-specific data:
- Career Suggestions: ${context.careerSuggestions?.map((c) => c.title).join(", ") || "No suggestions available."}
- Selected Career: ${context.selectedCareer?.title || "None"}
- Schools: ${context.schools?.map((s) => s["INSTNM"]).join(", ") || "No schools available."}
- Median Salary: ${
context.salaryData?.find((s) => s.percentile === "Median")?.value || "Unavailable"
- Job Description: ${context.careerDetails?.jobDescription || "No job description available."}
- Expected Tasks: ${context.careerDetails?.tasks?.join(", ") || "No tasks available."}
- Salary Data:
${context.salaryData?.length > 0
? context.salaryData.map(sd => `${sd.percentile}: $${sd.regionalSalary || "N/A"} (Regional), $${sd.nationalSalary || "N/A"} (National)`).join(", ")
: "Not available"}
- Schools Available: ${
context.schools?.length > 0
? context.schools
.map(school => `${school.INSTNM} (Distance: ${school.distance || "N/A"}, Tuition: $${school["In_state cost"] || "N/A"})`)
.join("; ")
: "No schools available."
}
- Economic Projections: ${
context.economicProjections && Object.keys(context.economicProjections).length > 0
? `2022 Employment: ${context.economicProjections["2022 Employment"] || "N/A"}, ` +
`2032 Employment: ${context.economicProjections["2032 Employment"] || "N/A"}, ` +
`Total Change: ${context.economicProjections["Total Change"] || "N/A"}`
: "Not available"
}
- ROI (Return on Investment): If available, use education costs vs. salary potential to guide users.
- ROI Analysis: ${
context.persistedROI && Array.isArray(context.persistedROI) && context.persistedROI.length > 0
? context.persistedROI
.map(roi => `${roi.schoolName}: Net Gain: $${roi.netGain || "N/A"}, Monthly Payment: $${roi.monthlyPayment || "N/A"}`)
.join("; ")
: "No ROI data available."
}
- User State: ${context.userState || "Not provided"}
- User Area: ${context.areaTitle || "Not provided"}
- User Zipcode: ${context.userZipcode || "Not provided"}
**Your response should ALWAYS provide analysis, not just list careers.**
Example responses:

View File

@ -36,6 +36,8 @@ function Dashboard() {
const [careersWithJobZone, setCareersWithJobZone] = useState([]); // Store careers with job zone info
const [selectedFit, setSelectedFit] = useState('');
const [results, setResults] = useState([]); // Add results state
const [chatbotContext, setChatbotContext] = useState({});
const jobZoneLabels = {
'1': 'Little or No Preparation',
@ -93,9 +95,29 @@ function Dashboard() {
});
}, [careersWithJobZone, selectedJobZone, selectedFit]);
const updateChatbotContext = (updatedData) => {
setChatbotContext((prevContext) => {
const mergedContext = {
...prevContext, // ✅ Preserve existing context (Dashboard Data)
...Object.keys(updatedData).reduce((acc, key) => {
if (updatedData[key] !== undefined && updatedData[key] !== null) {
acc[key] = updatedData[key]; // ✅ Only update fields with actual data
}
return acc;
}, {}),
};
console.log("🔄 Updated Chatbot Context (Merged Dashboard + PopoutPanel):", mergedContext);
return mergedContext;
});
};
const memoizedCareerSuggestions = useMemo(() => filteredCareers, [filteredCareers]);
const memoizedPopoutPanel = useMemo(() => {
console.log("Passing careerDetails to PopoutPanel:", careerDetails);
return (
<PopoutPanel
isVisible={!!selectedCareer} // ✅ Ensures it's only visible when needed
@ -109,6 +131,7 @@ const memoizedCareerSuggestions = useMemo(() => filteredCareers, [filteredCareer
error={error}
userState={userState}
results={results}
updateChatbotContext={updateChatbotContext}
/>
);
}, [selectedCareer, careerDetails, schools, salaryData, economicProjections, tuitionData, loading, error, userState]);
@ -153,6 +176,33 @@ const memoizedCareerSuggestions = useMemo(() => filteredCareers, [filteredCareer
fetchUserProfile();
}, [apiUrl]);
useEffect(() => {
if (
careerSuggestions.length > 0 &&
riaSecScores.length > 0 &&
userState !== null &&
areaTitle !== null &&
userZipcode !== null
) {
console.log("✅ All data ready, forcing chatbotContext update...");
// ✅ Create a completely new object so React detects the change
const newChatbotContext = {
careerSuggestions: [...careersWithJobZone], // Ensure fresh array reference
riaSecScores: [...riaSecScores], // Ensure fresh array reference
userState: userState || "",
areaTitle: areaTitle || "",
userZipcode: userZipcode || "",
};
setChatbotContext(newChatbotContext);
} else {
console.log("⏳ Skipping chatbotContext update because data is not ready yet.");
}
}, [careerSuggestions, riaSecScores, userState, areaTitle, userZipcode, careersWithJobZone]);
const handleCareerClick = useCallback(
async (career) => {
const socCode = career.code; // Extract SOC code from career object
@ -239,15 +289,19 @@ async (career) => {
]
: [];
setCareerDetails({
...career,
jobDescription: description,
tasks: tasks,
economicProjections: economicResponse.data || {},
salaryData: salaryDataPoints,
schools: schoolsWithDistance,
tuitionData: tuitionResponse.data || [],
});
const updatedCareerDetails = {
...career,
jobDescription: description,
tasks: tasks,
economicProjections: economicResponse.data || {},
salaryData: salaryDataPoints,
schools: schoolsWithDistance,
tuitionData: tuitionResponse.data || [],
};
// Ensure `careerDetails` is fully updated before passing to chatbot
setCareerDetails(updatedCareerDetails);
updateChatbotContext({ careerDetails: updatedCareerDetails });
} catch (error) {
console.error('Error processing career click:', error.message);
@ -276,14 +330,9 @@ async (career) => {
careerSuggestions,
riaSecScores,
selectedCareer,
schools,
salaryData,
economicProjections,
tuitionData,
userState,
areaTitle,
userZipcode,
results,
});
return (
@ -362,21 +411,7 @@ async (career) => {
{/* Pass context to Chatbot */}
<div className="chatbot-widget">
{careerSuggestions.length > 0 ? (
<Chatbot
context={{
careerSuggestions: careersWithJobZone || [],
riaSecScores: riaSecScores || [],
selectedCareer: selectedCareer || null,
schools: schools || [],
salaryData: salaryData || [],
economicProjections: economicProjections || null,
tuitionData: tuitionData || [],
userState: userState || "",
areaTitle: areaTitle || "",
userZipcode: userZipcode || "",
results: results || [],
}}
/>
<Chatbot context={chatbotContext} />
) : (
<p>Loading Chatbot...</p>
)}

View File

@ -11,6 +11,7 @@ function PopoutPanel({
loading = false,
error = null,
closePanel,
updateChatbotContext,
}) {
const [isCalculated, setIsCalculated] = useState(false);
const [results, setResults] = useState([]); // Store loan repayment calculation results
@ -39,6 +40,24 @@ function PopoutPanel({
setProgramLengths(schools.map(school => getProgramLength(school['CREDDESC'])));
}, [schools]);
useEffect(() => {
console.log("📩 Updating Chatbot Context from PopoutPanel:", data);
if (data && Object.keys(data).length > 0) {
updateChatbotContext({
careerDetails: data,
schools,
salaryData,
economicProjections,
results,
persistedROI, // ✅ Make sure ROI is included!
});
} else {
console.log("⚠️ No valid PopoutPanel data to update chatbot context.");
}
}, [data, schools, salaryData, economicProjections, results, persistedROI, updateChatbotContext]);
if (!isVisible) return null;
if (loading || loadingCalculation) {
@ -51,6 +70,7 @@ function PopoutPanel({
);
}
// Get program length for calculating tuition
const getProgramLength = (degreeType) => {
if (degreeType?.includes("Associate")) return 2;
@ -94,7 +114,7 @@ function PopoutPanel({
</div>
<h2>{title}</h2>
{/* Job Description and Tasks */}
<div className="job-description">
<h3>Job Description</h3>