diff --git a/frontend/src/App.js b/frontend/src/App.js
index 2f44159..2dca27b 100644
--- a/frontend/src/App.js
+++ b/frontend/src/App.js
@@ -79,19 +79,19 @@ export default function App(props) {
palette: {
mode: 'light',
background: {
- drawer: '#333333',
+ drawer: '#3a3f51',
header: '#536067',
tableBody: '#ffffff',
- tableHeader: '#333333',
- details: '#333333',
- detailsContent: '#333333',
+ tableHeader: '#3a3f51',
+ details: '#3a3f51',
+ detailsContent: '#3a3f51',
},
action: {
// disabledBackground: 'set color of background here',
// disabled: '#616161',
},
primary: {
- main: '#333333',
+ main: '#3a3f51',
},
secondary: {
main: '#ffffff',
@@ -110,7 +110,7 @@ export default function App(props) {
MuiDrawer: {
styleOverrides: {
paper: {
- backgroundColor: '#333333',
+ backgroundColor: '#3a3f51',
color: 'white',
},
},
@@ -140,7 +140,7 @@ export default function App(props) {
return (
-
+
{!initComplete && }
{initComplete && (
@@ -148,6 +148,7 @@ export default function App(props) {
{/* */}
setNewAccountDialogOpen(true)} />
+
diff --git a/frontend/src/components/AccountDetails.js b/frontend/src/components/AccountDetails.js
index d5f3e39..c7405ae 100644
--- a/frontend/src/components/AccountDetails.js
+++ b/frontend/src/components/AccountDetails.js
@@ -14,6 +14,8 @@ import { usePopupState, bindTrigger, bindPopover } from 'material-ui-popup-state
import ReconcileForm from './ReconcileForm'
import { createSelector } from '@reduxjs/toolkit'
import Paper from '@mui/material/Paper'
+import BalanceCalculation from './AccountTable/BalanceCalculation'
+import EditIcon from '@mui/icons-material/Edit'
export default function BudgetDetails({ accountId, name }) {
const theme = useTheme()
@@ -56,18 +58,28 @@ export default function BudgetDetails({ accountId, name }) {
justifyContent="space-between"
alignItems="center"
spacing={2}
- sx={{ p: 3, height: '100%' }}
+ sx={{ px: 2, pb: 2, height: '100%' }}
>
-
-
-
+
+
- {account.name}
-
+
+ {account.name}
+
+
+ {/* */}
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
+
+
- Summary
-
-
-
-
- Cleared
- Uncleared ({pendingTransactions})
- Balance
-
-
-
-
- {intlFormat(account.cleared)}
-
-
- +
-
-
- {intlFormat(account.uncleared)}
-
-
- =
-
-
- {intlFormat(account.balance)}
-
-
+ Pending Transactions
+ {pendingTransactions}
diff --git a/frontend/src/components/AccountTable/AccountTable.js b/frontend/src/components/AccountTable/AccountTable.js
index 1c47a0c..b4f0ecc 100644
--- a/frontend/src/components/AccountTable/AccountTable.js
+++ b/frontend/src/components/AccountTable/AccountTable.js
@@ -161,13 +161,6 @@ export default function Account(props) {
const payeesMap = useSelector(selectPayeesMap)
- let amountFieldFocused = null
- let amountFieldModified = false
- const focusAmountField = field => {
- amountFieldFocused = field
- amountFieldModified = false
- }
-
const filter = createFilterOptions()
const columns = [
{
@@ -383,10 +376,6 @@ export default function Account(props) {
)
},
editComponent: props => {
- // if (amountFieldModified === true && amountFieldFocused !== 'outflow') {
- // props.value.amount = 0
- // }
-
const value = dinero(props.value)
return (
@@ -395,7 +384,6 @@ export default function Account(props) {
variant="standard"
value={toUnit(value, { digits: 2 })}
onChange={value => {
- amountFieldModified = true
props.onChange(toSnapshot(inputToDinero(value)))
}}
// onFocus={focusOutflowField}
@@ -712,7 +700,7 @@ export default function Account(props) {
}
return (
-
+
)
}
diff --git a/frontend/src/components/AccountTable/BalanceCalculation.js b/frontend/src/components/AccountTable/BalanceCalculation.js
new file mode 100644
index 0000000..21f3e7f
--- /dev/null
+++ b/frontend/src/components/AccountTable/BalanceCalculation.js
@@ -0,0 +1,115 @@
+import React, { useState, useEffect } from 'react'
+import { useDispatch } from 'react-redux'
+import { accountsSelectors, editAccount } from '../../redux/slices/Accounts'
+import { FromAPI, getBalanceColor, intlFormat } from '../../utils/Currency'
+import { usePopupState } from 'material-ui-popup-state/hooks'
+import Stack from '@mui/material/Stack'
+import Box from '@mui/material/Box'
+import Typography from '@mui/material/Typography'
+import { useTheme } from '@mui/styles'
+import { createSelector } from '@reduxjs/toolkit'
+
+export default function BalanceCalculation({ account }) {
+ const theme = useTheme()
+
+ return (
+
+
+
+
+ {intlFormat(account.cleared)}
+
+
+ Cleared
+
+
+
+
+
+ +
+
+
+
+
+
+ {intlFormat(account.uncleared)}
+
+
+ Uncleared
+
+
+
+
+
+ =
+
+
+
+
+
+ {intlFormat(account.balance)}
+
+
+ Working Balance
+
+
+
+
+ )
+}
diff --git a/frontend/src/components/BudgetDetails.js b/frontend/src/components/BudgetDetails.js
index 4448f95..9c8acd4 100644
--- a/frontend/src/components/BudgetDetails.js
+++ b/frontend/src/components/BudgetDetails.js
@@ -1,26 +1,21 @@
import Box from '@mui/material/Box'
import { useSelector, useDispatch } from 'react-redux'
-import { getBalanceColor, inputToDinero, intlFormat, valueToDinero } from '../utils/Currency'
-import Table from '@mui/material/Table'
-import TableBody from '@mui/material/TableBody'
-import TableCell from '@mui/material/TableCell'
-import TableContainer from '@mui/material/TableContainer'
-import TableRow from '@mui/material/TableRow'
-import TableHead from '@mui/material/TableHead'
+import { inputToDinero, intlFormat, valueToDinero, getBalanceColor } from '../utils/Currency'
import { useTheme } from '@mui/styles'
import Stack from '@mui/material/Stack'
import { isPositive, isZero } from 'dinero.js'
import Alert from '@mui/material/Alert'
-import IconButton from '@mui/material/IconButton'
-import { formatMonthFromDateString, getDateFromString } from '../utils/Date'
-import BudgetMonthPicker from './BudgetMonthPicker'
-import Button from '@mui/material/Button'
import Typography from '@mui/material/Typography'
-import { usePopupState, bindTrigger } from 'material-ui-popup-state/hooks'
-import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIosNew'
-import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos'
-import { selectActiveBudget, setCurrentMonth } from '../redux/slices/Budgets'
+import { selectActiveBudget } from '../redux/slices/Budgets'
import Paper from '@mui/material/Paper'
+import BudgetMonthCalculation from './BudgetTable/BudgetMonthCalculation'
+import CategoryMonthActivity from './CategoryMonthActivity'
+import BudgetMonthNavigator from './BudgetMonthNavigator'
+import Card from '@mui/material/Card'
+import CardActions from '@mui/material/CardActions'
+import CardContent from '@mui/material/CardContent'
+import Button from '@mui/material/Button'
+import { setSelectedCategory } from '../redux/slices/Categories'
export default function BudgetDetails(props) {
const theme = useTheme()
@@ -31,194 +26,117 @@ export default function BudgetDetails(props) {
return state.budgetMonths.entities[month] || null
})
- const income = budgetMonth ? valueToDinero(budgetMonth.income) : inputToDinero(0)
- const activity = budgetMonth ? valueToDinero(budgetMonth.activity) : inputToDinero(0)
- const budgeted = budgetMonth ? valueToDinero(budgetMonth.budgeted) : inputToDinero(0)
const underfunded = budgetMonth ? valueToDinero(budgetMonth.underfunded) : inputToDinero(0)
-
- const availableMonths = useSelector(state => state.budgets.availableMonths)
const budget = useSelector(selectActiveBudget)
-
const toBeBudgeted = budget ? valueToDinero(budget.toBeBudgeted) : inputToDinero(0)
- const nextMonth = getDateFromString(month)
- nextMonth.setMonth(nextMonth.getMonth() + 1)
- const nextMonthDisabled = !availableMonths.includes(formatMonthFromDateString(nextMonth))
+ const selectedCategory = useSelector(state => {
+ if (!state.categories.selected) {
+ return null
+ }
- const prevMonth = getDateFromString(month)
- prevMonth.setMonth(prevMonth.getMonth() - 1)
- const prevMonthDisabled = !availableMonths.includes(formatMonthFromDateString(prevMonth))
-
- const monthPickerPopupState = usePopupState({
- variant: 'popover',
- popupId: 'monthPicker',
+ return state.categories.entities[state.categories.selected]
})
-
- const navigateMonth = direction => {
- const monthDate = new Date(Date.UTC(...month.split('-')))
- monthDate.setDate(1)
- monthDate.setMonth(monthDate.getMonth() + direction)
- dispatch(setCurrentMonth({ month: formatMonthFromDateString(monthDate) }))
+ const clearSelectedCategory = () => {
+ dispatch(setSelectedCategory(null))
}
- const isToday = month === formatMonthFromDateString(new Date())
-
return (
-
-
-
-
- navigateMonth(-1)}
- sx={{
- fontSize: theme.typography.h6.fontSize,
- color: 'white',
- }}
- >
-
-
+
+
+
-
-
+
+
+
+
- {new Date(Date.UTC(...month.split('-'))).toLocaleDateString(undefined, {
- year: 'numeric',
- month: 'long',
- })}
-
-
-
-
-
- navigateMonth(1)}
- sx={{
- fontSize: theme.typography.h6.fontSize,
- // [`.Mui-disabled`]: { color: theme.palette.grey[500] },
- color: 'white',
- }}
- >
-
-
-
-
-
-
-
-
-
- Available to Budget
+ Monthly Summary
-
-
-
+
+
- {intlFormat(toBeBudgeted)}
-
+ Underfunded
+ {intlFormat(underfunded)}
+
+
+
+
+ {selectedCategory && (
+
+
+
+
+ {selectedCategory.name} Activity
+
+
+
+
+
+
+
+
+
-
-
-
-
-
- Monthly Breakdown
-
-
-
- Income
- {intlFormat(income)}
-
-
-
- Activity
- {intlFormat(activity)}
-
-
-
- Budgeted
- {intlFormat(budgeted)}
-
-
-
- Underfunded
- {intlFormat(underfunded)}
-
-
-
+ )}
+
+
diff --git a/frontend/src/components/BudgetMonthNavigator.js b/frontend/src/components/BudgetMonthNavigator.js
new file mode 100644
index 0000000..2bc11ca
--- /dev/null
+++ b/frontend/src/components/BudgetMonthNavigator.js
@@ -0,0 +1,139 @@
+import Box from '@mui/material/Box'
+import { useSelector, useDispatch } from 'react-redux'
+import { useTheme } from '@mui/styles'
+import Stack from '@mui/material/Stack'
+import IconButton from '@mui/material/IconButton'
+import { formatMonthFromDateString, getDateFromString } from '../utils/Date'
+import BudgetMonthPicker from './BudgetMonthPicker'
+import Button from '@mui/material/Button'
+import Typography from '@mui/material/Typography'
+import { usePopupState, bindTrigger } from 'material-ui-popup-state/hooks'
+import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIosNew'
+import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos'
+import { selectActiveBudget, setCurrentMonth } from '../redux/slices/Budgets'
+import EventIcon from '@mui/icons-material/Event'
+import List from '@mui/material/List'
+import ListItem from '@mui/material/ListItem'
+
+export default function BudgetMonthNavigator({ mini }) {
+ const theme = useTheme()
+ const dispatch = useDispatch()
+
+ const month = useSelector(state => state.budgets.currentMonth)
+ const availableMonths = useSelector(state => state.budgets.availableMonths)
+
+ const nextMonth = getDateFromString(month)
+ nextMonth.setMonth(nextMonth.getMonth() + 1)
+ const nextMonthDisabled = !availableMonths.includes(formatMonthFromDateString(nextMonth))
+
+ const prevMonth = getDateFromString(month)
+ prevMonth.setMonth(prevMonth.getMonth() - 1)
+ const prevMonthDisabled = !availableMonths.includes(formatMonthFromDateString(prevMonth))
+
+ const monthPickerPopupState = usePopupState({
+ variant: 'popover',
+ popupId: 'monthPicker',
+ })
+
+ const navigateMonth = direction => {
+ const monthDate = new Date(Date.UTC(...month.split('-')))
+ monthDate.setDate(1)
+ monthDate.setMonth(monthDate.getMonth() + direction)
+ dispatch(setCurrentMonth({ month: formatMonthFromDateString(monthDate) }))
+ }
+
+ const isToday = month === formatMonthFromDateString(new Date())
+
+ if (mini === true) {
+ return (
+
+
+
+
+
+
+ )
+ }
+
+ return (
+
+
+
+ navigateMonth(-1)}
+ sx={{
+ fontSize: theme.typography.h6.fontSize,
+ color: 'white',
+ }}
+ >
+
+
+
+
+
+
+
+
+
+ navigateMonth(1)}
+ sx={{
+ fontSize: theme.typography.h6.fontSize,
+ // [`.Mui-disabled`]: { color: theme.palette.grey[500] },
+ color: 'white',
+ }}
+ >
+
+
+
+
+ )
+}
diff --git a/frontend/src/components/BudgetTable/BudgetMonthCalculation.js b/frontend/src/components/BudgetTable/BudgetMonthCalculation.js
new file mode 100644
index 0000000..8c5543d
--- /dev/null
+++ b/frontend/src/components/BudgetTable/BudgetMonthCalculation.js
@@ -0,0 +1,122 @@
+import React, { useState, useEffect } from 'react'
+import { useDispatch, useSelector } from 'react-redux'
+import Stack from '@mui/material/Stack'
+import Box from '@mui/material/Box'
+import Typography from '@mui/material/Typography'
+import { useTheme } from '@mui/styles'
+import { getBalanceColor, inputToDinero, intlFormat, valueToDinero } from '../../utils/Currency'
+import { selectActiveBudget } from '../../redux/slices/Budgets'
+import { add } from 'dinero.js'
+
+export default function BudgetMonthCalculation({ account }) {
+ const theme = useTheme()
+
+ const month = useSelector(state => state.budgets.currentMonth)
+ const budgetMonth = useSelector(state => {
+ return state.budgetMonths.entities[month] || null
+ })
+
+ const income = budgetMonth ? valueToDinero(budgetMonth.income) : inputToDinero(0)
+ const activity = budgetMonth ? valueToDinero(budgetMonth.activity) : inputToDinero(0)
+
+ return (
+
+
+
+
+ {intlFormat(income)}
+
+
+ Income
+
+
+
+
+
+ +
+
+
+
+
+
+ {intlFormat(activity)}
+
+
+ Spent
+
+
+
+
+
+ =
+
+
+
+
+
+ {intlFormat(add(income, activity))}
+
+
+ Net
+
+
+
+
+ )
+}
diff --git a/frontend/src/components/BudgetTable/BudgetTable.js b/frontend/src/components/BudgetTable/BudgetTable.js
index 431449b..ffe859b 100644
--- a/frontend/src/components/BudgetTable/BudgetTable.js
+++ b/frontend/src/components/BudgetTable/BudgetTable.js
@@ -3,7 +3,7 @@ import { useSelector, useDispatch } from 'react-redux'
import { createSelector } from '@reduxjs/toolkit'
import { refreshBudget } from '../../redux/slices/Budgets'
import { updateCategoryMonth, refreshBudgetCategory } from '../../redux/slices/BudgetMonths'
-import { updateCategory } from '../../redux/slices/Categories'
+import { setSelectedCategory, updateCategory } from '../../redux/slices/Categories'
import { updateCategoryGroup, fetchCategories, categoryGroupsSelectors } from '../../redux/slices/CategoryGroups'
import { categoriesSelectors } from '../../redux/slices/Categories'
import IconButton from '@mui/material/IconButton'
@@ -502,6 +502,11 @@ export default function BudgetTable(props) {
dispatch(refreshBudget())
}
+ const onCategoryRowClick = row => {
+ console.log(row)
+ dispatch(setSelectedCategory(row.original.categoryId))
+ }
+
const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = useTable(
{
columns,
@@ -526,8 +531,8 @@ export default function BudgetTable(props) {
sx={{
backgroundColor: theme.palette.background.tableBody,
display: 'grid',
- gridTemplateColums: '1fr',
- gridTemplateRows: 'auto 1fr auto',
+ // gridTemplateColums: '1fr',
+ // gridTemplateRows: 'auto 1fr auto',
height: '100vh',
}}
>
@@ -579,6 +584,9 @@ export default function BudgetTable(props) {
prepareRow(row)
return (
onCategoryRowClick(row)}
{...row.getRowProps({
...(!row.original.groupId && { sx: { backgroundColor: theme.palette.action.hover } }),
})}
diff --git a/frontend/src/components/CategoryMonthActivity.js b/frontend/src/components/CategoryMonthActivity.js
new file mode 100644
index 0000000..9fa2fe7
--- /dev/null
+++ b/frontend/src/components/CategoryMonthActivity.js
@@ -0,0 +1,112 @@
+import React from 'react'
+import { accountsSelectors } from '../redux/slices/Accounts'
+import { useSelector } from 'react-redux'
+import Box from '@mui/material/Box'
+import Table from '@mui/material/Table'
+import TableHead from '@mui/material/TableHead'
+import TableBody from '@mui/material/TableBody'
+import TableRow from '@mui/material/TableRow'
+import TableCell from '@mui/material/TableCell'
+import TableContainer from '@mui/material/TableContainer'
+import Tooltip from '@mui/material/Tooltip'
+import Typography from '@mui/material/Typography'
+import { intlFormat, FromAPI } from '../utils/Currency'
+import { formatMonthFromDateString } from '../utils/Date'
+import { useTheme } from '@mui/styles'
+import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'
+
+export default function CategoryMonthActivity(props) {
+ const theme = useTheme()
+
+ const month = useSelector(state => new Date(state.budgets.currentMonth))
+ const accounts = useSelector(accountsSelectors.selectAll)
+ const selectedCategory = useSelector(state => {
+ if (!state.categories.selected) {
+ return null
+ }
+
+ return state.categories.entities[state.categories.selected]
+ })
+ const payees = useSelector(state => state.payees.entities)
+
+ if (!selectedCategory) {
+ return <>No category selected>
+ }
+
+ const transactions = accounts.reduce((total, account) => {
+ const filtered = Object.values(account.transactions.entities).filter(trx => {
+ const trxDate = new Date(trx.date)
+ if (trx.categoryId !== selectedCategory.id) {
+ return false
+ }
+
+ if (trxDate.getMonth() === month.getMonth() && trxDate.getFullYear() === month.getFullYear()) {
+ return true
+ }
+
+ return false
+ })
+
+ return total.concat(filtered)
+ }, [])
+
+ if (transactions.length === 0) {
+ return No transactions for this month
+ }
+
+ return (
+
+
+
+
+
+
+
+ Payee
+
+
+ Amount
+
+
+
+
+
+ {transactions.map(transaction => {
+ transaction = FromAPI.transformTransaction(transaction)
+ return (
+
+
+
+ Date: {formatMonthFromDateString(transaction.date)}
+
+
+ Account: {accounts.find(acct => acct.id === transaction.accountId).name}
+
+
+ Memo: {transaction.memo}{' '}
+
+
+ }
+ >
+
+
+
+
+ {payees[transaction.payeeId].name}
+ {intlFormat(transaction.amount)}
+
+ )
+ })}
+
+
+
+
+ )
+}
diff --git a/frontend/src/components/Drawer.js b/frontend/src/components/Drawer.js
index 0344d14..2c4fee9 100644
--- a/frontend/src/components/Drawer.js
+++ b/frontend/src/components/Drawer.js
@@ -1,5 +1,5 @@
import React, { useState } from 'react'
-import Drawer from '@mui/material/Drawer'
+import MuiDrawer from '@mui/material/Drawer'
import List from '@mui/material/List'
import Divider from '@mui/material/Divider'
import ListItem from '@mui/material/ListItem'
@@ -11,18 +11,13 @@ import ExpandMore from '@mui/icons-material/ExpandMore'
import Collapse from '@mui/material/Collapse'
import { useNavigate } from 'react-router-dom'
import { useSelector, useDispatch } from 'react-redux'
-import AccountBalanceIcon from '@mui/icons-material/AccountBalance'
import { inputToDinero, intlFormat, valueToDinero } from '../utils/Currency'
import LogoutIcon from '@mui/icons-material/Logout'
import api from '../api'
-import Grid from '@mui/material/Grid'
import { add, isNegative } from 'dinero.js'
-import { useTheme } from '@mui/styles'
+import { styled, useTheme } from '@mui/styles'
import AddCircleIcon from '@mui/icons-material/AddCircle'
-import Menu from '@mui/material/Menu'
-import MenuItem from '@mui/material/MenuItem'
-import { usePopupState, bindTrigger, bindMenu } from 'material-ui-popup-state/hooks'
-import ChevronRightIcon from '@mui/icons-material/ChevronRight'
+import { usePopupState } from 'material-ui-popup-state/hooks'
import { accountsSelectors, editAccount, fetchAccounts } from '../redux/slices/Accounts'
import { setTheme } from '../redux/slices/App'
import { selectActiveBudget } from '../redux/slices/Budgets'
@@ -30,9 +25,51 @@ import Brightness4Icon from '@mui/icons-material/Brightness4'
import Brightness7Icon from '@mui/icons-material/Brightness7'
import Settings from './Settings/Settings'
import SettingsIcon from '@mui/icons-material/Settings'
-import MailOutlineIcon from '@mui/icons-material/MailOutline'
+import Box from '@mui/material/Box'
+import Stack from '@mui/material/Stack'
+import Typography from '@mui/material/Typography'
+import Avatar from '@mui/material/Avatar'
+import ChevronLeftIcon from '@mui/icons-material/ChevronLeft'
+import ChevronRightIcon from '@mui/icons-material/ChevronRight'
+import AccountBalanceIcon from '@mui/icons-material/AccountBalance'
-const drawerWidth = 350
+const drawerWidth = 300
+
+const openedMixin = theme => ({
+ width: drawerWidth,
+ transition: theme.transitions.create('width', {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ overflowX: 'hidden',
+})
+
+const closedMixin = theme => ({
+ transition: theme.transitions.create('width', {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ overflowX: 'hidden',
+ width: `calc(${theme.spacing(9)} + 1px)`,
+ [theme.breakpoints.up('sm')]: {
+ width: `calc(${theme.spacing(9)} + 1px)`,
+ },
+})
+
+const Drawer = styled(MuiDrawer, { shouldForwardProp: prop => prop !== 'open' })(({ theme, open }) => ({
+ width: drawerWidth,
+ flexShrink: 0,
+ whiteSpace: 'nowrap',
+ boxSizing: 'border-box',
+ ...(open && {
+ ...openedMixin(theme),
+ '& .MuiDrawer-paper': openedMixin(theme),
+ }),
+ ...(!open && {
+ ...closedMixin(theme),
+ '& .MuiDrawer-paper': closedMixin(theme),
+ }),
+}))
export default function AppDrawer(props) {
const dispatch = useDispatch()
@@ -49,6 +86,7 @@ export default function AppDrawer(props) {
/**
* State block
*/
+ const [drawerOpen, setDrawerOpen] = useState(true)
const [accountsListOpen, setAccountsListOpen] = useState({ ACCOUNTS: true, OFF_BUDGET: true })
const [selectedItem, setSelectedItem] = useState('Budget')
const [settingsOpen, setSettingsOpen] = useState(false)
@@ -102,39 +140,46 @@ export default function AppDrawer(props) {
return (
- listItemClicked(key)}>
-
-
-
-
- {accountsListOpen[key] ? (
-
- ) : (
-
- )}
-
-
-
-
-
-
+ listItemClicked(key)}>
+ {drawerOpen && (
+ <>
+
+ {accountsListOpen[key] ? (
+
+ ) : (
+
+ )}
+
+ {label}
+
+
+ {intlFormat(balance)}
+
+
+ }
/>
-
-
-
+ >
+ )}
+ {!drawerOpen && (
+ <>
+ } />
+
+ {accountsListOpen[key] ? (
+
+ ) : (
+
+ )}
+
+ >
+ )}
+
@@ -169,11 +214,16 @@ export default function AppDrawer(props) {
props.onAddAccountClick()
}
+ const toggleDrawer = () => {
+ setDrawerOpen(!drawerOpen)
+ }
+
const AccountItem = account => {
const balance = valueToDinero(account.balance)
const balanceColor = isNegative(balance) ? theme.palette.error.main : theme.palette.secondary.main
return (
- listItemClicked(`account-${account.id}`, `/accounts/${account.id}`)}
@@ -195,33 +245,43 @@ export default function AppDrawer(props) {
DragState.dropAccount = -1
}}
>
-
-
-
-
+ {drawerOpen === false && (
+
+ {account.name[0]}
+
+ )}
+ {drawerOpen === true && (
+
+
+
+
-
-
-
-
-
+
+ {/* {selectedItem === `account-${account.id}` && (
+
+ )} */}
+
+
+
+ )}
+
)
}
@@ -235,6 +295,7 @@ export default function AppDrawer(props) {
-
-
-
+
+ {drawerOpen && }
+
+ {drawerOpen === false ? (
+
+ ) : (
+
+ )}
+
-
- {/* */}
+
+
+
+
{menuItems.map((menuItemConfig, index) => (
- listItemClicked(menuItemConfig.name, menuItemConfig.path)}
selected={selectedItem === menuItemConfig.name}
>
-
+
{index % 2 === 0 ? : }
-
+
))}
-
+ {/* */}
{budgetAccounts.length > 0 && AccountList('ACCOUNTS', budgetAccounts)}
@@ -281,21 +347,46 @@ export default function AppDrawer(props) {
-
-
-
- props.onAddAccountClick()} />
+ {drawerOpen && (
+ <>
+
+
+
+
+ >
+ )}
+ {drawerOpen === false && (
+ <>
+
+
+
+ >
+ )}
-
+
+
+
+
+
+
+
+
+
+
{currentTheme === 'dark' ? (
@@ -303,15 +394,16 @@ export default function AppDrawer(props) {
)}
-
+
+
-
+
-
+
diff --git a/frontend/src/pages/Account.js b/frontend/src/pages/Account.js
index 50e68f8..d681977 100644
--- a/frontend/src/pages/Account.js
+++ b/frontend/src/pages/Account.js
@@ -5,7 +5,7 @@ import AccountTable from '../components/AccountTable/AccountTable'
import { useNavigate } from 'react-router-dom'
import { accountsSelectors } from '../redux/slices/Accounts'
import AccountDetails from '../components/AccountDetails'
-import Grid from '@mui/material/Grid'
+import Stack from '@mui/material/Stack'
import Box from '@mui/material/Box'
import { useTheme } from '@mui/styles'
@@ -22,5 +22,35 @@ export default function Account(props) {
}
}, [])
- return {account && }
+ return (
+
+
+
+
+
+
+
+
+
+ )
}
diff --git a/frontend/src/pages/Budget.js b/frontend/src/pages/Budget.js
index 1e5f93b..ef37391 100644
--- a/frontend/src/pages/Budget.js
+++ b/frontend/src/pages/Budget.js
@@ -1,32 +1,43 @@
import React from 'react'
import BudgetTable from '../components/BudgetTable/BudgetTable'
import BudgetDetails from '../components/BudgetDetails'
-import Grid from '@mui/material/Grid'
import Box from '@mui/material/Box'
+import Stack from '@mui/material/Stack'
import { useTheme } from '@mui/styles'
-import BudgetTableHeader from '../components/BudgetTable/BudgetTableHeader'
+import { useSelector } from 'react-redux'
export default function Budget(props) {
const theme = useTheme()
return (
-
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
)
}
diff --git a/frontend/src/redux/slices/App.js b/frontend/src/redux/slices/App.js
index ccce4d2..f0253f7 100644
--- a/frontend/src/redux/slices/App.js
+++ b/frontend/src/redux/slices/App.js
@@ -4,7 +4,7 @@ const appSlice = createSlice({
name: 'app',
initialState: {
- theme: localStorage.getItem('theme') || 'light',
+ theme: localStorage.getItem('theme') || 'dark',
},
reducers: {
diff --git a/frontend/src/redux/slices/Categories.js b/frontend/src/redux/slices/Categories.js
index e27bc4d..a35e4c9 100644
--- a/frontend/src/redux/slices/Categories.js
+++ b/frontend/src/redux/slices/Categories.js
@@ -23,12 +23,18 @@ const categoriesAdapter = createEntityAdapter()
const categoriesSlice = createSlice({
name: 'categories',
- initialState: categoriesAdapter.getInitialState(),
+ initialState: categoriesAdapter.getInitialState({
+ selected: null,
+ }),
reducers: {
setCategories: (state, { payload }) => {
categoriesAdapter.setAll(state, payload)
},
+
+ setSelectedCategory: (state, { payload }) => {
+ state.selected = payload
+ },
},
extraReducers: builder => {
@@ -42,7 +48,7 @@ const categoriesSlice = createSlice({
},
})
-export const { setCategories } = categoriesSlice.actions
+export const { setCategories, setSelectedCategory } = categoriesSlice.actions
export const categoriesSelectors = categoriesAdapter.getSelectors(state => state.categories)
export const selectCategoryToGroupMap = createSelector(categoriesSelectors.selectAll, categories =>