dev1/src/components/PopoutPanel.js

184 lines
6.6 KiB
JavaScript

import { ClipLoader } from 'react-spinners';
import LoanRepayment from './LoanRepayment.js';
import './PopoutPanel.css';
import { useState, useEffect } from 'react';
function PopoutPanel({
data = {},
userState = 'N/A', // Passed explicitly from Dashboard
loading = false,
error = null,
closePanel,
}) {
console.log('PopoutPanel Props:', { data, loading, error, userState });
const [isCalculated, setIsCalculated] = useState(false);
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 (
<div className="popout-panel">
<button className="close-btn" onClick={closePanel}>X</button>
<h2>Loading Career Details...</h2>
<ClipLoader size={35} color="#4A90E2" />
</div>
);
}
// Safely access nested data with fallbacks
const {
jobDescription = null, // Default to null if not provided
tasks = null, // Default to null if not provided
title = 'Career Details',
economicProjections = {},
salaryData = [],
schools = [],
} = data;
// Get program length for calculating tuition
const getProgramLength = (degreeType) => {
if (degreeType?.includes("Associate")) return 2;
if (degreeType?.includes("Bachelor")) return 4;
if (degreeType?.includes("Master")) return 6;
if (degreeType?.includes("Doctoral") || degreeType?.includes("First Professional")) return 8;
if (degreeType?.includes("Certificate")) return 1;
return 4; // Default to 4 years if unspecified
};
return (
<div className="popout-panel">
<button onClick={closePanel}>Close</button>
<h2>{title}</h2>
{/* Job Description and Tasks */}
<div className="job-description">
<h3>Job Description</h3>
<p>{jobDescription || 'No description available'}</p>
</div>
<div className="job-tasks">
<h3>Expected Tasks</h3>
{tasks && tasks.length > 0 ? (
<ul>
{tasks.map((task, index) => (
<li key={index}>{task}</li>
))}
</ul>
) : (
<p>No tasks available for this career path.</p>
)}
</div>
{/* Schools Offering Programs Section */}
<h3>Schools Offering Programs</h3>
<div className="schools-offering">
{Array.isArray(schools) && schools.length > 0 ? (
schools.map((school, index) => (
<div key={index} className="school-card">
<div><strong>{school['INSTNM']}</strong></div>
<div>Degree Type: {school['CREDDESC'] || 'Degree type information is not available for this program'}</div>
<div>In-State Tuition: ${school['In_state cost'] || 'Tuition information is not available for this school'}</div>
<div>Out-of-State Tuition: ${school['Out_state cost'] || 'Tuition information is not available for this school'}</div>
<div>Distance: {school['distance'] || 'Distance to school not available'}</div>
<div>
Website: <a href={school['Website']} target="_blank" rel="noopener noreferrer">{school['Website']}</a>
</div>
</div>
))
) : (
<p className="no-schools-message">No schools of higher education are available in your state for this career path.</p>
)}
</div>
{/* Economic Projections */}
<div className="economic-projections">
<h3>Economic Projections for {userState}</h3>
{economicProjections && typeof economicProjections === 'object' ? (
<ul>
<li>2022 Employment: {economicProjections['2022 Employment'] || 'N/A'}</li>
<li>2032 Employment: {economicProjections['2032 Employment'] || 'N/A'}</li>
<li>Total Change: {economicProjections['Total Change'] || 'N/A'}</li>
</ul>
) : (
<p>No economic projections available for this career path.</p>
)}
</div>
{/* Salary Data Points */}
<div className="salary-data">
<h3>Salary Data</h3>
{salaryData.length > 0 ? (
<table>
<thead>
<tr>
<th>Percentile</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
{salaryData.map((point, index) => (
<tr key={index}>
<td>{point.percentile}</td>
<td>{point.value > 0 ? `$${parseInt(point.value, 10).toLocaleString()}` : 'N/A'}</td>
</tr>
))}
</tbody>
</table>
) : (
<p>Salary data is not available.</p>
)}
</div>
{/* Loan Repayment Analysis */}
<h3>Loan Repayment Analysis</h3>
{/* Loan Repayment Calculation Results */}
<LoanRepayment
schools={schools.map((school) => {
const years = getProgramLength(school['CREDDESC']);
return {
schoolName: school['INSTNM'],
inState: parseFloat(school['In_state cost'] * years) || 0,
outOfState: parseFloat(school['Out_state cost'] * years) || 0,
degreeType: school['CREDDESC'],
};
})}
salaryData={salaryData}
setResults={setResults}
setLoading={setLoadingCalculation}
/>
{/* Results Display */}
{results.length > 0 && (
<div className="results-container">
<h3>Comparisons by School over the life of the loan</h3>
{results.map((result, index) => (
<div className="school-result-card" key={index}>
<h4>{result.schoolName} - {result.degreeType || 'Degree type not available'}</h4>
<p>Total Tuition: ${result.tuition}</p>
<p>Monthly Payment: ${result.monthlyPayment}</p>
<p>Total Monthly Payment (with extra): ${result.totalMonthlyPayment}</p>
<p>Total Loan Cost: ${result.totalLoanCost}</p>
<p className={`net-gain ${parseFloat(result.netGain) < 0 ? 'negative' : 'positive'}`}>
Net Gain: {result.netGain}
</p>
<p>Monthly Salary (Gross): {result.monthlySalary}</p>
</div>
))}
</div>
)}
</div>
);
}
export default PopoutPanel;