diff --git a/client/src/Components/TrendsComparison.jsx b/client/src/Components/TrendsComparison.jsx
index 154c1d5..5259e75 100644
--- a/client/src/Components/TrendsComparison.jsx
+++ b/client/src/Components/TrendsComparison.jsx
@@ -1,18 +1,81 @@
import React from 'react';
import { Bar } from 'react-chartjs-2';
-
+import PropTypes from 'prop-types';
// test data for display
-const data = {
- labels: ['Red', 'Green', 'Yellow'],
- datasets: [
- {
- data: [300, 50, 100],
- backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'],
- hoverBackgroundColor: ['#FF6384', '#36A2EB', '#FFCE56']
- }
- ]
-};
-const TrendsComparison = () => ;
+const TrendsComparison = props => {
+ const [m1Data, setm1Data] = React.useState({});
+ const [m2Data, setm2Data] = React.useState({});
+ const [categories, setCategories] = React.useState({});
+ const [graphData, setGraphData] = React.useState({});
+
+ React.useEffect(() => {
+ const cat1 = {};
+ const cat2 = {};
+ const totalCats = {};
+ props.data.accountData.accounts.forEach(account => {
+ if (account.transactions[props.y1]) {
+ if (account.transactions[props.y1][props.m1]) {
+ account.transactions[props.y1][props.m1].forEach(transaction => {
+ if (cat1[transaction.category]) {
+ cat1[transaction.category] += Number(transaction.amount);
+ } else {
+ cat1[transaction.category] = Number(transaction.amount);
+ totalCats[transaction.category] = 1;
+ }
+ });
+ }
+ }
+ if (account.transactions[props.y2]) {
+ if (account.transactions[props.y2][props.m2]) {
+ account.transactions[props.y2][props.m2].forEach(transaction => {
+ if (cat2[transaction.category]) {
+ cat2[transaction.category] += Number(transaction.amount);
+ } else {
+ cat2[transaction.category] = Number(transaction.amount);
+ totalCats[transaction.category] = 1;
+ }
+ });
+ }
+ }
+ });
+ setm1Data(cat1);
+ setm2Data(cat2);
+ setCategories(totalCats);
+ }, [props.data.accountData.accounts, props.m1, props.m2, props.y1, props.y2]);
+
+ React.useEffect(() => {
+ setGraphData({
+ labels: Object.keys(categories).sort(),
+ datasets: [
+ {
+ label: 'Month 1',
+ data: Object.keys(categories)
+ .sort()
+ .map(cat => m1Data[cat] || 0),
+ backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'],
+ hoverBackgroundColor: ['#FF6384', '#36A2EB', '#FFCE56']
+ },
+ {
+ label: 'Month 2',
+ data: Object.keys(categories)
+ .sort()
+ .map(cat => m2Data[cat] || 0),
+ backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'],
+ hoverBackgroundColor: ['#FF6384', '#36A2EB', '#FFCE56']
+ }
+ ]
+ });
+ }, [m1Data, m2Data, categories]);
+ return ;
+};
export default TrendsComparison;
+
+TrendsComparison.propTypes = {
+ data: PropTypes.object,
+ m1: PropTypes.string,
+ m2: PropTypes.string,
+ y1: PropTypes.string,
+ y2: PropTypes.string
+};
diff --git a/client/src/Components/TrendsComparisonSelector.jsx b/client/src/Components/TrendsComparisonSelector.jsx
new file mode 100644
index 0000000..5774dbb
--- /dev/null
+++ b/client/src/Components/TrendsComparisonSelector.jsx
@@ -0,0 +1,168 @@
+import React from 'react';
+import { makeStyles } from '@material-ui/core/styles';
+import InputLabel from '@material-ui/core/InputLabel';
+import FormControl from '@material-ui/core/FormControl';
+import Select from '@material-ui/core/Select';
+import PropTypes from 'prop-types';
+
+const useStyles = makeStyles(theme => ({
+ root: {
+ display: 'flex',
+ flexWrap: 'wrap'
+ },
+ formControl: {
+ margin: theme.spacing(1),
+ minWidth: 120
+ },
+ selectEmpty: {
+ marginTop: theme.spacing(2)
+ }
+}));
+
+const date = new Date();
+const year = date.getFullYear();
+const month = date.getMonth();
+const month2 = month === 0 ? 11 : month - 1;
+
+export default function ComparisonSelector(props) {
+ const classes = useStyles();
+ const [state, setState] = React.useState({
+ month1: month.toString(),
+ year1: year.toString(),
+ month2: month2.toString(),
+ year2: year.toString(),
+ years: []
+ });
+
+ const handleChange = name => event => {
+ setState({
+ ...state,
+ [name]: event.target.value
+ });
+ };
+
+ const updateYear = () => {
+ let result = {};
+ for (let i = 0; i < props.data.accountData.accounts.length; i++) {
+ for (let obj in props.data.accountData.accounts[i].transactions) {
+ result[obj] = 1;
+ }
+ }
+ return Object.keys(result);
+ };
+
+ React.useEffect(() => {
+ setState({
+ ...state,
+ years: updateYear()
+ });
+ }, []);
+
+ React.useEffect(() => props.setM1(state.month1), [state.month1]);
+ React.useEffect(() => props.setM2(state.month2), [state.month2]);
+ React.useEffect(() => props.setY1(state.year1), [state.year1]);
+ React.useEffect(() => props.setY2(state.year2), [state.year2]);
+
+ return (
+
+
+
+ Month 1
+
+
+
+ Year 1
+
+
+
+
+
+ Month 2
+
+
+
+ Year 2
+
+
+
+
+ );
+}
+
+ComparisonSelector.propTypes = {
+ data: PropTypes.object,
+ setM1: PropTypes.func,
+ setM2: PropTypes.func,
+ setY1: PropTypes.func,
+ setY2: PropTypes.func
+};
diff --git a/client/src/Components/TrendsHabits.jsx b/client/src/Components/TrendsHabits.jsx
index ed7bc14..f8fefa0 100644
--- a/client/src/Components/TrendsHabits.jsx
+++ b/client/src/Components/TrendsHabits.jsx
@@ -1,19 +1,153 @@
import React from 'react';
import { Line } from 'react-chartjs-2';
+import PropTypes from 'prop-types';
// test data for display
-const data = {
- labels: ['Red', 'Green', 'Yellow'],
- datasets: [
- {
- data: [300, 50, 100],
- backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'],
- hoverBackgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'],
- lineTension: 0
+const numToMonths = [
+ 'January',
+ 'February',
+ 'March',
+ 'April',
+ 'May',
+ 'June',
+ 'July',
+ 'August',
+ 'September',
+ 'October',
+ 'November',
+ 'December'
+];
+const date = new Date();
+const currentYear = date.getFullYear();
+
+const TrendsHabits = props => {
+ const [category, setCategory] = React.useState([{ name: '' }]);
+ const [graphData, setGraph] = React.useState({});
+ const [months, setMonths] = React.useState([]);
+ const [years, setYears] = React.useState([]);
+
+ React.useEffect(() => {
+ setCategory(
+ props.data.accountData.budgetCategories.filter(category => {
+ return category.name == props.category;
+ })
+ );
+ }, [props.category, props.data.accountData.budgetCategories]);
+
+ React.useEffect(() => {
+ if (props.view === 'month' && category.length > 0) {
+ const possibleMonths = {};
+ props.data.accountData.accounts.map(account => {
+ Object.keys(account.transactions[currentYear]).map(month => {
+ if (possibleMonths[month]) {
+ possibleMonths[month] += account.transactions[currentYear][
+ month
+ ].reduce((x, y) => {
+ if (y.category === category[0].name) {
+ return x + Number(y.amount);
+ }
+ return x + 0;
+
+ }, 0);
+ } else {
+ possibleMonths[month] = account.transactions[currentYear][
+ month
+ ].reduce((x, y) => {
+ if (y.category === category[0].name) {
+ return x + Number(y.amount);
+ }
+ return x + 0;
+
+ }, 0);
+ }
+ });
+ setMonths(possibleMonths);
+ });
+ } else if (category.length > 0) {
+ const possibleYears = {};
+ props.data.accountData.accounts.map(account => {
+ Object.keys(account.transactions).map(year => {
+ const possibleMonths = {};
+ Object.keys(account.transactions[year]).map(month => {
+ if (possibleMonths[month]) {
+ possibleMonths[month] += account.transactions[year][month].reduce(
+ (x, y) => {
+ if (y.category === category[0].name) {
+ return x + Number(y.amount);
+ }
+ return x + 0;
+
+ },
+ 0
+ );
+ } else {
+ possibleMonths[month] = account.transactions[year][month].reduce(
+ (x, y) => {
+ if (y.category === category[0].name) {
+ return x + Number(y.amount);
+ }
+ return x + 0;
+
+ },
+ 0
+ );
+ }
+ });
+ let total = 0;
+ Object.keys(possibleMonths).forEach(
+ month => (total += possibleMonths[month])
+ );
+ if (possibleYears[year]) {
+ possibleYears[year] += total;
+ } else {
+ possibleYears[year] = total;
+ }
+ });
+ });
+ setYears(possibleYears);
}
- ]
-};
+ }, [category, props.data.accountData.accounts, props.view]);
-const TrendsHabits = () => ;
+ React.useEffect(() => {
+ if (category) {
+ if (category[0]) {
+ if (category[0].name) {
+ if (props.view === 'month') {
+ const numbers = Object.keys(months);
+ setGraph({
+ labels: numbers.map(num => numToMonths[num]),
+ datasets: [
+ {
+ label: category[0].name,
+ data: numbers.map(
+ num => Math.floor(months[num] * 1000) / 1000
+ )
+ }
+ ]
+ });
+ } else {
+ const numbers = Object.keys(years);
+ setGraph({
+ labels: numbers,
+ datasets: [
+ {
+ label: category[0].name,
+ data: numbers.map(num => Math.floor(years[num] * 1000) / 1000)
+ }
+ ]
+ });
+ }
+ }
+ }
+ }
+ }, [months, years, props.view, category]);
+ return ;
+};
export default TrendsHabits;
+
+TrendsHabits.propTypes = {
+ data: PropTypes.object,
+ view: PropTypes.string,
+ category: PropTypes.string
+};
diff --git a/client/src/Components/TrendsHabitsSelector.jsx b/client/src/Components/TrendsHabitsSelector.jsx
new file mode 100644
index 0000000..1dc31e2
--- /dev/null
+++ b/client/src/Components/TrendsHabitsSelector.jsx
@@ -0,0 +1,103 @@
+import React from 'react';
+import { makeStyles } from '@material-ui/core/styles';
+import InputLabel from '@material-ui/core/InputLabel';
+import FormControl from '@material-ui/core/FormControl';
+import Select from '@material-ui/core/Select';
+import Radio from '@material-ui/core/Radio';
+import RadioGroup from '@material-ui/core/RadioGroup';
+import FormControlLabel from '@material-ui/core/FormControlLabel';
+import FormLabel from '@material-ui/core/FormLabel';
+import PropTypes from 'prop-types';
+
+const useStyles = makeStyles(theme => ({
+ root: {
+ display: 'flex',
+ flexWrap: 'wrap'
+ },
+ formControl: {
+ margin: theme.spacing(1),
+ minWidth: 120
+ },
+ selectEmpty: {
+ marginTop: theme.spacing(2)
+ },
+ radioformControl: {
+ margin: theme.spacing(3)
+ },
+ group: {
+ margin: theme.spacing(1, 0)
+ }
+}));
+
+export default function HabitsSelector(props) {
+ const classes = useStyles();
+ const [state, setState] = React.useState({
+ category: '',
+ categories: []
+ });
+ const [value, setValue] = React.useState('month');
+
+ const handleChange1 = name => event => {
+ setState({
+ ...state,
+ [name]: event.target.value
+ });
+ };
+
+ const handleChange2 = event => {
+ setValue(event.target.value);
+ };
+
+ React.useEffect(() => {
+ props.setView(value);
+ props.setCategory(state.category);
+ }, [value, state.category]);
+
+ return (
+
+
+ Category
+
+
+
+ Time Period
+
+ }
+ label="Month to Month"
+ />
+ }
+ label="Year to Year"
+ />
+
+
+
+ );
+}
+
+HabitsSelector.propTypes = {
+ data: PropTypes.object,
+ setView: PropTypes.func,
+ setCategory: PropTypes.func
+};
diff --git a/client/src/Components/TrendsOverview.jsx b/client/src/Components/TrendsOverview.jsx
index 77c92d5..de86de6 100644
--- a/client/src/Components/TrendsOverview.jsx
+++ b/client/src/Components/TrendsOverview.jsx
@@ -1,18 +1,55 @@
import React from 'react';
import { Doughnut } from 'react-chartjs-2';
+import PropTypes from 'prop-types';
-// test data for display
-const data = {
- labels: ['Red', 'Green', 'Yellow'],
- datasets: [
- {
- data: [300, 50, 100],
- backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'],
- hoverBackgroundColor: ['#FF6384', '#36A2EB', '#FFCE56']
- }
- ]
-};
+const TrendsOverview = props => {
+ const [labels, setLabels] = React.useState([]);
+ const [data, setData] = React.useState([]);
+ const [transactions, setTransactions] = React.useState([]);
+
+ React.useEffect(() => {
+ const transactions = {};
+ props.data.accountData.accounts.map(account => {
+ if (account.transactions[props.year]) {
+ if (account.transactions[props.year][props.month]) {
+ account.transactions[props.year][props.month].forEach(transaction => {
+ if (transactions[transaction.category]) {
+ transactions[transaction.category] += Number(transaction.amount);
+ } else {
+ transactions[transaction.category] = Number(transaction.amount);
+ }
+ });
+ }
+ }
+ });
+ setTransactions(transactions);
+ }, [props.year, props.month, props.data.accountData.accounts]);
-const TrendsOverview = () => ;
+ React.useEffect(() => {
+ setLabels(Object.keys(transactions));
+ }, [transactions]);
+
+ React.useEffect(() => {
+ setData(labels.map(label => Math.round(transactions[label] * 1000) / 1000));
+ }, [labels, transactions]);
+
+ const userData = {
+ labels,
+ datasets: [
+ {
+ data,
+ backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'],
+ hoverBackgroundColor: ['#FF6384', '#36A2EB', '#FFCE56']
+ }
+ ]
+ };
+ return ;
+};
export default TrendsOverview;
+
+TrendsOverview.propTypes = {
+ data: PropTypes.object,
+ month: PropTypes.string,
+ year: PropTypes.string
+};
diff --git a/client/src/Components/TrendsOverviewSelector.jsx b/client/src/Components/TrendsOverviewSelector.jsx
new file mode 100644
index 0000000..2ee6b1c
--- /dev/null
+++ b/client/src/Components/TrendsOverviewSelector.jsx
@@ -0,0 +1,114 @@
+import React from 'react';
+import { makeStyles } from '@material-ui/core/styles';
+import InputLabel from '@material-ui/core/InputLabel';
+import FormControl from '@material-ui/core/FormControl';
+import Select from '@material-ui/core/Select';
+import PropTypes from 'prop-types';
+
+const useStyles = makeStyles(theme => ({
+ root: {
+ display: 'flex',
+ flexWrap: 'wrap'
+ },
+ formControl: {
+ margin: theme.spacing(1),
+ minWidth: 120
+ },
+ selectEmpty: {
+ marginTop: theme.spacing(2)
+ }
+}));
+const date = new Date();
+const currentMonth = date.getMonth().toString();
+const currentYear = date.getFullYear().toString();
+export default function OverviewSelector(props) {
+ const classes = useStyles();
+ const [state, setState] = React.useState({
+ month: currentMonth,
+ year: currentYear,
+ years: []
+ });
+
+ const handleChange = name => event => {
+ setState({
+ ...state,
+ [name]: event.target.value
+ });
+ };
+
+ const updateYear = () => {
+ let result = {};
+ for (let i = 0; i < props.data.accountData.accounts.length; i++) {
+ for (let obj in props.data.accountData.accounts[i].transactions) {
+ result[obj] = 1;
+ }
+ }
+ return Object.keys(result);
+ };
+
+ React.useEffect(() => {
+ setState({
+ ...state,
+ years: updateYear()
+ });
+ }, []);
+
+ React.useEffect(() => {
+ props.setMonth(state.month);
+ props.setYear(state.year);
+ }, [state.month, state.year]);
+
+ return (
+
+
+ Month
+
+
+
+ Year
+
+
+
+ );
+}
+
+OverviewSelector.propTypes = {
+ data: PropTypes.object,
+ setMonth: PropTypes.func,
+ setYear: PropTypes.func
+};
diff --git a/client/src/Components/TrendsPage.jsx b/client/src/Components/TrendsPage.jsx
index c394eed..abc253e 100644
--- a/client/src/Components/TrendsPage.jsx
+++ b/client/src/Components/TrendsPage.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useCallback } from 'react';
import { makeStyles } from '@material-ui/core/styles';
import PropTypes from 'prop-types';
import Paper from '@material-ui/core/Paper';
@@ -9,6 +9,9 @@ import Box from '@material-ui/core/Box';
import TrendsOverview from './TrendsOverview.jsx';
import TrendsHabits from './TrendsHabits.jsx';
import TrendsComparison from './TrendsComparison.jsx';
+import OverviewSelector from './TrendsOverviewSelector.jsx';
+import HabitsSelector from './TrendsHabitsSelector.jsx';
+import ComparisonSelector from './TrendsComparisonSelector.jsx';
import Loading from './Loading.jsx';
const useStyles = makeStyles({
@@ -50,6 +53,14 @@ function a11yProps(index) {
export default function TrendsPage(props) {
const classes = useStyles();
const [value, setValue] = React.useState(0);
+ const [overviewYear, setOverviewYear] = React.useState('');
+ const [overviewMonth, setOverviewMonth] = React.useState('');
+ const [habitView, setHabitView] = React.useState('month');
+ const [habitCategory, setHabitCategory] = React.useState('');
+ const [compareMonth1, setCompareMonth1] = React.useState('');
+ const [compareMonth2, setCompareMonth2] = React.useState('');
+ const [compareYear1, setCompareYear1] = React.useState('');
+ const [compareYear2, setCompareYear2] = React.useState('');
function handleChange(event, newValue) {
setValue(newValue);
@@ -79,13 +90,40 @@ export default function TrendsPage(props) {
-
+
+
-
+
+
-
+
+
);