From cceda0390551e9b1a658a10927450e09eec468bd Mon Sep 17 00:00:00 2001
From: Neil <55785687+carkom@users.noreply.github.com>
Date: Thu, 25 Jul 2024 09:35:44 +0100
Subject: [PATCH] Spending Report: add save button (#3112)

* add save button

* notes

* rerun checks

* add time

* tooltips

* change entity to string

* lint fix

* adjust defaults

* lint
---
 .../src/components/reports/ReportSidebar.tsx  | 15 ++++-
 .../components/reports/reports/Spending.tsx   | 58 ++++++++++++++++++-
 .../reports/reports/SpendingCard.tsx          | 10 +++-
 packages/loot-core/src/types/prefs.d.ts       |  2 +
 upcoming-release-notes/3112.md                |  6 ++
 5 files changed, 86 insertions(+), 5 deletions(-)
 create mode 100644 upcoming-release-notes/3112.md

diff --git a/packages/desktop-client/src/components/reports/ReportSidebar.tsx b/packages/desktop-client/src/components/reports/ReportSidebar.tsx
index 230bc01a6..5c9971430 100644
--- a/packages/desktop-client/src/components/reports/ReportSidebar.tsx
+++ b/packages/desktop-client/src/components/reports/ReportSidebar.tsx
@@ -6,12 +6,14 @@ import { type CategoryGroupEntity } from 'loot-core/types/models/category-group'
 import { type CustomReportEntity } from 'loot-core/types/models/reports';
 import { type LocalPrefs } from 'loot-core/types/prefs';
 
+import { styles } from '../../style/styles';
 import { theme } from '../../style/theme';
 import { Button } from '../common/Button';
 import { Menu } from '../common/Menu';
 import { Popover } from '../common/Popover';
 import { Select } from '../common/Select';
 import { Text } from '../common/Text';
+import { Tooltip } from '../common/Tooltip';
 import { View } from '../common/View';
 
 import { CategorySelector } from './CategorySelector';
@@ -437,7 +439,18 @@ export function ReportSidebar({
             />
             {!disabledList.currentInterval.get(customReportItems.dateRange) &&
               customReportItems.includeCurrentInterval && (
-                <Text style={{ marginLeft: 10 }}>+1</Text>
+                <Tooltip
+                  placement="bottom start"
+                  content={<Text>Current month</Text>}
+                  style={{
+                    ...styles.tooltip,
+                    lineHeight: 1.5,
+                    padding: '6px 10px',
+                    marginTop: 5,
+                  }}
+                >
+                  <Text style={{ marginLeft: 10 }}>+1</Text>
+                </Tooltip>
               )}
           </View>
         ) : (
diff --git a/packages/desktop-client/src/components/reports/reports/Spending.tsx b/packages/desktop-client/src/components/reports/reports/Spending.tsx
index bfecccbd1..0800df9e3 100644
--- a/packages/desktop-client/src/components/reports/reports/Spending.tsx
+++ b/packages/desktop-client/src/components/reports/reports/Spending.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useMemo } from 'react';
+import React, { useState, useMemo, useEffect } from 'react';
 
 import * as monthUtils from 'loot-core/src/shared/months';
 import { amountToCurrency } from 'loot-core/src/shared/util';
@@ -6,13 +6,16 @@ import { type RuleConditionEntity } from 'loot-core/types/models/rule';
 
 import { useCategories } from '../../../hooks/useCategories';
 import { useFilters } from '../../../hooks/useFilters';
+import { useLocalPref } from '../../../hooks/useLocalPref';
 import { useNavigate } from '../../../hooks/useNavigate';
 import { useResponsive } from '../../../ResponsiveProvider';
 import { theme, styles } from '../../../style';
 import { AlignedText } from '../../common/AlignedText';
 import { Block } from '../../common/Block';
+import { Button } from '../../common/Button';
 import { Paragraph } from '../../common/Paragraph';
 import { Text } from '../../common/Text';
+import { Tooltip } from '../../common/Tooltip';
 import { View } from '../../common/View';
 import { AppliedFilters } from '../../filters/AppliedFilters';
 import { FilterButton } from '../../filters/FiltersMenu';
@@ -37,8 +40,28 @@ export function Spending() {
     onConditionsOpChange,
   } = useFilters<RuleConditionEntity>();
 
+  const [spendingReportFilter = '', setSpendingReportFilter] = useLocalPref(
+    'spendingReportFilter',
+  );
+  const [spendingReportTime = 'lastMonth', setSpendingReportTime] =
+    useLocalPref('spendingReportTime');
+
   const [dataCheck, setDataCheck] = useState(false);
-  const [mode, setMode] = useState('lastMonth');
+  const [mode, setMode] = useState(spendingReportTime);
+
+  const parseFilter = spendingReportFilter && JSON.parse(spendingReportFilter);
+  const filterSaved =
+    JSON.stringify(parseFilter.conditions) === JSON.stringify(conditions) &&
+    parseFilter.conditionsOp === conditionsOp &&
+    spendingReportTime === mode;
+
+  useEffect(() => {
+    const checkFilter =
+      spendingReportFilter && JSON.parse(spendingReportFilter);
+    if (checkFilter.conditions) {
+      onApplyFilter(checkFilter);
+    }
+  }, [onApplyFilter, spendingReportFilter]);
 
   const getGraphData = useMemo(() => {
     setDataCheck(false);
@@ -58,6 +81,16 @@ export function Spending() {
     return null;
   }
 
+  const saveFilter = () => {
+    setSpendingReportFilter(
+      JSON.stringify({
+        conditionsOp,
+        conditions,
+      }),
+    );
+    setSpendingReportTime(mode);
+  };
+
   const showAverage =
     Math.abs(
       data.intervalData[27].months[
@@ -108,6 +141,27 @@ export function Spending() {
                 hover={false}
                 exclude={['date']}
               />
+              <Tooltip
+                placement="bottom start"
+                content={<Text>Save compare and filter options</Text>}
+                style={{
+                  ...styles.tooltip,
+                  lineHeight: 1.5,
+                  padding: '6px 10px',
+                  marginLeft: 10,
+                }}
+              >
+                <Button
+                  type="primary"
+                  style={{
+                    marginLeft: 10,
+                  }}
+                  onClick={saveFilter}
+                  disabled={filterSaved ? true : false}
+                >
+                  {filterSaved ? 'Saved' : 'Save'}
+                </Button>
+              </Tooltip>
               <View style={{ flex: 1 }} />
             </View>
           )}
diff --git a/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx b/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx
index 2796261d1..57bbf6ad1 100644
--- a/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx
+++ b/packages/desktop-client/src/components/reports/reports/SpendingCard.tsx
@@ -4,6 +4,7 @@ import * as monthUtils from 'loot-core/src/shared/months';
 import { amountToCurrency } from 'loot-core/src/shared/util';
 
 import { useCategories } from '../../../hooks/useCategories';
+import { useLocalPref } from '../../../hooks/useLocalPref';
 import { styles } from '../../../style/styles';
 import { theme } from '../../../style/theme';
 import { Block } from '../../common/Block';
@@ -20,12 +21,17 @@ export function SpendingCard() {
   const categories = useCategories();
 
   const [isCardHovered, setIsCardHovered] = useState(false);
+  const [spendingReportFilter = ''] = useLocalPref('spendingReportFilter');
+  const [spendingReportTime = 'lastMonth'] = useLocalPref('spendingReportTime');
 
+  const parseFilter = spendingReportFilter && JSON.parse(spendingReportFilter);
   const getGraphData = useMemo(() => {
     return createSpendingSpreadsheet({
       categories,
+      conditions: parseFilter.conditions,
+      conditionsOp: parseFilter.conditionsOp,
     });
-  }, [categories]);
+  }, [categories, parseFilter]);
 
   const data = useReport('default', getGraphData);
   const todayDay =
@@ -92,7 +98,7 @@ export function SpendingCard() {
             style={{ flex: 1 }}
             compact={true}
             data={data}
-            mode="lastMonth"
+            mode={spendingReportTime}
           />
         ) : (
           <LoadingIndicator message="Loading report..." />
diff --git a/packages/loot-core/src/types/prefs.d.ts b/packages/loot-core/src/types/prefs.d.ts
index a8a1dbfca..82cd445a0 100644
--- a/packages/loot-core/src/types/prefs.d.ts
+++ b/packages/loot-core/src/types/prefs.d.ts
@@ -50,6 +50,8 @@ export type LocalPrefs = Partial<
     reportsViewLegend: boolean;
     reportsViewSummary: boolean;
     reportsViewLabel: boolean;
+    spendingReportFilter: string;
+    spendingReportTime: string;
     sidebarWidth: number;
     'mobile.showSpentColumn': boolean;
   } & Record<`flags.${FeatureFlag}`, boolean>
diff --git a/upcoming-release-notes/3112.md b/upcoming-release-notes/3112.md
new file mode 100644
index 000000000..88fa4cdaa
--- /dev/null
+++ b/upcoming-release-notes/3112.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [carkom]
+---
+
+Add a save button to Spending report so you can keep filter settings between sessions
-- 
GitLab