jveebs 3 years ago
commit 348b3835e1

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

@ -0,0 +1,23 @@
{
"files": {
"main.css": "/static/css/main.a647f1f7.css",
"main.js": "/static/js/main.205e7457.js",
"static/js/496.f12dc038.chunk.js": "/static/js/496.f12dc038.chunk.js",
"static/media/budgethero1.png": "/static/media/budgethero1.ef97d4454cc11d5d60d0.png",
"static/media/umass_lowell.jpeg": "/static/media/umass_lowell.adff7eaefc5d0aa6343d.jpeg",
"static/media/expenses_logo.png": "/static/media/expenses_logo.f24db1454b6c041fade7.png",
"static/media/money2.png": "/static/media/money2.4e0a9f8da499f5fe72a1.png",
"static/media/money1.png": "/static/media/money1.900d2433a99d49f20ade.png",
"static/media/river_hawk.png": "/static/media/river_hawk.175d1b2ee8b8ae31ab50.png",
"static/media/money3.png": "/static/media/money3.8859e70f73221654d7ed.png",
"static/media/BudgetBuddyLogo.png": "/static/media/BudgetBuddyLogo.8e4cd296c3a372956bf4.png",
"index.html": "/index.html",
"main.a647f1f7.css.map": "/static/css/main.a647f1f7.css.map",
"main.205e7457.js.map": "/static/js/main.205e7457.js.map",
"496.f12dc038.chunk.js.map": "/static/js/496.f12dc038.chunk.js.map"
},
"entrypoints": [
"static/css/main.a647f1f7.css",
"static/js/main.205e7457.js"
]
}

@ -0,0 +1,15 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,122 @@
/*!
Copyright (c) 2018 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/
/*!
*
* Copyright 2009-2017 Kris Kowal under the terms of the MIT
* license found at https://github.com/kriskowal/q/blob/v1/LICENSE
*
* With parts by Tyler Close
* Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
* at http://www.opensource.org/licenses/mit-license.html
* Forked at ref_send.js version: 2009-05-11
*
* With parts by Mark Miller
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*!
* @kurkle/color v0.3.2
* https://github.com/kurkle/color#readme
* (c) 2023 Jukka Kurkela
* Released under the MIT License
*/
/*!
* Chart.js v4.2.1
* https://www.chartjs.org
* (c) 2023 Chart.js Contributors
* Released under the MIT License
*/
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @mui/styled-engine v5.12.0
*
* @license MIT
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* A better abstraction over CSS.
*
* @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
* @website https://github.com/cssinjs/jss
* @license MIT
*/
/** @license React v16.13.1
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-is.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 KiB

@ -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(() => {

@ -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>
);
};

@ -29,22 +29,16 @@ 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>
<button type="submit" className="btn btn-primary btn-lg w-100 center" onClick={calculateMonthlyPayment}>Calculate</button>
<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)}/>
<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>
)

@ -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"

@ -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"

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

@ -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;
}

@ -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;
}

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

@ -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>
<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="Daniel" />
</div>
<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="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="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>
</div>*/}
{/*<h4 className="mb-4">Account Settings</h4>
<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.
<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>*/}
<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;

@ -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';

Loading…
Cancel
Save