updated settings/loan calculator/add transaction

Strengthened form validation in the settings page, fixing an input bug with whitespaces. Added form validation to the loan calculator and add transaction widgets
main
danielq65 3 years ago
parent 461b05f1b6
commit 0125f6f9f7

@ -123,9 +123,27 @@ const AddExpenseForm = (props) => {
setCost(event.target.value) setCost(event.target.value)
} }
(() => {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
const forms = document.querySelectorAll('.needs-validation')
// Loop over them and prevent submission
Array.from(forms).forEach(form => {
form.addEventListener('submit', event => {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated')
}, false)
})
})()
return ( return (
<div className='widget'> <div className='widget'>
<h4>Add Transaction</h4> <h4>Add Transaction</h4>
<form className="needs-validation" onSubmit={onSubmit} noValidate>
<div style={{height: "85%"}} className='d-flex flex-column justify-content-between'> <div style={{height: "85%"}} className='d-flex flex-column justify-content-between'>
<div className='row'> <div className='row'>
<div className='col'> <div className='col'>
@ -140,6 +158,9 @@ const AddExpenseForm = (props) => {
value={cost} value={cost}
onChange={(event) => setCost(event.target.value)} onChange={(event) => setCost(event.target.value)}
/> />
<div className="invalid-feedback">
Please enter a valid amount
</div>
</div> </div>
<div className='col'> <div className='col'>
<label htmlFor='category-select'>Category</label> <label htmlFor='category-select'>Category</label>
@ -184,7 +205,7 @@ const AddExpenseForm = (props) => {
<button className='btn btn-dark m-right mt-2' onClick={toggleTransactionType}> <button className='btn btn-dark m-right mt-2' onClick={toggleTransactionType}>
{transactionType.toUpperCase()} {transactionType.toUpperCase()}
</button> </button>
<button type='submit' onClick={onSubmit} id="add-transaction-button" className='btn btn-primary m-right mt-2'> <button type='submit' id="add-transaction-button" className='btn btn-primary m-right mt-2'>
Add Transaction Add Transaction
</button> </button>
<button className='btn btn-primary mt-2' onClick={handleAddCategory}> <button className='btn btn-primary mt-2' onClick={handleAddCategory}>
@ -193,6 +214,7 @@ const AddExpenseForm = (props) => {
</div> </div>
</div> </div>
</div> </div>
</form>
</div> </div>
); );
}; };

@ -8,7 +8,9 @@ const LoanCalculator = () => {
const [monthlyPayment, setMonthlyPayment] = useState(0); const [monthlyPayment, setMonthlyPayment] = useState(0);
const [interestPaid, setInterestPaid] = useState(0); const [interestPaid, setInterestPaid] = useState(0);
const calculateMonthlyPayment = () => { const calculateMonthlyPayment = (event) => {
event.preventDefault();
const percentageToDecimal = (percent) => { const percentageToDecimal = (percent) => {
return percent / 12 / 100; return percent / 12 / 100;
} }
@ -24,21 +26,69 @@ const LoanCalculator = () => {
setInterestPaid(monthlyPayment * (loanDuration * 12) - loanAmount); setInterestPaid(monthlyPayment * (loanDuration * 12) - loanAmount);
}, [monthlyPayment]); }, [monthlyPayment]);
(() => {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
const forms = document.querySelectorAll('.needs-validation')
// Loop over them and prevent submission
Array.from(forms).forEach(form => {
form.addEventListener('submit', event => {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated')
}, false)
})
})()
return ( return (
<div className="widget"> <div className="widget">
<h4 className="mb-0">Loan Calculator</h4> <h4>Loan Calculator</h4>
<form onSubmit={(event) => event.preventDefault()}> <form className="needs-validation" onSubmit={calculateMonthlyPayment} noValidate>
<FormInputGroup text="Loan Amount $" placeholder="" value={loanAmount} onInput={(event) => setLoanAmount(event.target.value)}/> <div className="row">
<FormInputGroup text="Interest Rate %" placeholder="" value={interestRate} onInput={(event) => setInterestRate(event.target.value)}/> <div className="col-6">
<FormInputGroup text="Loan Duration in Years" placeholder="" value={loanDuration} onInput={(event) => setLoanDuration(event.target.value)}/> <div className="input-group">
<label className="input-group-text">Loan Amount $</label>
<input type="number" className="form-control" placeholder="" min={1000} step=".01" value={loanAmount} onChange={(event) => setLoanAmount(event.target.value)} required/>
<div className="invalid-feedback">
Please enter a valid loan amount
<br/>
Loan amount must be of at least $1,000
</div>
</div>
<div className="input-group mt-3">
<label className="input-group-text">Interest Rate %</label>
<input type="number" className="form-control" placeholder="" min={5} step=".001" value={interestRate} onChange={(event) => setInterestRate(event.target.value)} required/>
<div className="invalid-feedback">
Please enter a valid interest rate
<br/>
Interest rate must be of at least 5.0%
</div>
</div>
<div className="input-group mt-3">
<label className="input-group-text">Loan Duration in Years</label>
<input type="number" className="form-control" placeholder="" min={2} value={loanDuration} onChange={(event) => setLoanDuration(event.target.value)} required/>
<div className="invalid-feedback">
Please enter a valid loan duration in years
<br/>
Loan duration cannot be less than 2 years
</div>
</div>
</div>
<h4 className="mt-4 alert alert-info fw-bold"> <div className="col-6">
<h4 className="alert alert-info h-100 fw-bold">
Monthly Payment: ${monthlyPayment.toFixed(2)} Monthly Payment: ${monthlyPayment.toFixed(2)}
<h5 className="mt-4">Principal Paid: ${loanAmount}</h5> <h5 className="mt-4">Principal Paid: ${loanAmount}</h5>
<h5>Interest Paid: ${interestPaid.toFixed(2)}</h5> <h5>Interest Paid: ${interestPaid.toFixed(2)}</h5>
</h4> </h4>
<button type="submit" className="btn btn-primary btn-lg w-100 mt-3 center" onClick={calculateMonthlyPayment}>Calculate</button> </div>
</div>
<button type="submit" className="btn btn-primary btn-lg w-100 mt-3 center">Calculate</button>
</form> </form>
</div> </div>
) )

@ -129,16 +129,6 @@ const Settings = () => {
}) })
})() })()
// toggle between light mode and dark mode
/*const toggleDarkMode = () => {
if (document.documentElement.getAttribute('data-bs-theme') === 'dark') {
document.documentElement.setAttribute('data-bs-theme','light')
}
else {
document.documentElement.setAttribute('data-bs-theme','dark')
}
}*/
return ( return (
<> <>
<div className="container overflow-auto"> <div className="container overflow-auto">
@ -161,18 +151,18 @@ const Settings = () => {
<div className="row mb-3"> <div className="row mb-3">
<label htmlFor="newFirstName" className="col-2 col-form-label">New First Name</label> <label htmlFor="newFirstName" className="col-2 col-form-label">New First Name</label>
<div className="col-4"> <div className="col-4">
<input type="text" className="form-control" id="newFirstName" placeholder="Please enter a new first name" value={firstName} onChange={(event) => setFirstName(event.target.value)} required/> <input type="text" className="form-control" id="newFirstName" placeholder="Please enter a new first name" pattern="\S(.*\S)?" value={firstName} onChange={(event) => setFirstName(event.target.value)} required/>
<div className="invalid-feedback"> <div className="invalid-feedback">
Please enter a new first name Please enter a valid new first name
</div> </div>
</div> </div>
</div> </div>
<div className="row mb-3"> <div className="row mb-3">
<label htmlFor="newLastName" className="col-2 col-form-label">New Last Name</label> <label htmlFor="newLastName" className="col-2 col-form-label">New Last Name</label>
<div className="col-4"> <div className="col-4">
<input type="text" className="form-control" id="newLastName" placeholder="Please enter a new last name" value={lastName} onChange={(event) => setLastName(event.target.value)} required /> <input type="text" className="form-control" id="newLastName" placeholder="Please enter a new last name" pattern="\S(.*\S)?" value={lastName} onChange={(event) => setLastName(event.target.value)} required/>
<div className="invalid-feedback"> <div className="invalid-feedback">
Please enter a new last name Please enter a valid new last name
</div> </div>
</div> </div>
</div> </div>
@ -187,7 +177,7 @@ const Settings = () => {
<div className="row mb-3"> <div className="row mb-3">
<label htmlFor="currentPassword" className="col-2 col-form-label">Current Password</label> <label htmlFor="currentPassword" className="col-2 col-form-label">Current Password</label>
<div className="col-4"> <div className="col-4">
<input type="password" className="form-control" id="currentPassword" placeholder="Please enter your current password" minLength="8" value={currentPassword} onChange={(event) => setCurrentPassword(event.target.value)} required /> <input type="password" className="form-control" id="currentPassword" placeholder="Please enter your current password" pattern="\S(.*\S)?" minLength="8" value={currentPassword} onChange={(event) => setCurrentPassword(event.target.value)} required/>
<div className="invalid-feedback"> <div className="invalid-feedback">
Please enter your current password Please enter your current password
</div> </div>
@ -196,11 +186,13 @@ const Settings = () => {
<div className="row mb-3"> <div className="row mb-3">
<label htmlFor="newPassword" className="col-2 col-form-label">New Password</label> <label htmlFor="newPassword" className="col-2 col-form-label">New Password</label>
<div className="col-4"> <div className="col-4">
<input type="password" className="form-control" id="newPassword" placeholder="Please enter a new password" minLength="8" value={newPassword} onChange={(event) => setNewPassword(event.target.value)} required /> <input type="password" className="form-control" id="newPassword" placeholder="Please enter a new password" pattern="\S(.*\S)?" minLength="8" value={newPassword} onChange={(event) => setNewPassword(event.target.value)} required/>
<div className="invalid-feedback"> <div className="invalid-feedback">
Please enter a new password Please enter a valid new password
<br/> <br/>
Your new password must be at least 8 characters long Your new password must be at least 8 characters long
<br/>
It cannot have whitespace at the start or end of it
</div> </div>
</div> </div>
</div> </div>
@ -210,13 +202,6 @@ const Settings = () => {
</div> </div>
</form> </form>
{/*<h4 className="mb-4">Dark Mode</h4>
<div className="form-check form-switch mb-5">
<input className="form-check-input" type="checkbox" id="darkModeCheckbox" onClick={toggleDarkMode}/>
<label className="form-check-label" htmlFor="darkModeCheckbox">Enable Dark Mode</label>
</div>*/}
<h4 className="mb-4">Account Settings</h4> <h4 className="mb-4">Account Settings</h4>
<h5 className="mb-4">Delete Your Account</h5> <h5 className="mb-4">Delete Your Account</h5>
@ -224,7 +209,7 @@ const Settings = () => {
<div className="row mb-3"> <div className="row mb-3">
<label htmlFor="deleteAccount" className="col-2 col-form-label">Current Password</label> <label htmlFor="deleteAccount" className="col-2 col-form-label">Current Password</label>
<div className="col-4"> <div className="col-4">
<input type="password" className="form-control" id="deleteAccount" placeholder="Please enter your current password" minLength="8" value={deleteAccount} onChange={(event) => setDeleteAccount(event.target.value)} required /> <input type="password" className="form-control" id="deleteAccount" placeholder="Please enter your current password" pattern="\S(.*\S)?" minLength="8" value={deleteAccount} onChange={(event) => setDeleteAccount(event.target.value)} required/>
<div className="invalid-feedback"> <div className="invalid-feedback">
Please enter your current password in order to delete your account Please enter your current password in order to delete your account
</div> </div>

Loading…
Cancel
Save