This commit is contained in:
jveebs 2023-04-25 16:42:33 -04:00
commit 348b3835e1
30 changed files with 490 additions and 105 deletions

View file

@ -1,14 +1,14 @@
import React, { useContext, useState, useEffect } from 'react';
import ExpenseItem from './ExpenseItem';
import { AppContext } from '../context/AppContext';
import './css/ExpenseList.css'
const ExpenseList = () => {
const [whole, setWhole] = useState('');
const [decimal, setDecimal] = useState('');
const [transaction, setTransactions] = useState('');
const [category, setCategories] = useState('');
const [time, setTime] = useState('');
function getSessionKey() {
var cookies = document.cookie.split(';');
@ -68,13 +68,41 @@ const ExpenseList = () => {
}
}
async function buildTable(data1, data2){
async function getDate() {
try {
const response = await fetch('https://api.bb.gabefarrell.com/w/transactions/recent', {
method: 'GET',
headers: {
'x-session-key': getSessionKey(),
},
});
const data = await response.json();
const timestamp = data.transactions.map((item)=>item.timestamp);
let dateFormat = [];
let date, month, day;
for (let i = 0; i < timestamp.length; i++) {
date = new Date(timestamp[i]);
month = date.getMonth();
day = date.getDay();
console.log(month, day);
dateFormat.push(month + '/' + day);
}
//let dateFormat = new Date(timestamp[0]);
// console.log(date);
return dateFormat;
} catch (error) {
console.error(error);
}
}
async function buildTable(data1, data2, data3){
var table = document.getElementById('myTable')
for (var i = 0; i < data1.length; i++){
var row = `<tr>
<td>${data1[i]}</td>
<td>${data2[i]}</td>
<td>$${data2[i]}</td>
</tr>`
table.innerHTML += row
@ -82,17 +110,18 @@ const ExpenseList = () => {
}
}
buildTable(category, transaction);
buildTable(category, transaction, time);
async function fetchTransactions() {
const categories = await getTransactionsCategory();
const transaction_balance = await getTransactionsBalance();
const date = await getDate();
setCategories(categories);
setTransactions(transaction_balance);
setTime(date);
}
useEffect(() => {

View file

@ -23,10 +23,10 @@ const ExpenseTotal = () => {
}, [])
return (
<div className='widget p-4'>
{//<img src={logo} className='expenseTotalIcon'></img>
}
<span className='widgetText'>This Month's Expenses: ${expense}</span>
<div>
<h5 class="textttt">This Month's Expenses:</h5>
<img src={logo} class="imageee"></img>
<h1 class="displayyyy">${expense}</h1>
</div>
);
};

View file

@ -29,25 +29,19 @@ const LoanCalculator = () => {
<h4 className="mb-0">Loan Calculator</h4>
<form onSubmit={(event) => event.preventDefault()}>
<div className="row align-items-center">
<div className="col mb-3">
<FormInputGroup text="Loan Amount $" placeholder="Enter the value of the loan" value={loanAmount} onInput={(event) => setLoanAmount(event.target.value)}/>
<FormInputGroup text="Interest Rate %" placeholder="Enter interest rate of the loan" value={interestRate} onInput={(event) => setInterestRate(event.target.value)}/>
<FormInputGroup text="Loan Duration in Years" placeholder="Enter the duration of the loan in years" value={loanDuration} onInput={(event) => setLoanDuration(event.target.value)}/>
</div>
<div className="col">
<h5 className="alert alert-info fw-bold mt-3">
Monthly Payment: ${monthlyPayment.toFixed(2)}
<h6 className="mt-4">Principal Paid: ${loanAmount}</h6>
<h6>Interest Paid: ${interestPaid.toFixed(2)}</h6>
</h5>
</div>
</div>
<FormInputGroup text="Loan Amount $" placeholder="" value={loanAmount} onInput={(event) => setLoanAmount(event.target.value)}/>
<FormInputGroup text="Interest Rate %" placeholder="" value={interestRate} onInput={(event) => setInterestRate(event.target.value)}/>
<FormInputGroup text="Loan Duration in Years" placeholder="" value={loanDuration} onInput={(event) => setLoanDuration(event.target.value)}/>
<button type="submit" className="btn btn-primary btn-lg w-100 center" onClick={calculateMonthlyPayment}>Calculate</button>
<h4 className="alert alert-info fw-bold">
Monthly Payment: ${monthlyPayment.toFixed(2)}
<h5 className="mt-4">Principal Paid: ${loanAmount}</h5>
<h5>Interest Paid: ${interestPaid.toFixed(2)}</h5>
</h4>
<button type="submit" className="btn btn-primary btn-lg w-100 mt-3 center" onClick={calculateMonthlyPayment}>Calculate</button>
</form>
</div>
)
};
export default LoanCalculator;
export default LoanCalculator;

View file

@ -1,6 +1,6 @@
import React, {useState, useEffect} from 'react';
import './css/ViewBudget.css'
import logo from './widget_logos/current_balance_logo.png';
import './css/Remaining.css'
import logo from './widget_logos/budget_logo.png';
export default function Remaining() {
const [budget, setBudget] = useState('');
@ -107,7 +107,10 @@ export default function Remaining() {
{/* <img src={logo}></img>
<span>Current Balance: ${data}</span> */}
{/* <button onClick={apiGet()}> TEST</button> */}
<h1>{budget}</h1>
<h5 class="text">Budget Remaining</h5>
<img src={logo} class="image"></img><h1 class="display">${budget}</h1>
<form id="form" onSubmit={handleSubmit}>
<input
type = "text"

View file

@ -110,7 +110,9 @@ export default function FetchAPI() {
{/* <img src={logo}></img>
<span>Current Balance: ${data}</span> */}
{/* <button onClick={apiGet()}> TEST</button> */}
<h1>{balance}</h1>
<h5 class="text">Current Balance</h5>
<img src={logo} class="imagee"></img>
<h1 class="displayy">${balance}</h1>
<form id="form" onSubmit={handleSubmit}>
<input
type = "text"

View file

@ -0,0 +1,6 @@
td {
padding-top: 8px;
padding-bottom: 8px;
padding-left: 50px;
border: 1px solid;
}

View file

@ -1,4 +1,16 @@
.widgetText {
padding-left: 1em;
color: #333;
.imageee {
margin-top: 50px;
margin-left: 20px;
max-width: 50px;
}
.displayyyy {
margin-top: 50px;
margin-left: 120px;
float: right;
}
.textttt {
position: fixed;
top: 10px;
}

View file

@ -1,3 +1,14 @@
img {
width: 50px;
.image {
margin-top: 50px;
margin-left: 20px;
width: 70px;
}
.display {
margin-top: 50px;
}
.text {
position: fixed;
top: 10px;
}

View file

@ -1,7 +1,14 @@
/* MAKE SURE TO BE SPECIFIC WITH STYLING CUZ THIS CHANGED DIFFERENT SPANS
span {
float: right;
margin-right: 50px;
.imagee {
margin-top: 50px;
margin-left: 20px;
width: 50px;
}
*/
.displayy {
margin-top: 50px;
}
.text {
position: fixed;
top: 10px;
}

View file

@ -1,13 +1,115 @@
export default function Settings() {
import React, { useState, useEffect } from "react";
import { getName, getEmail, getSessionKey, handleLogout } from "../utils/utils";
const Settings = () => {
const [currentName, setCurrentName] = useState('');
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [newName, setNewName] = useState('');
const [currentPassword, setCurrentPassword] = useState('');
const [newPassword, setNewPassword] = useState('');
const [email, setEmail] = useState('');
const [deleteAccount, setDeleteAccount] = useState('');
useEffect(() => {
async function fetchName() {
const currentName = await getName();
setCurrentName(currentName);
}
fetchName();
}, []);
useEffect(() => {
async function fetchEmail() {
const email = await getEmail();
setEmail(email);
}
fetchEmail();
}, []);
// javascript for the updated username and password alerts
const handleNameClick = () => {
const alert = '<div class="alert alert-success alert-dismissible" role="alert">Name updated successfully!<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div>';
document.getElementById('nameAlert').innerHTML = alert;
const handleNameChange = (event) => {
event.preventDefault();
const name = `${firstName} ${lastName}`;
setNewName(name);
const formData = new FormData();
formData.append('name', name);
fetch(`https://api.bb.gabefarrell.com/auth/changename?name=${name}`, {
method: 'POST',
body: formData,
headers: {
'x-session-key': getSessionKey(),
},
})
.then(response => {
if(response.ok) {
alert('Name updated successfully!');
window.location.reload();
}
else {
alert('Name update failed!');
window.location.reload();
}
})
}
const handlePasswordClick = () => {
const alert = '<div class="alert alert-success alert-dismissible" role="alert">Name updated successfully!<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div>';
document.getElementById('passwordAlert').innerHTML = alert;
const handlePasswordChange = (event) => {
event.preventDefault();
const oldP = `${currentPassword}`;
const newP = `${newPassword}`
const formData = new FormData();
formData.append('old', oldP);
formData.append('new', newP);
fetch(`https://api.bb.gabefarrell.com/auth/changepassword?old=${oldP}&new=${newP}`, {
method: 'POST',
body: formData,
headers: {
'x-session-key': getSessionKey(),
},
})
.then(response => {
if(response.ok) {
alert('Password updated successfully!');
window.location.reload();
}
else {
alert('Password update failed! Make sure you have entered your current password correctly');
window.location.reload();
}
})
}
const handleDeleteAccount = (event) => {
event.preventDefault();
const password = `${deleteAccount}`;
const formData = new FormData();
formData.append('password', password);
fetch(`https://api.bb.gabefarrell.com/auth/deleteaccount?password=${password}`, {
method: 'POST',
body: formData,
headers: {
'x-session-key': getSessionKey(),
},
})
.then(response => {
if(response.ok) {
alert('Account deleted successfully!');
handleLogout();
}
else {
alert('Account could not be delete. Make sure you have entered your current password correctly');
window.location.reload();
}
})
}
(() => {
@ -16,10 +118,10 @@ export default function Settings() {
// Loop over them and prevent submission
Array.from(forms).forEach(form => {
form.addEventListener('click', event => {
form.addEventListener('submit', event => {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated')
@ -28,98 +130,117 @@ export default function Settings() {
})()
// toggle between light mode and dark mode
const toggleDarkMode = () => {
/*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')
}
}
}*/
// JSX: Javascript XML
return (
<>
<div className="container overflow-auto">
<h4 className="mt-4 mb-4">Profile Settings</h4>
<h5 className="mb-4">Email and Name</h5>
<form className="needs-validation" noValidate>
<form className="needs-validation" onSubmit={handleNameChange} noValidate>
<div className="row mb-3">
<label htmlFor="staticEmail" className="col-2 col-form-label">Email</label>
<div className="col-4">
<input type="text" readOnly className="form-control-plaintext" id="staticEmail" value="daniel_quinonezrosario@student.uml.edu" />
</div>
</div>
<div className="row mb-3">
<label htmlFor="currentName" className="col-2 col-form-label">Current Name</label>
<div className="col-4">
<input type="text" readOnly className="form-control-plaintext" id="currentName" value="Daniel" />
</div>
</div>
<div className="row mb-3">
<label htmlFor="newName" className="col-2 col-form-label">New Name</label>
<div className="col-4">
<input type="text" className="form-control" id="newName" required />
<div className="invalid-feedback">
Please enter a new name
<label htmlFor="staticEmail" className="col-2 col-form-label">Email</label>
<div className="col-4">
<input type="text" readOnly className="form-control-plaintext" id="staticEmail" value={email}/>
</div>
</div>
<div className="row mb-3">
<label htmlFor="currentName" className="col-2 col-form-label">Current Name</label>
<div className="col-4">
<input type="text" readOnly className="form-control-plaintext" id="currentName" value={currentName}/>
</div>
</div>
<div className="row mb-3">
<label htmlFor="newFirstName" className="col-2 col-form-label">New First Name</label>
<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/>
<div className="invalid-feedback">
Please enter a new first name
</div>
</div>
</div>
<div className="row mb-3">
<label htmlFor="newLastName" className="col-2 col-form-label">New Last Name</label>
<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 />
<div className="invalid-feedback">
Please enter a new last name
</div>
</div>
</div>
<div id="nameAlert"></div>
<div>
<button type="button" className="btn btn-primary mb-5" id="newNameButton" onClick={handleNameClick}>Change Name</button>
<button type="submit" className="btn btn-primary mb-5" id="newNameButton">Change Name</button>
</div>
</form>
<h5 className="mb-4">Password</h5>
<form className="needs-validation" noValidate>
<form className="needs-validation" onSubmit={handlePasswordChange} noValidate>
<div className="row mb-3">
<label htmlFor="currentPassword" className="col-2 col-form-label">Current Password</label>
<div className="col-4">
<input type="password" className="form-control" id="currentPassword" minLength="8" required />
<div className="invalid-feedback">
Please enter your current password
<label htmlFor="currentPassword" className="col-2 col-form-label">Current Password</label>
<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 />
<div className="invalid-feedback">
Please enter your current password
</div>
</div>
</div>
</div>
<div className="row mb-3">
<label htmlFor="newPassword" className="col-2 col-form-label">New Password</label>
<div className="col-4">
<input type="password" className="form-control" id="newPassword" minLength="8" required />
<div className="invalid-feedback">
Please enter a new password
<br />
Your new password must be at least 8 characters long
<label htmlFor="newPassword" className="col-2 col-form-label">New Password</label>
<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 />
<div className="invalid-feedback">
Please enter a new password
<br/>
Your new password must be at least 8 characters long
</div>
</div>
</div>
</div>
<div id="passwordAlert"></div>
<div>
<button type="button" className="btn btn-primary mb-5" id="newPasswordButton" onClick={handlePasswordClick}>Change Password</button>
<button type="submit" className="btn btn-primary mb-5" id="newPasswordButton">Change Password</button>
</div>
</form>
<h4 className="mb-4">Dark Mode</h4>
{/*<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>
<div className="mb-4">
<button type="button" className="btn btn-danger">Delete Account</button>
<br />
<div className="mt-2">
CAUTION: This will delete your account. All account and profile data
will be completely erased.
</div>
</div>*/}
<h4 className="mb-4">Account Settings</h4>
<h5 className="mb-4">Delete Your Account</h5>
<form className="needs-validation" onSubmit={handleDeleteAccount} noValidate>
<div className="row mb-3">
<label htmlFor="deleteAccount" className="col-2 col-form-label">Current Password</label>
<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 />
<div className="invalid-feedback">
Please enter your current password in order to delete your account
</div>
</div>
</div>
<div>
<button type="submit" className="btn btn-danger" id="deleteAccountButton">Delete Account</button>
</div>
<div className="mt-2 mb-5 fw-bold">
CAUTION: This will delete your account. All account and profile data
will be completely erased.
</div>
</form>
</div>
</>
);
}
)
}
export default Settings;

View file

@ -35,6 +35,22 @@ export async function getName() {
}
}
export async function getEmail() {
try {
const response = await fetch('https://api.bb.gabefarrell.com/userinfo', {
method: 'GET',
headers: {
'x-session-key': getSessionKey(),
},
});
const data = await response.json();
const email = data.email;
return email;
} catch (error) {
console.error(error);
}
}
export function handleLogout() {
document.cookie.split(";").forEach(function(c) { document.cookie = c.replace(/^ +/, "").replace(/=.*/, "=;expires=" + new Date().toUTCString() + ";path=/"); });
window.location.href='/welcome';