Expenses by Category Chart & Add transaction widget

main
jveebs 3 years ago
parent 78e2b99ef2
commit 1b5e9a2cef

@ -7,11 +7,10 @@ import { getSessionKey } from '../utils/utils.js'
const AddExpenseForm = (props) => { const AddExpenseForm = (props) => {
const { dispatch } = useContext(AppContext); const { dispatch } = useContext(AppContext);
const [name, setName] = useState('');
const [cost, setCost] = useState(''); const [cost, setCost] = useState('');
const [category, setCategory] = useState(''); const [category, setCategory] = useState('');
const [categoryList, setCategoryList] = useState([]); const [categoryList, setCategoryList] = useState([]);
const [isExpense, setIsExpense] = useState(true); const [transactionType, setTransactionType] = useState('expenses');
useEffect(() => { useEffect(() => {
try { try {
@ -26,18 +25,23 @@ const AddExpenseForm = (props) => {
if (data.status != 200) { if (data.status != 200) {
console.log(data.error); console.log(data.error);
} else { } else {
isExpense getCategoryList();
? setCategoryList(Object.keys(data.expenses))
: setCategoryList(Object.keys(data.income));
} }
}) })
} catch(error) { } catch(error) {
console.error(error); console.error(error);
} }
}, []) }, [transactionType])
const toggleTransactionType = () => { const toggleTransactionType = () => {
setIsExpense(!isExpense); if (transactionType == "expenses") {
setTransactionType("income");
} else {
setTransactionType("expenses");
}
}
const getCategoryList = () => {
fetch('https://api.bb.gabefarrell.com/w/budget', { fetch('https://api.bb.gabefarrell.com/w/budget', {
method: 'GET', method: 'GET',
headers: { headers: {
@ -49,9 +53,19 @@ const AddExpenseForm = (props) => {
if (data.status != 200) { if (data.status != 200) {
console.log(data.error); console.log(data.error);
} else { } else {
isExpense let categories = [];
? setCategoryList(Object.keys(data.expenses))
: setCategoryList(Object.keys(data.income)); Object.values(data.expenses).map((transactions) => {
transactions.forEach(transaction => {
if (transaction.type == transactionType && !categories.includes(transaction.category)) {
categories.push(transaction.category)
}
});
});
if (categories.length == 0) categories = ["Uncategorized"];
setCategoryList(categories);
setCategory(categories[0])
} }
}) })
}; };
@ -64,7 +78,6 @@ const AddExpenseForm = (props) => {
let currency = "USD" let currency = "USD"
let whole = 0; let whole = 0;
let decimal = 0; let decimal = 0;
let type = isExpense ? 'expenses' : 'income';
if (cost.includes(".")) { if (cost.includes(".")) {
@ -77,10 +90,12 @@ const AddExpenseForm = (props) => {
formData.append('currency', currency); formData.append('currency', currency);
formData.append('whole', whole); formData.append('whole', whole);
formData.append('decimal', decimal); formData.append('decimal', decimal);
formData.append('type', type) formData.append('type', transactionType)
console.log(transactionType);
try { try {
fetch(`https://api.bb.gabefarrell.com/w/transactions?whole=${whole}&decimal=${decimal}&currency=${currency}&category=${category}&type=${type}`, { fetch(`https://api.bb.gabefarrell.com/w/transactions?whole=${whole}&decimal=${decimal}&currency=${currency}&category=${category}&type=${transactionType}`, {
method: 'POST', method: 'POST',
body: formData, body: formData,
headers: { headers: {
@ -99,7 +114,6 @@ const AddExpenseForm = (props) => {
console.error(error); console.error(error);
} }
setName('');
setCost(''); setCost('');
}; };
@ -148,13 +162,13 @@ const AddExpenseForm = (props) => {
<div className='row mt-3'> <div className='row mt-3'>
<div className='col-sm'> <div className='col-sm'>
<button type='submit' onClick={onSubmit} className='btn btn-primary' style={{marginRight:"12px"}}> <button type='submit' onClick={onSubmit} className='btn btn-primary' style={{marginRight:"12px"}}>
Add {isExpense ? 'Expense' : 'Income'} Add {transactionType.substring(0, 1).toUpperCase() + transactionType.substring(1)}
</button> </button>
<button className='btn btn-primary' onClick={handleAddCategory} style={{marginRight:"12px"}}> <button className='btn btn-primary' onClick={handleAddCategory} style={{marginRight:"12px"}}>
Add New Category Add New Category
</button> </button>
<button onClick={toggleTransactionType}> <button onClick={toggleTransactionType}>
{isExpense ? 'EXPENSE' : 'INCOME'} {transactionType.toUpperCase()}
</button> </button>
</div> </div>
</div> </div>

@ -0,0 +1,93 @@
import { Doughnut } from "react-chartjs-2";
import { Chart as ChartJS, ArcElement, Tooltip, Legend, defaults } from 'chart.js';
import { AppProvider } from "../context/AppContext";
import { useState, useEffect } from 'react'
import { calculateValue, getSessionKey } from '../utils/utils.js'
import { Minimize } from "@material-ui/icons";
ChartJS.register(ArcElement, Tooltip, Legend);
export default function CategorizedExpenses() {
const [chartData, setChartData] = useState(null);
useEffect(() => {
async function getChartData() {
try {
fetch('https://api.bb.gabefarrell.com/w/budget', {
method: 'GET',
headers: {
'x-session-key' : getSessionKey(),
}
})
.then(response => response.json())
.then(data => {
if (data.status != 200) {
console.log(data.error);
} else {
let categories = [];
let values = [];
Object.values(data.expenses).map((transactions) => {
let cost = 0;
categories.push(transactions[0].category)
transactions.forEach(transaction => {
cost += calculateValue(transaction.amount);
});
values.push(cost);
});
if (categories.length == 0) categories = [`No expenses`];
const chartData = {
labels: categories,
datasets: [{
data: values,
label: "Category",
backgroundColor: [
'#FFC857',
'#ED8146',
'#DB3A34',
'#5672C7',
],
borderColor: [
"white"
],
borderWidth: 2,
}],
}
setChartData(chartData);
}
})
.catch(error => {
console.log(error);
});
} catch(error) {
console.error(error);
}
}
getChartData();
});
if (!chartData) {
return <p>Loading...</p>
}
return (
<div className="widget">
<h4>Expenses by Category</h4>
<Doughnut className="w-100 h-auto"
data={chartData}
options={{
plugins: {
legend: {
position: 'right'
}
},
responsive: true
}}
/>
</div>
)
}

@ -8,7 +8,7 @@ import { Minimize } from "@material-ui/icons";
ChartJS.register(ArcElement, Tooltip, Legend); ChartJS.register(ArcElement, Tooltip, Legend);
export default function CategorizedBudget() { export default function CategorizedIncome() {
const [chartData, setChartData] = useState(null); const [chartData, setChartData] = useState(null);
useEffect(() => { useEffect(() => {
@ -26,12 +26,11 @@ export default function CategorizedBudget() {
console.log(data.error); console.log(data.error);
} else { } else {
console.log(typeof data.expenses_by_category);
const chartData = { const chartData = {
labels: Object.keys(data.expenses).length > 0 ? Object.keys(data.expenses) : [ "no expenses"], labels: Object.keys(data.income).length > 0 ? Object.keys(data.income) : [ "no income"],
datasets: [ datasets: [
{ {
data: Object.values(data.expenses_by_category).map(category => { data: Object.values(data.income_by_category).map(category => {
return calculateValue(category); return calculateValue(category);
}), }),
backgroundColor: [ backgroundColor: [
@ -66,7 +65,7 @@ export default function CategorizedBudget() {
return ( return (
<div className="widget"> <div className="widget">
<h4>Expenses by Category</h4> <h4>Income by Category</h4>
<Doughnut className="w-100 h-auto" <Doughnut className="w-100 h-auto"
data={chartData} data={chartData}
options={{ options={{

@ -8,7 +8,8 @@ import ExpenseList from '../components/ExpenseList';
import AddExpenseForm from '../components/AddExpenseForm'; import AddExpenseForm from '../components/AddExpenseForm';
import RemainingBudget from '../components/Remaining'; import RemainingBudget from '../components/Remaining';
import AddIncome from '../components/AddIncome' import AddIncome from '../components/AddIncome'
import CategorizedBudget from '../components/CategorizedBudget'; import CategorizedExpenses from '../components/CategorizedExpenses';
import CategorizedIncome from '../components/CategorizedIncome';
import { Typography } from '@mui/material'; import { Typography } from '@mui/material';
export default function Dashboard() { export default function Dashboard() {
@ -40,12 +41,10 @@ export default function Dashboard() {
<div className='row mt-3'> <div className='row mt-3'>
<div className='col-12 col-lg-6'> <div className='col-12 col-lg-6'>
<CategorizedBudget/> <CategorizedExpenses type={"expenses"}/>
</div> </div>
<div className='col-12 col-lg-6'> <div className='col-12 col-lg-6'>
<div className='widget'> <CategorizedExpenses type={"income"}/>
</div>
</div> </div>
</div> </div>
</div> </div>

@ -43,6 +43,6 @@ export function handleLogout() {
window.location.href='/welcome'; window.location.href='/welcome';
} }
export function calculateValue(category) { export function calculateValue(amount) {
return category.whole + category.decimal * 0.01; return amount.whole + amount.decimal * 0.01;
} }
Loading…
Cancel
Save