From 60a2fe6d2db29bbdb00fbeabcb27108f2178c3a3 Mon Sep 17 00:00:00 2001 From: Justin Walrath Date: Sat, 17 Jun 2023 22:42:30 -0400 Subject: [PATCH] [#9] Can now lookup account information for the budgets --- client/src/base/App.jsx | 2 +- client/src/data/context/BudgetContext.jsx | 17 ++++++-- client/src/data/context/BudgetReducer.js | 6 +++ client/src/views/BudgetPeriodCard.jsx | 4 +- client/src/views/BudgetPeriodTransTable.jsx | 47 +++++++++++++++------ 5 files changed, 56 insertions(+), 20 deletions(-) diff --git a/client/src/base/App.jsx b/client/src/base/App.jsx index 9a41eaa..1d1eed2 100644 --- a/client/src/base/App.jsx +++ b/client/src/base/App.jsx @@ -1,5 +1,4 @@ import { useEffect, useContext } from 'react'; -import mockedData from '../mocked/MockedData'; import BudgetCardView from '../views/BudgetCardView'; import { BudgetContext, BudgetState } from '../data/context/BudgetContext'; import './App.css'; @@ -9,6 +8,7 @@ const AppImpl = () => { useEffect(() => { context.api.getCurrentPeriod(); + context.api.getAccounts(); }, []); return ( diff --git a/client/src/data/context/BudgetContext.jsx b/client/src/data/context/BudgetContext.jsx index 0a94163..4e90929 100644 --- a/client/src/data/context/BudgetContext.jsx +++ b/client/src/data/context/BudgetContext.jsx @@ -6,7 +6,8 @@ const BudgetContext = createContext(); const BudgetState = (props) => { const initialState = { - budgetPeriods: [] + budgetPeriods: [], + accounts: [] }, [state, dispatch] = useReducer(BudgetReducer, initialState), api = { @@ -18,9 +19,19 @@ const BudgetState = (props) => { crossorigin: true } }).then(response => { - dispatch({ type: 'budget/populate', data: [{ ...response.data, id: response.data.id }] }); + dispatch({ type: 'budget/populate', data: [response.data] }); + }); + }, + getAccounts: () => { + axios.get('http://localhost:3001/jules/accounts', { + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET', + crossorigin: true + } + }).then(response => { + dispatch({ type: 'accounts/populate', data: response.data }); }); - }, updateBillPaid: (periodId, billId) => { dispatch({ type: 'budget/period/bills/update', data: { periodId, billId }}); diff --git a/client/src/data/context/BudgetReducer.js b/client/src/data/context/BudgetReducer.js index 4f96a86..0132e49 100644 --- a/client/src/data/context/BudgetReducer.js +++ b/client/src/data/context/BudgetReducer.js @@ -15,6 +15,12 @@ const BudgetReducer = (state, action) => { })) }; } + if (action.type === 'accounts/populate') { + return { + ...state, + accounts: action.data + } + } return {...state }; }; diff --git a/client/src/views/BudgetPeriodCard.jsx b/client/src/views/BudgetPeriodCard.jsx index c6c46d3..135b458 100644 --- a/client/src/views/BudgetPeriodCard.jsx +++ b/client/src/views/BudgetPeriodCard.jsx @@ -25,7 +25,7 @@ const BudgetPeriodCard = ({periodData, isActive}) => { cardRef.current.scrollIntoView({inline: "start"}); cardRef.current.parentElement.scrollBy(-40, 0); } - }, []); + }, [isActive]); useEffect(() => { setPaidIncomes(incomes.filter((income) => income.paid)); }, [incomes]); useEffect(() => { setUnpaidIncomes(incomes.filter((income) => !income.paid)); }, [incomes]); useEffect(() => { @@ -34,7 +34,7 @@ const BudgetPeriodCard = ({periodData, isActive}) => { paidBills.reduce((prev, bill) => { return prev + bill.amount; }, 0.0) + paidIncomes.reduce((prev, income) => { return prev + income.amount; }, 0.0) ); - }, [paidBills, paidIncomes]); + }, [paidBills, paidIncomes, periodData.startingAmount]); useEffect(() => { setProjectedLeftover( bankBalance - diff --git a/client/src/views/BudgetPeriodTransTable.jsx b/client/src/views/BudgetPeriodTransTable.jsx index c227473..616e02b 100644 --- a/client/src/views/BudgetPeriodTransTable.jsx +++ b/client/src/views/BudgetPeriodTransTable.jsx @@ -1,24 +1,43 @@ +import { useState, useEffect, useContext } from 'react'; import { Grid } from 'gridjs-react'; import { h } from 'gridjs'; +import { BudgetContext } from '../data/context/BudgetContext'; import './BudgetPeriodTransTable.scss'; import '../../node_modules/gridjs/dist/theme/mermaid.css' const BudgetPeriodTransTable = ({title, transList, isBill, actionHandler}) => { - const columns = [ - 'Description', - 'Amount', - { - name: 'Actions', - formatter: (cell, row) => { - return h('button', { - className: 'py-2 mb-4 px-4 border rounded-md text-white bg-blue-600', - onClick: () => actionHandler(row) - }, row.cells[2].data.paid ? 'Unpay' : 'Pay'); + const context = useContext(BudgetContext), + [tableData, setTableData] = useState([]), + columns = [ + 'Description', + 'Amount', + { + name: 'Actions', + formatter: (cell, row) => { + let buttonText = 'Pay'; + + if (row.cells[2].data.postingDate != null) { + buttonText = row.cells[2].data.isIncome ? 'Paid' : 'Unpay'; + } + + return h('button', { + className: 'py-2 mb-4 px-4 border rounded-md text-white bg-blue-600', + onClick: () => actionHandler(row) + }, buttonText); + } } - } - ], - toCurrency = (amount) => { return '$' + (isBill === true ? '-' : '') + amount; }, - tableData = transList.map(t => { return [t.description, toCurrency(t.amount), t]}); + ]; + + useEffect(() => { + const toCurrency = (amount) => { return '$' + (isBill === true ? '-' : '') + amount; }, + lookupAccountName = (accountId) => { + return context.accounts.find((a) => a._id === accountId)?.name ?? ''; + }; + + setTableData(transList.map(t => { + return [lookupAccountName(t.account), toCurrency(t.amount), t] + })); + }, [context.accounts, transList, isBill]); return (