diff --git a/src/lib/utils.js b/src/lib/utils.js index 010c2b03..2c51e1a1 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -116,11 +116,24 @@ export function getPrevMonths(n) { return [...Array(n)].map(_i => m.add(1, 'months').format('MMM[\n]YYYY')); } +export function getMonthsBetween(startDate, endDate) { + const dateStart = moment(startDate); + const dateEnd = moment(endDate); + const timeValues = []; + + while (dateEnd > dateStart || dateStart.format('M') === dateEnd.format('M')) { + timeValues.push(dateStart.format('YYYY-MM')); + dateStart.add(1, 'month'); + } + return timeValues; +} + export default { getAllFarmsForKS, getDateOptions, getPrevMonths, getTotalHarvest, updateFarmAndCertification, - getTotalHarvestData + getTotalHarvestData, + getMonthsBetween }; diff --git a/src/screens/shared/dateFilterMenu/DateFilterMenu.js b/src/screens/shared/dateFilterMenu/DateFilterMenu.js index 2dfc9874..e6dc39e6 100644 --- a/src/screens/shared/dateFilterMenu/DateFilterMenu.js +++ b/src/screens/shared/dateFilterMenu/DateFilterMenu.js @@ -1,3 +1,4 @@ +/* eslint-disable no-unused-vars */ import React from 'react'; import { withStyles } from '@material-ui/core/styles'; @@ -37,7 +38,8 @@ class DateFilterMenu extends React.PureComponent { filterBy: null, showDropdown: false, startDate: '', - endDate: '' + endDate: '', + applied: false }; } @@ -61,10 +63,10 @@ class DateFilterMenu extends React.PureComponent { // TO-DO onChange needs to take start and end date, if those are changed if (startDate && endDate) { onChange([startDate, endDate]); + this.setState({ applied: true }); } else { onChange(filterBy); } - this.setState({ anchorEl: null }); }; @@ -97,9 +99,17 @@ class DateFilterMenu extends React.PureComponent { this.setState({ endDate: event.target.value }); }; + filterLabel = (startDate, endDate) => { + const { applied } = this.state; + if (startDate !== '' && endDate !== '' && applied === true) { + return startDate.concat(' to ').concat(endDate); + } + return 'Date Filters'; + }; + render() { const { classes } = this.props; - const { anchorEl, filterBy, showDropdown } = this.state; + const { anchorEl, filterBy, showDropdown, startDate, endDate } = this.state; return (
@@ -111,7 +121,9 @@ class DateFilterMenu extends React.PureComponent { startIcon={} endIcon={} > -

Date Filters

+

+ {this.filterLabel(startDate, endDate)} +

- + {/*

Advanced Options

{showDropdown ? : }
@@ -136,7 +148,7 @@ class DateFilterMenu extends React.PureComponent { value={filterBy} handleClick={this.handleRadioClick} /> - + */}
); diff --git a/src/screens/shared/graphs/Graph.js b/src/screens/shared/graphs/Graph.js index 60b763a5..c2cbf247 100644 --- a/src/screens/shared/graphs/Graph.js +++ b/src/screens/shared/graphs/Graph.js @@ -45,7 +45,7 @@ class Graph extends React.Component { }; } - getGraphProps = (type, farm) => { + getGraphProps = (type, farm, filterBy) => { switch (type) { case 'certification': return { @@ -55,17 +55,17 @@ class Graph extends React.Component { case 'production': return { label: 'Farm Production History', - graph: + graph: }; case 'recentHarvests': return { label: 'Recent Harvests', - graph: + graph: }; case 'topItems': return { label: 'Top 5 Items', - graph: + graph: }; case 'harvestLogs': return { @@ -83,7 +83,8 @@ class Graph extends React.Component { render() { const { classes, type, farm } = this.props; - const { label, graph } = this.getGraphProps(type, farm); + const { filterBy } = this.state; + const { label, graph } = this.getGraphProps(type, farm, filterBy); return (
diff --git a/src/screens/shared/graphs/ProductionGraph.js b/src/screens/shared/graphs/ProductionGraph.js index fe2c9030..cd3d9bac 100644 --- a/src/screens/shared/graphs/ProductionGraph.js +++ b/src/screens/shared/graphs/ProductionGraph.js @@ -13,7 +13,8 @@ import { import { getPrevMonths, getMonthsofYear, - getTotalHarvestData + getTotalHarvestData, + getMonthsBetween } from '@lib/utils'; const fontProps = { @@ -62,12 +63,9 @@ class ProductionGraph extends React.PureComponent { } async componentDidMount() { - // Fetch all the "total harvest" records for the specified farm. + // Fetch all the "total harvest" records in the database. const totalHarvest = await getTotalHarvestData(); - console.log(totalHarvest); - const dateList = []; - const cropsList = []; - const quantitiesList = []; + const dateList = []; const cropsList = []; const quantitiesList = []; for (let h = 0; h < totalHarvest.length; h += 1) { const { created, crops, quantities } = totalHarvest[h]; dateList[h] = created.slice(0, 7); // takes YYYY-MM format @@ -77,7 +75,7 @@ class ProductionGraph extends React.PureComponent { this.setState({ dateList, cropsList, quantitiesList }); } - filterByDate = (dateList, cropsList, quantitiesList) => { + filterByDate = (dateList, cropsList, quantitiesList, filterBy) => { const dict = []; const months = getMonthsofYear(); for (let i = 0; i < dateList.length; i += 1) { @@ -90,9 +88,28 @@ class ProductionGraph extends React.PureComponent { } // Take the recent 9 months and match them up to the data in `dict`, filling in months without production with 0. - const recentDates = getPrevMonths(9); - const recentCrops = ['', '', '', '', '', '', '', '', '']; - const recentQuantities = ['', '', '', '', '', '', '', '', '']; + let recentDates = []; + let recentCrops = []; + let recentQuantities = []; + if (filterBy !== null) { + recentDates = getMonthsBetween(filterBy[0], filterBy[1]); + // Reformatting the dates (2021-03 to Mar\n2021) + for (let i = 0; i < recentDates.length; i += 1) { + const year = recentDates[i].slice(0, 4); + // eslint-disable-next-line radix + const month = months[parseInt(recentDates[i].slice(5, 7)) - 1]; + const dateFormatted = `${String(month)}\n${year}`; + recentDates[i] = dateFormatted; + } + recentCrops = new Array(recentDates.length).fill(''); + recentQuantities = new Array(recentDates.length).fill(''); + // DEFAULT: Take the recent 9 months and match them up to the data in `dict`, filling in months without production with 0. + } else { + recentDates = getPrevMonths(9); + recentCrops = ['', '', '', '', '', '', '', '', '']; + recentQuantities = ['', '', '', '', '', '', '', '', '']; + } + for (let i = 0; i < dict.length; i += 1) { for (let j = 0; j < recentDates.length; j += 1) { if (recentDates[j] === dict[i][0]) { @@ -181,11 +198,6 @@ class ProductionGraph extends React.PureComponent { }; getTopFourItems = dict => { - // Index 0: Oct\n2020 ; Index 1: Nov\n2020 - // 4th: ["N/A", "N/A"] - // 3rd: ["N/A", "N/A"] - // 2nd Highest: ["Pineapple", "Tomato Cherry"] - // Highest: ["Corn", "Tomato Roma"] const level5other = []; const level4 = []; const level3 = []; @@ -202,9 +214,24 @@ class ProductionGraph extends React.PureComponent { return [level1, level2, level3, level4, level5other]; }; - getData = dict => { + getData = (dict, filterBy) => { + let labels = [] + if (filterBy !== null) { + const months = getMonthsofYear(); + labels = getMonthsBetween(filterBy[0], filterBy[1]); + // Reformatting the dates (2021-03 to Mar\n2021) + for (let i = 0; i < labels.length; i += 1) { + const year = labels[i].slice(0, 4); + // eslint-disable-next-line radix + const month = months[parseInt(labels[i].slice(5, 7)) - 1]; + const dateFormatted = `${String(month)}\n${year}`; + labels[i] = dateFormatted; + } + } + else { + labels = getPrevMonths(9); + } // produces data object for each segmenet of stacked bar graph - const labels = getPrevMonths(9); const level5other = []; const level4 = []; const level3 = []; @@ -235,9 +262,14 @@ class ProductionGraph extends React.PureComponent { render() { const { dateList, cropsList, quantitiesList } = this.state; - console.log(dateList, cropsList, quantitiesList); - const lists = this.filterByDate(dateList, cropsList, quantitiesList); - console.log(lists); + const { filterBy } = this.props; + const lists = this.filterByDate( + dateList, + cropsList, + quantitiesList, + filterBy + ); + const productionDict = []; for (let i = 0; i < lists.dateStringList.length; i += 1) { productionDict[i] = [ @@ -248,15 +280,13 @@ class ProductionGraph extends React.PureComponent { ) ]; } - console.log(productionDict); for (let i = 0; i < productionDict.length; i += 1) { productionDict[i][1] = this.sortData( productionDict[i][1].cropsToQuantity ); } - console.log(productionDict); - const data = this.getData(productionDict); + const data = this.getData(productionDict, filterBy); return ( diff --git a/src/screens/shared/graphs/RecentHarvestsGraph.js b/src/screens/shared/graphs/RecentHarvestsGraph.js index 80dc0b17..d49cde4a 100644 --- a/src/screens/shared/graphs/RecentHarvestsGraph.js +++ b/src/screens/shared/graphs/RecentHarvestsGraph.js @@ -1,5 +1,10 @@ import React from 'react'; -import { getPrevMonths, getTotalHarvest, getMonthsofYear } from '@lib/utils'; +import { + getPrevMonths, + getTotalHarvest, + getMonthsofYear, + getMonthsBetween +} from '@lib/utils'; import FarmProfileGraph from './FarmProfileGraph'; class RecentHarvestsGraph extends React.PureComponent { @@ -13,7 +18,6 @@ class RecentHarvestsGraph extends React.PureComponent { async componentDidMount() { const { farm } = this.props; - // Fetch all the "total harvest" records for the specified farm. const totalHarvest = farm.totalHarvestIds === undefined // If there are no harvest logs under the farm ID, then return an empty list. @@ -31,7 +35,7 @@ class RecentHarvestsGraph extends React.PureComponent { this.setState({ dateList, totalList }); } - getData = (dateList, totalList) => { + getData = (dateList, totalList, filterBy) => { // Reformatting the dates (2021-03 to Mar\n2021) const dict = []; const months = getMonthsofYear(); @@ -41,13 +45,31 @@ class RecentHarvestsGraph extends React.PureComponent { const month = months[parseInt(dateList[i].slice(5, 7)) - 1]; const dateFormatted = `${String(month)}\n${year}`; // Creating a dictionary mapping dates to its corresponding total production quantity. + // Note: Each farm only has 1 "total harvest" record per month, so aggregation of total production pounds is not needed. dict[i] = [dateFormatted, totalList[i]]; } - // Take the recent 9 months and match them up to the data in `dict`, filling in months without production with 0. - // Note: Each farm only has 1 "total harvest" record per month, so aggregation of total production pounds is not needed. - const recentDates = getPrevMonths(9); - const recentValues = [0, 0, 0, 0, 0, 0, 0, 0, 0]; + // DURING FILTERING: Parse the selected months + let recentDates = []; + let recentValues = []; + if (filterBy !== null) { + recentDates = getMonthsBetween(filterBy[0], filterBy[1]); + // Reformatting the dates (2021-03 to Mar\n2021) + for (let i = 0; i < recentDates.length; i += 1) { + const year = recentDates[i].slice(0, 4); + // eslint-disable-next-line radix + const month = months[parseInt(recentDates[i].slice(5, 7)) - 1]; + const dateFormatted = `${String(month)}\n${year}`; + recentDates[i] = dateFormatted; + } + recentValues = new Array(recentDates.length).fill(0); + // DEFAULT: Take the recent 9 months and match them up to the data in `dict`, filling in months without production with 0. + } else { + recentDates = getPrevMonths(9); + recentValues = [0, 0, 0, 0, 0, 0, 0, 0, 0]; + } + + // Fills in the empty 0 values with values from the dictionary for (let i = 0; i < dict.length; i += 1) { for (let j = 0; j < recentDates.length; j += 1) { if (recentDates[j] === dict[i][0]) { @@ -64,8 +86,9 @@ class RecentHarvestsGraph extends React.PureComponent { }; render() { + const { filterBy } = this.props; const { dateList, totalList } = this.state; - const { labels, values } = this.getData(dateList, totalList); + const { labels, values } = this.getData(dateList, totalList, filterBy); return ( { + const dict = []; + const months = getMonthsofYear(); + for (let i = 0; i < dateList.length; i += 1) { + const year = dateList[i].slice(0, 4); + // eslint-disable-next-line radix + const month = months[parseInt(dateList[i].slice(5, 7)) - 1]; + const dateFormatted = `${String(month)}\n${year}`; + // Creating a dictionary mapping dates to its corresponding total production quantity. + dict[i] = [dateFormatted, cropsList[i], quantitiesList[i]]; + } + + // Take the recent 9 months and match them up to the data in `dict`, filling in months without production with 0. + let recentDates = []; + let recentCrops = []; + let recentQuantities = []; + if (filterBy !== null) { + recentDates = getMonthsBetween(filterBy[0], filterBy[1]); + // Reformatting the dates (2021-03 to Mar\n2021) + for (let i = 0; i < recentDates.length; i += 1) { + const year = recentDates[i].slice(0, 4); + // eslint-disable-next-line radix + const month = months[parseInt(recentDates[i].slice(5, 7)) - 1]; + const dateFormatted = `${String(month)}\n${year}`; + recentDates[i] = dateFormatted; } - cropsStr += crops; - quantitiesStr += quantities; + recentCrops = new Array(recentDates.length).fill(''); + recentQuantities = new Array(recentDates.length).fill(''); + // DEFAULT: Take the recent 9 months and match them up to the data in `dict`, filling in months without production with 0. + } else { + recentDates = getPrevMonths(9); + recentCrops = ['', '', '', '', '', '', '', '', '']; + recentQuantities = ['', '', '', '', '', '', '', '', '']; + } + + for (let i = 0; i < dict.length; i += 1) { + for (let j = 0; j < recentDates.length; j += 1) { + if (recentDates[j] === dict[i][0]) { + if (recentCrops[j] === '' && recentQuantities[j] === '') { + // eslint-disable-next-line prefer-destructuring + recentCrops[j] = dict[i][1]; + // eslint-disable-next-line prefer-destructuring + recentQuantities[j] = dict[i][2]; + } else { + // eslint-disable-next-line prefer-destructuring + recentCrops[j] += ', '.concat(dict[i][1]); + // eslint-disable-next-line prefer-destructuring + recentQuantities[j] += ', '.concat(dict[i][2]); + } + } + } + } + + return { + dateStringList: recentDates, + cropsStringList: recentCrops, + quantitiesStringList: recentQuantities + }; + }; + + convertToString = (cropsStringList, quantitiesStringList) => { + let cropsString = ""; let quantitiesString = ""; + for (let i = 0; i < cropsStringList.length; i += 1) { + if (cropsStringList[i] !== "") { + if (cropsString === "") { + cropsString = cropsString.concat(cropsStringList[i]) + quantitiesString = quantitiesString.concat(quantitiesStringList[i]) + } else { + cropsString = cropsString.concat(", ").concat(cropsStringList[i]) + quantitiesString = quantitiesString.concat(", ").concat(quantitiesStringList[i]) + } + } + } + + return { + cropsString, quantitiesString } - const quantitiesFloats = - quantitiesStr === '' - ? [] - : quantitiesStr.match(/\d+(?:\.\d+)?/g).map(Number); // Converts string to float for the quantities - this.setState({ cropsStr, quantitiesFloats }); } // Reformulates data into a dictionary mapping every unique crop and its totaled quantity. - formulateData = (cropsStr, quantitiesFloats) => { - const cropsSplit = cropsStr.split(','); // Splitting string of crops into a list (by comma separation) - let dict = []; + formulateData = (crops, quantities) => { + const quantitiesFloats = + quantities === '' ? [] : quantities.match(/\d+(?:\.\d+)?/g).map(Number); // Converts string to float for the quantities + const cropsSplit = crops.split(','); // Splitting string of crops into a list (by comma separation) + let dict = []; for (let i = 0; i < cropsSplit.length; i += 1) { cropsSplit[i] = cropsSplit[i].replace(/^\s+|\s+$/g, ''); // Trims starting and trailing white spaces if (cropsSplit.slice(0, i).includes(cropsSplit[i])) { @@ -59,7 +131,7 @@ class TopItemsGraph extends React.PureComponent { } return { - cropsToQuantity: dict + dict }; }; @@ -67,7 +139,6 @@ class TopItemsGraph extends React.PureComponent { sortData = cropsToQuantity => { let dict = cropsToQuantity; dict = dict.sort((a, b) => b[1] - a[1]); - console.log(dict); const cropsSorted = []; const quantitiesSorted = []; @@ -99,17 +170,24 @@ class TopItemsGraph extends React.PureComponent { }; render() { - const { cropsStr, quantitiesFloats } = this.state; - const { cropsToQuantity } = this.formulateData(cropsStr, quantitiesFloats); - console.log(cropsToQuantity); - console.log(typeof cropsToQuantity); - const { labels, values } = this.sortData(cropsToQuantity); + const { dateList, cropsList, quantitiesList } = this.state; + const { filterBy } = this.props; + const lists = this.filterByDate( + dateList, + cropsList, + quantitiesList, + filterBy + ); + + const {cropsString, quantitiesString} = this.convertToString(lists.cropsStringList, lists.quantitiesStringList) + const productionDict = this.formulateData(cropsString, quantitiesString).dict + const { labels, values } = this.sortData(productionDict); return ( ); }