From 2b96bb3d523647e591183bade8afe578a55721bd Mon Sep 17 00:00:00 2001 From: Crazypkr1099 Date: Mon, 10 Jun 2024 07:41:45 -0400 Subject: [PATCH] Added Year comparison feature. (#2806) * Added Year comparsion feature. Also fixed bug with greater than 28 days. * Removed comments and console.logs * Create 2806.md * Cleaned up code * Hide's graph if no data, and hides average, last month or last year if no data. * Apply suggestions from code review Co-authored-by: Neil <55785687+carkom@users.noreply.github.com> * Fixed spent MTD and last MTD. Added in all suggestions from carkom. * Update 2806.md * Added changes required by carkom #2 * Couple more fixes, only show graph if have data for last month (as requested by carkom) * Removed console.log that was mistakenly added. * removed useEffect * Add files via upload * Remove async function * lint fix * fixed carkom requests & added in fix for YAxis issues * Fixed couple of mistakes. Removed Y Axis fix (new PR will be created) * Cleanup code * Fix mode buttons * Removed console.log... * Update showAverage Logic * Update switch logic default should be default for everyone other part of the graph. * Add Math.abs * lint fix --------- Co-authored-by: Neil <55785687+carkom@users.noreply.github.com> --- .../reports/graphs/SpendingGraph.tsx | 40 ++++- .../components/reports/reports/Spending.tsx | 166 +++++++++++------- .../reports/reports/SpendingCard.tsx | 14 +- .../spreadsheets/spending-spreadsheet.ts | 29 ++- .../loot-core/src/types/models/reports.d.ts | 1 + upcoming-release-notes/2806.md | 6 + 6 files changed, 172 insertions(+), 84 deletions(-) create mode 100644 upcoming-release-notes/2806.md diff --git a/packages/desktop-client/src/components/reports/graphs/SpendingGraph.tsx b/packages/desktop-client/src/components/reports/graphs/SpendingGraph.tsx index 2aadf407dcf..60b2b4f78ae 100644 --- a/packages/desktop-client/src/components/reports/graphs/SpendingGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/SpendingGraph.tsx @@ -45,6 +45,7 @@ type CustomTooltipProps = { payload?: PayloadItem[]; balanceTypeOp?: string; thisMonth?: string; + lastYear?: string; selection?: string; }; @@ -53,6 +54,7 @@ const CustomTooltip = ({ payload, balanceTypeOp, thisMonth, + lastYear, selection, }: CustomTooltipProps) => { if (active && payload && payload.length) { @@ -82,21 +84,27 @@ const CustomTooltip = ({
- {payload[0].payload.months[thisMonth].cumulative && ( + {payload[0].payload.months[thisMonth].cumulative ? ( - )} + ) : null} {['cumulative'].includes(balanceTypeOp) && ( )} - {payload[0].payload.months[thisMonth].cumulative && ( + {payload[0].payload.months[thisMonth].cumulative ? ( - )} + ) : null}
@@ -129,7 +137,20 @@ export function SpendingGraph({ const balanceTypeOp = 'cumulative'; const thisMonth = monthUtils.currentMonth(); const lastMonth = monthUtils.subMonths(monthUtils.currentMonth(), 1); - const selection = mode.toLowerCase() === 'average' ? 'average' : lastMonth; + const lastYear = monthUtils.prevYear(monthUtils.currentMonth()); + let selection; + switch (mode) { + case 'Average': + selection = 'average'; + break; + case 'lastYear': + selection = lastYear; + break; + default: + selection = lastMonth; + break; + } + const thisMonthMax = data.intervalData.reduce((a, b) => a.months[thisMonth][balanceTypeOp] < b.months[thisMonth][balanceTypeOp] ? a @@ -139,11 +160,11 @@ export function SpendingGraph({ selection === 'average' ? data.intervalData[27].average : data.intervalData.reduce((a, b) => - a.months[lastMonth][balanceTypeOp] < - b.months[lastMonth][balanceTypeOp] + a.months[selection][balanceTypeOp] < + b.months[selection][balanceTypeOp] ? a : b, - ).months[lastMonth][balanceTypeOp]; + ).months[selection][balanceTypeOp]; const maxYAxis = selectionMax > thisMonthMax; const dataMax = Math.max( ...data.intervalData.map(i => i.months[thisMonth].cumulative), @@ -233,6 +254,7 @@ export function SpendingGraph({ } diff --git a/packages/desktop-client/src/components/reports/reports/Spending.tsx b/packages/desktop-client/src/components/reports/reports/Spending.tsx index 5b6dc4aee24..5f54faaaf78 100644 --- a/packages/desktop-client/src/components/reports/reports/Spending.tsx +++ b/packages/desktop-client/src/components/reports/reports/Spending.tsx @@ -38,7 +38,7 @@ export function Spending() { } = useFilters(); const [dataCheck, setDataCheck] = useState(false); - const [mode, setMode] = useState('Last month'); + const [mode, setMode] = useState('lastMonth'); const getGraphData = useMemo(() => { setDataCheck(false); @@ -57,15 +57,21 @@ export function Spending() { if (!data) { return null; } + const showAverage = - data.intervalData[27].months[ - monthUtils.subMonths(monthUtils.currentDay(), 3) - ].daily !== 0; + Math.abs( + data.intervalData[27].months[ + monthUtils.subMonths(monthUtils.currentDay(), 3) + ].cumulative, + ) > 0; + const todayDay = monthUtils.getDay(monthUtils.currentDay()) - 1 >= 28 ? 27 : monthUtils.getDay(monthUtils.currentDay()) - 1; + const showLastYear = Math.abs(data.intervalData[27].lastYear) > 0; + const showLastMonth = Math.abs(data.intervalData[27].lastMonth) > 0; return ( - Spent MTD:} - right={ - - - {amountToCurrency( - Math.abs(data.intervalData[todayDay].thisMonth), - )} - - - } - /> - Spent Last MTD:} - right={ - - - {amountToCurrency( - Math.abs(data.intervalData[todayDay].lastMonth), - )} - - - } - /> + {showLastMonth && ( + + Spent MTD:} + right={ + + + {amountToCurrency( + Math.abs(data.intervalData[todayDay].thisMonth), + )} + + + } + /> + Spent Last MTD:} + right={ + + + {amountToCurrency( + Math.abs(data.intervalData[todayDay].lastMonth), + )} + + + } + /> + + )} {showAverage && ( Spent Average MTD:} @@ -211,46 +227,66 @@ export function Spending() { )} - - - Compare this month to: - - setMode('Last month')} - > - Last month - - {showAverage && ( - setMode('Average')} + {!showLastMonth ? ( + +

Additional data required to generate graph

+ + Currently, there is insufficient data to display any + information regarding your spending. Please input + transactions from last month to enable graph visualization. + +
+ ) : ( + <> + - Average -
- )} -
+ + Compare this month to: + + setMode('lastMonth')} + > + Last month + + {showLastYear && ( + setMode('lastYear')} + > + Last year + + )} + {showAverage && ( + setMode('Average')} + > + Average + + )} + - {dataCheck ? ( - - ) : ( - + {dataCheck ? ( + + ) : ( + + )} + )} - {showAverage && ( diff --git a/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx b/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx index 8a11dd3428c..d999494ed9b 100644 --- a/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx +++ b/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx @@ -36,6 +36,7 @@ export function SpendingCard() { data && data.intervalData[todayDay].lastMonth - data.intervalData[todayDay].thisMonth; + const showLastMonth = data && Math.abs(data.intervalData[27].lastMonth) > 0; return ( @@ -57,7 +58,7 @@ export function SpendingCard() { end={monthUtils.currentMonth()} /> - {data && ( + {data && showLastMonth && ( )} - - {data ? ( + {!showLastMonth ? ( + +

+ Additional data required to generate graph +

+
+ ) : data ? ( ) : ( - + )} diff --git a/packages/desktop-client/src/components/reports/spreadsheets/spending-spreadsheet.ts b/packages/desktop-client/src/components/reports/spreadsheets/spending-spreadsheet.ts index 79981b47a77..205a1b160b3 100644 --- a/packages/desktop-client/src/components/reports/spreadsheets/spending-spreadsheet.ts +++ b/packages/desktop-client/src/components/reports/spreadsheets/spending-spreadsheet.ts @@ -1,5 +1,4 @@ // @ts-strict-ignore - import keyBy from 'lodash/keyBy'; import { runQuery } from 'loot-core/src/client/query-helpers'; @@ -35,6 +34,11 @@ export function createSpendingSpreadsheet({ setDataCheck, }: createSpendingSpreadsheetProps) { const [startDate, endDate] = getSpecificRange(3, null, 'Months'); + const [lastYearStartDate, lastYearEndDate] = getSpecificRange( + 12, + 0, + 'Months', + ); const interval = 'Daily'; return async ( @@ -50,7 +54,7 @@ export function createSpendingSpreadsheet({ runQuery( makeQuery( 'assets', - startDate, + lastYearStartDate, endDate, interval, categories.list, @@ -61,7 +65,7 @@ export function createSpendingSpreadsheet({ runQuery( makeQuery( 'debts', - startDate, + lastYearStartDate, endDate, interval, categories.list, @@ -72,6 +76,9 @@ export function createSpendingSpreadsheet({ ]); const intervals = monthUtils.dayRangeInclusive(startDate, endDate); + intervals.push( + ...monthUtils.dayRangeInclusive(lastYearStartDate, lastYearEndDate), + ); const days = [...Array(29).keys()] .filter(f => f > 0) .map(n => n.toString().padStart(2, '0')); @@ -85,6 +92,12 @@ export function createSpendingSpreadsheet({ return { month, perMonthAssets: 0, perMonthDebts: 0 }; }); + months.unshift({ + month: monthUtils.prevYear(monthUtils.currentMonth()), + perMonthAssets: 0, + perMonthDebts: 0, + }); + const intervalData = days.map(day => { let averageSum = 0; let monthCount = 0; @@ -126,7 +139,10 @@ export function createSpendingSpreadsheet({ } return null; }); - if (month.month !== monthUtils.currentMonth()) { + if ( + month.month !== monthUtils.currentMonth() && + month.month !== monthUtils.prevYear(monthUtils.currentMonth()) + ) { averageSum += cumulativeAssets + cumulativeDebts; monthCount += 1; } @@ -165,8 +181,9 @@ export function createSpendingSpreadsheet({ months: indexedData, day, average: integerToAmount(averageSum) / monthCount, - thisMonth: dayData[3].cumulative, - lastMonth: dayData[2].cumulative, + thisMonth: dayData[4].cumulative, + lastMonth: dayData[3].cumulative, + lastYear: dayData[0].cumulative, }; }); diff --git a/packages/loot-core/src/types/models/reports.d.ts b/packages/loot-core/src/types/models/reports.d.ts index eccc1c79f99..42ed96875b3 100644 --- a/packages/loot-core/src/types/models/reports.d.ts +++ b/packages/loot-core/src/types/models/reports.d.ts @@ -49,6 +49,7 @@ export interface SpendingEntity { average: number; thisMonth: number; lastMonth: number; + lastYear: number; }[]; startDate?: string; endDate?: string; diff --git a/upcoming-release-notes/2806.md b/upcoming-release-notes/2806.md new file mode 100644 index 00000000000..bfeb7b8b1d5 --- /dev/null +++ b/upcoming-release-notes/2806.md @@ -0,0 +1,6 @@ +--- +category: Features +authors: [Crazypkr1099] +--- + +Add Year Spending Comparison Feature