From 9bfbf229db31b97848d9d8e2a80f98de6f411857 Mon Sep 17 00:00:00 2001
From: Joel Jeremy Marquez <joeljeremy.marquez@gmail.com>
Date: Thu, 3 Aug 2023 14:14:23 -0700
Subject: [PATCH] Reports privacy filter (#1447)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

<!-- Thank you for submitting a pull request! Make sure to follow the
instructions to write release notes for your PR — it should only take a
minute or two:
https://github.com/actualbudget/docs#writing-good-release-notes -->

Addresses
https://github.com/actualbudget/actual/issues/1360#issuecomment-1646600087
---
 .../src/components/reports/CashFlow.js        | 15 ++--
 .../src/components/reports/NetWorth.js        |  9 ++-
 .../src/components/reports/Overview.js        | 70 +++++++++++++------
 upcoming-release-notes/1447.md                |  6 ++
 4 files changed, 74 insertions(+), 26 deletions(-)
 create mode 100644 upcoming-release-notes/1447.md

diff --git a/packages/desktop-client/src/components/reports/CashFlow.js b/packages/desktop-client/src/components/reports/CashFlow.js
index b2ed9fc03..662dc2810 100644
--- a/packages/desktop-client/src/components/reports/CashFlow.js
+++ b/packages/desktop-client/src/components/reports/CashFlow.js
@@ -13,6 +13,7 @@ import Block from '../common/Block';
 import Paragraph from '../common/Paragraph';
 import Text from '../common/Text';
 import View from '../common/View';
+import PrivacyFilter from '../PrivacyFilter';
 
 import Change from './Change';
 import { cashFlowByDate } from './graphs/cash-flow-spreadsheet';
@@ -132,7 +133,7 @@ function CashFlow() {
             left={<Block>Income:</Block>}
             right={
               <Text style={{ fontWeight: 600 }}>
-                {integerToCurrency(totalIncome)}
+                <PrivacyFilter>{integerToCurrency(totalIncome)}</PrivacyFilter>
               </Text>
             }
           />
@@ -142,7 +143,9 @@ function CashFlow() {
             left={<Block>Expenses:</Block>}
             right={
               <Text style={{ fontWeight: 600 }}>
-                {integerToCurrency(totalExpenses)}
+                <PrivacyFilter>
+                  {integerToCurrency(totalExpenses)}
+                </PrivacyFilter>
               </Text>
             }
           />
@@ -152,12 +155,16 @@ function CashFlow() {
             left={<Block>Transfers:</Block>}
             right={
               <Text style={{ fontWeight: 600 }}>
-                {integerToCurrency(totalTransfers)}
+                <PrivacyFilter>
+                  {integerToCurrency(totalTransfers)}
+                </PrivacyFilter>
               </Text>
             }
           />
           <Text style={{ fontWeight: 600 }}>
-            <Change amount={totalIncome + totalExpenses + totalTransfers} />
+            <PrivacyFilter>
+              <Change amount={totalIncome + totalExpenses + totalTransfers} />
+            </PrivacyFilter>
           </Text>
         </View>
 
diff --git a/packages/desktop-client/src/components/reports/NetWorth.js b/packages/desktop-client/src/components/reports/NetWorth.js
index b1cb62127..8988cff78 100644
--- a/packages/desktop-client/src/components/reports/NetWorth.js
+++ b/packages/desktop-client/src/components/reports/NetWorth.js
@@ -11,6 +11,7 @@ import useFilters from '../../hooks/useFilters';
 import { styles } from '../../style';
 import Paragraph from '../common/Paragraph';
 import View from '../common/View';
+import PrivacyFilter from '../PrivacyFilter';
 
 import Change from './Change';
 import netWorthSpreadsheet from './graphs/net-worth-spreadsheet';
@@ -117,9 +118,13 @@ export default function NetWorth() {
           <View
             style={[styles.largeText, { fontWeight: 400, marginBottom: 5 }]}
           >
-            {integerToCurrency(data.netWorth)}
+            <PrivacyFilter blurIntensity={5}>
+              {integerToCurrency(data.netWorth)}
+            </PrivacyFilter>
           </View>
-          <Change amount={data.totalChange} />
+          <PrivacyFilter>
+            <Change amount={data.totalChange} />
+          </PrivacyFilter>
         </View>
 
         <NetWorthGraph start={start} end={end} graphData={data.graphData} />
diff --git a/packages/desktop-client/src/components/reports/Overview.js b/packages/desktop-client/src/components/reports/Overview.js
index 7b01ee811..b4e4a7ed8 100644
--- a/packages/desktop-client/src/components/reports/Overview.js
+++ b/packages/desktop-client/src/components/reports/Overview.js
@@ -1,4 +1,4 @@
-import React, { useMemo } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
 import { useSelector } from 'react-redux';
 
 import { VictoryBar, VictoryGroup, VictoryVoronoiContainer } from 'victory';
@@ -10,6 +10,7 @@ import { colors, styles } from '../../style';
 import AnchorLink from '../common/AnchorLink';
 import Block from '../common/Block';
 import View from '../common/View';
+import PrivacyFilter from '../PrivacyFilter';
 
 import Change from './Change';
 import theme from './chart-theme';
@@ -61,6 +62,9 @@ function Card({ flex, to, style, children }) {
 function NetWorthCard({ accounts }) {
   const end = monthUtils.currentMonth();
   const start = monthUtils.subMonths(end, 5);
+  const [isCardHovered, setIsCardHovered] = useState(false);
+  const onCardHover = useCallback(() => setIsCardHovered(true));
+  const onCardHoverEnd = useCallback(() => setIsCardHovered(false));
 
   const params = useMemo(
     () => netWorthSpreadsheet(start, end, accounts),
@@ -74,7 +78,11 @@ function NetWorthCard({ accounts }) {
 
   return (
     <Card flex={2} to="/reports/net-worth">
-      <View style={{ flex: 1 }}>
+      <View
+        style={{ flex: 1 }}
+        onPointerEnter={onCardHover}
+        onPointerLeave={onCardHoverEnd}
+      >
         <View style={{ flexDirection: 'row', padding: 20 }}>
           <View style={{ flex: 1 }}>
             <Block
@@ -89,12 +97,16 @@ function NetWorthCard({ accounts }) {
             <Block
               style={[styles.mediumText, { fontWeight: 500, marginBottom: 5 }]}
             >
-              {integerToCurrency(data.netWorth)}
+              <PrivacyFilter activationFilters={[!isCardHovered]}>
+                {integerToCurrency(data.netWorth)}
+              </PrivacyFilter>
             </Block>
-            <Change
-              amount={data.totalChange}
-              style={{ color: colors.n6, fontWeight: 300 }}
-            />
+            <PrivacyFilter activationFilters={[!isCardHovered]}>
+              <Change
+                amount={data.totalChange}
+                style={{ color: colors.n6, fontWeight: 300 }}
+              />
+            </PrivacyFilter>
           </View>
         </View>
 
@@ -116,6 +128,10 @@ function CashFlowCard() {
 
   const params = useMemo(() => simpleCashFlow(start, end), [start, end]);
   const data = useReport('cash_flow_simple', params);
+  const [isCardHovered, setIsCardHovered] = useState(false);
+  const onCardHover = useCallback(() => setIsCardHovered(true));
+  const onCardHoverEnd = useCallback(() => setIsCardHovered(false));
+
   if (!data) {
     return null;
   }
@@ -126,7 +142,11 @@ function CashFlowCard() {
 
   return (
     <Card flex={1} to="/reports/cash-flow">
-      <View style={{ flex: 1 }}>
+      <View
+        style={{ flex: 1 }}
+        onPointerEnter={onCardHover}
+        onPointerLeave={onCardHoverEnd}
+      >
         <View style={{ flexDirection: 'row', padding: 20 }}>
           <View style={{ flex: 1 }}>
             <Block
@@ -138,10 +158,12 @@ function CashFlowCard() {
             <DateRange start={start} end={end} />
           </View>
           <View style={{ textAlign: 'right' }}>
-            <Change
-              amount={income - expense}
-              style={{ color: colors.n6, fontWeight: 300 }}
-            />
+            <PrivacyFilter activationFilters={[!isCardHovered]}>
+              <Change
+                amount={income - expense}
+                style={{ color: colors.n6, fontWeight: 300 }}
+              />
+            </PrivacyFilter>
           </View>
         </View>
 
@@ -185,10 +207,14 @@ function CashFlowCard() {
                     x: 30,
                     y: Math.max(income, 5),
                     premadeLabel: (
-                      <div style={{ textAlign: 'right' }}>
-                        <div>Income</div>
-                        <div>{integerToCurrency(income)}</div>
-                      </div>
+                      <View style={{ textAlign: 'right' }}>
+                        Income
+                        <View>
+                          <PrivacyFilter activationFilters={[!isCardHovered]}>
+                            {integerToCurrency(income)}
+                          </PrivacyFilter>
+                        </View>
+                      </View>
                     ),
                     labelPosition: 'left',
                   },
@@ -202,10 +228,14 @@ function CashFlowCard() {
                     x: 60,
                     y: Math.max(expense, 5),
                     premadeLabel: (
-                      <div>
-                        <div>Expenses</div>
-                        <div>{integerToCurrency(expense)}</div>
-                      </div>
+                      <View>
+                        Expenses
+                        <View>
+                          <PrivacyFilter activationFilters={[!isCardHovered]}>
+                            {integerToCurrency(expense)}
+                          </PrivacyFilter>
+                        </View>
+                      </View>
                     ),
                     labelPosition: 'right',
                     fill: theme.colors.red,
diff --git a/upcoming-release-notes/1447.md b/upcoming-release-notes/1447.md
new file mode 100644
index 000000000..fc32a33b0
--- /dev/null
+++ b/upcoming-release-notes/1447.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [joel-jeremy]
+---
+
+Reports privacy filter
-- 
GitLab