Fixed Expected Salary input fields and Calculation
This commit is contained in:
parent
5f4992d4d3
commit
62175b5823
@ -1,9 +1,65 @@
|
|||||||
.loan-repayment-container {
|
.loan-repayment-container {
|
||||||
padding: 20px;
|
width: 100%;
|
||||||
background-color: #fafafa;
|
max-width: 500px; /* Adjust as needed */
|
||||||
border-radius: 8px;
|
margin: auto;
|
||||||
}
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loan-repayment-container form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loan-repayment-container .input-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center; /* Ensures labels and inputs are aligned */
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loan-repayment-container label {
|
||||||
|
font-weight: bold;
|
||||||
|
width: 40%; /* Consistent width for labels */
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loan-repayment-container input,
|
||||||
|
.loan-repayment-container select {
|
||||||
|
width: 58%; /* Consistent width for inputs */
|
||||||
|
padding: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loan-repayment-container .calculate-button-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loan-repayment-container button {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 300px;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: green;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loan-repayment-container button:hover {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
.loan-repayment-fields label {
|
.loan-repayment-fields label {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
@ -131,4 +187,8 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: red;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
@ -46,32 +46,42 @@ function LoanRepayment({
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
const schoolResults = schools.map((school) => {
|
const schoolResults = schools.map((school) => {
|
||||||
const tuition = tuitionType === 'inState' ? school.inState : school.outOfState;
|
const tuition = tuitionType === 'inState' ? school.inState : school.outOfState;
|
||||||
const monthlyRate = interestRate / 12 / 100;
|
const monthlyRate = Number(interestRate) / 12 / 100;
|
||||||
const loanTermMonths = loanTerm * 12;
|
const loanTermMonths = Number(loanTerm) * 12;
|
||||||
|
|
||||||
const minimumMonthlyPayment = tuition * (monthlyRate * Math.pow(1 + monthlyRate, loanTermMonths)) /
|
const minimumMonthlyPayment = tuition * (monthlyRate * Math.pow(1 + monthlyRate, loanTermMonths)) /
|
||||||
(Math.pow(1 + monthlyRate, loanTermMonths) - 1);
|
(Math.pow(1 + monthlyRate, loanTermMonths) - 1);
|
||||||
|
|
||||||
const extraMonthlyPayment = minimumMonthlyPayment + extraPayment;
|
const extraMonthlyPayment = Number(minimumMonthlyPayment) + Number(extraPayment);
|
||||||
let remainingBalance = tuition;
|
let remainingBalance = tuition;
|
||||||
let monthsWithExtra = 0;
|
let monthsWithExtra = 0;
|
||||||
|
|
||||||
while (remainingBalance > 0) {
|
while (remainingBalance > 0) {
|
||||||
monthsWithExtra++;
|
monthsWithExtra++;
|
||||||
const interest = remainingBalance * monthlyRate;
|
|
||||||
const principal = extraMonthlyPayment - interest;
|
// Calculate interest for this month
|
||||||
remainingBalance -= principal;
|
const interest = remainingBalance * monthlyRate;
|
||||||
}
|
|
||||||
|
// Ensure principal payment never goes negative
|
||||||
|
const principal = Math.max(extraMonthlyPayment - interest, 0);
|
||||||
|
|
||||||
|
// Reduce balance
|
||||||
|
remainingBalance -= principal;
|
||||||
|
|
||||||
|
// Prevent infinite loop in case of incorrect values
|
||||||
|
if (monthsWithExtra > loanTermMonths * 2) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const totalLoanCost = extraMonthlyPayment * monthsWithExtra;
|
const totalLoanCost = extraMonthlyPayment * monthsWithExtra;
|
||||||
|
|
||||||
let salary = salaryData.find((point) => point.percentile === selectedSalary)?.value || 0;
|
let salary = Number(salaryData.find((point) => point.percentile === selectedSalary)?.value || 0);
|
||||||
let netGain = 'N/A';
|
let netGain = 'N/A';
|
||||||
let monthlySalary = 'N/A';
|
let monthlySalary = 'N/A';
|
||||||
|
|
||||||
if (salary > 0) {
|
if (salary > 0) {
|
||||||
const totalSalary = salary * loanTerm;
|
const totalSalary = salary * loanTerm;
|
||||||
const currentSalaryEarnings = currentSalary * loanTerm * Math.pow(1.03, loanTerm);
|
const currentSalaryEarnings = Number(currentSalary) * loanTerm * Math.pow(1.03, loanTerm);
|
||||||
netGain = (totalSalary - totalLoanCost - currentSalaryEarnings).toFixed(2);
|
netGain = (totalSalary - totalLoanCost - currentSalaryEarnings).toFixed(2);
|
||||||
monthlySalary = (salary / 12).toFixed(2);
|
monthlySalary = (salary / 12).toFixed(2);
|
||||||
}
|
}
|
||||||
@ -94,41 +104,43 @@ function LoanRepayment({
|
|||||||
return (
|
return (
|
||||||
<div className="loan-repayment-container">
|
<div className="loan-repayment-container">
|
||||||
<form onSubmit={(e) => { e.preventDefault(); calculateLoanDetails(); }}>
|
<form onSubmit={(e) => { e.preventDefault(); calculateLoanDetails(); }}>
|
||||||
<div>
|
<div className="input-group">
|
||||||
<label>Tuition Type:</label>
|
<label>Tuition Type:</label>
|
||||||
<select value={tuitionType} onChange={(e) => setTuitionType(e.target.value)}>
|
<select value={tuitionType} onChange={(e) => setTuitionType(e.target.value)}>
|
||||||
<option value="inState">In-State</option>
|
<option value="inState">In-State</option>
|
||||||
<option value="outOfState">Out-of-State</option>
|
<option value="outOfState">Out-of-State</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Interest Rate:</label>
|
|
||||||
<input type="number" value={interestRate} onChange={(e) => setInterestRate(e.target.value)} />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Loan Term (years):</label>
|
|
||||||
<input type="number" value={loanTerm} onChange={(e) => setLoanTerm(e.target.value)} />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Extra Monthly Payment:</label>
|
|
||||||
<input type="number" value={extraPayment} onChange={(e) => setExtraPayment(e.target.value)} />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Current Salary:</label>
|
|
||||||
<input type="number" value={currentSalary} onChange={(e) => setCurrentSalary(e.target.value)} />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Expected Salary:</label>
|
|
||||||
<select value={selectedSalary} onChange={(e) => setSelectedSalary(e.target.value)}>
|
|
||||||
{salaryData.map((point, index) => (
|
|
||||||
<option key={index} value={point.percentile}>{point.percentile}</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<button type="submit">Calculate</button>
|
|
||||||
</form>
|
|
||||||
{error && <div className="error">{error}</div>}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="input-group">
|
||||||
|
<label>Interest Rate:</label>
|
||||||
|
<input type="number" value={interestRate} onChange={(e) => setInterestRate(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="input-group">
|
||||||
|
<label>Loan Term (years):</label>
|
||||||
|
<input type="number" value={loanTerm} onChange={(e) => setLoanTerm(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="input-group">
|
||||||
|
<label>Extra Monthly Payment:</label>
|
||||||
|
<input type="number" value={extraPayment} onChange={(e) => setExtraPayment(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="input-group">
|
||||||
|
<label>Current Salary:</label>
|
||||||
|
<input type="number" value={currentSalary} onChange={(e) => setCurrentSalary(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="input-group">
|
||||||
|
<label>Expected Salary:</label>
|
||||||
|
<select value={selectedSalary} onChange={(e) => setSelectedSalary(e.target.value)}>
|
||||||
|
{salaryData.map((point, index) => (
|
||||||
|
<option key={index} value={point.percentile}>{point.percentile}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="calculate-button-container">
|
||||||
|
<button type="submit">Calculate</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{error && <div className="error">{error}</div>}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user