From b192ad955ed222d9aa388fe36557b39868029db4 Mon Sep 17 00:00:00 2001
From: Neil <55785687+carkom@users.noreply.github.com>
Date: Thu, 13 Jun 2024 16:45:57 +0100
Subject: [PATCH] Custom Reports: fix card menus regression (#2878)

* fix menus

* notes
---
 .../reports/reports/CustomReportListCards.tsx | 133 +++---------------
 .../reports/reports/ListCardsMenu.tsx         |  30 ++++
 .../reports/reports/ListCardsPopover.tsx      | 116 +++++++++++++++
 upcoming-release-notes/2878.md                |   6 +
 4 files changed, 169 insertions(+), 116 deletions(-)
 create mode 100644 packages/desktop-client/src/components/reports/reports/ListCardsMenu.tsx
 create mode 100644 packages/desktop-client/src/components/reports/reports/ListCardsPopover.tsx
 create mode 100644 upcoming-release-notes/2878.md

diff --git a/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx b/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx
index 28469b859..4b7034602 100644
--- a/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx
+++ b/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx
@@ -1,4 +1,4 @@
-import React, { createRef, useEffect, useMemo, useRef, useState } from 'react';
+import React, { useEffect, useMemo, useState } from 'react';
 
 import { send, sendCatch } from 'loot-core/platform/client/fetch/index';
 import * as monthUtils from 'loot-core/src/shared/months';
@@ -12,42 +12,13 @@ import { useResponsive } from '../../../ResponsiveProvider';
 import { styles } from '../../../style/index';
 import { theme } from '../../../style/theme';
 import { Block } from '../../common/Block';
-import { Menu } from '../../common/Menu';
-import { MenuButton } from '../../common/MenuButton';
-import { Popover } from '../../common/Popover';
 import { Text } from '../../common/Text';
 import { View } from '../../common/View';
 import { DateRange } from '../DateRange';
 import { ReportCard } from '../ReportCard';
-import { SaveReportDelete } from '../SaveReportDelete';
-import { SaveReportName } from '../SaveReportName';
 
 import { GetCardData } from './GetCardData';
-
-type CardMenuProps = {
-  onMenuSelect: (item: string, report: CustomReportEntity) => void;
-  report: CustomReportEntity;
-};
-
-function CardMenu({ onMenuSelect, report }: CardMenuProps) {
-  return (
-    <Menu
-      onMenuSelect={item => {
-        onMenuSelect(item, report);
-      }}
-      items={[
-        {
-          name: 'rename',
-          text: 'Rename report',
-        },
-        {
-          name: 'delete',
-          text: 'Delete report',
-        },
-      ]}
-    />
-  );
-}
+import { ListCardsPopover } from './ListCardsPopover';
 
 function index(data: CustomReportEntity[]): { [key: string]: boolean }[] {
   return data.reduce((carry, report) => {
@@ -69,10 +40,8 @@ export function CustomReportListCards({
   const [reportMenu, setReportMenu] = useState(result);
   const [deleteMenuOpen, setDeleteMenuOpen] = useState(result);
   const [nameMenuOpen, setNameMenuOpen] = useState(result);
-  const triggerRef = useRef(null);
   const [err, setErr] = useState('');
   const [name, setName] = useState('');
-  const inputRef = createRef<HTMLInputElement>();
   const [earliestTransaction, setEarliestTransaction] = useState('');
 
   const payees = usePayees();
@@ -254,90 +223,22 @@ export function CustomReportListCards({
                     top: 25,
                   }}
                 >
-                  <MenuButton
-                    ref={triggerRef}
-                    onClick={() =>
-                      onMenuOpen(report.id === undefined ? '' : report.id, true)
-                    }
-                    style={{
-                      color:
-                        isCardHovered === report.id ? 'inherit' : 'transparent',
-                    }}
+                  <ListCardsPopover
+                    report={report}
+                    onMenuOpen={onMenuOpen}
+                    isCardHovered={isCardHovered}
+                    reportMenu={reportMenu}
+                    onMenuSelect={onMenuSelect}
+                    nameMenuOpen={nameMenuOpen}
+                    name={name}
+                    setName={setName}
+                    onAddUpdate={onAddUpdate}
+                    err={err}
+                    onNameMenuOpen={onNameMenuOpen}
+                    deleteMenuOpen={deleteMenuOpen}
+                    onDeleteMenuOpen={onDeleteMenuOpen}
+                    onDelete={onDelete}
                   />
-
-                  <Popover
-                    triggerRef={triggerRef}
-                    isOpen={
-                      !!(
-                        report.id &&
-                        reportMenu[report.id as keyof typeof reportMenu]
-                      )
-                    }
-                    onOpenChange={() =>
-                      onMenuOpen(
-                        report.id === undefined ? '' : report.id,
-                        false,
-                      )
-                    }
-                    style={{ width: 120 }}
-                  >
-                    <CardMenu onMenuSelect={onMenuSelect} report={report} />
-                  </Popover>
-
-                  <Popover
-                    triggerRef={triggerRef}
-                    isOpen={
-                      !!(
-                        report.id &&
-                        nameMenuOpen[report.id as keyof typeof nameMenuOpen]
-                      )
-                    }
-                    onOpenChange={() =>
-                      onNameMenuOpen(
-                        report.id === undefined ? '' : report.id,
-                        false,
-                      )
-                    }
-                    style={{ width: 325 }}
-                  >
-                    <SaveReportName
-                      menuItem="rename"
-                      name={name}
-                      setName={setName}
-                      inputRef={inputRef}
-                      onAddUpdate={onAddUpdate}
-                      err={err}
-                      report={report}
-                    />
-                  </Popover>
-
-                  <Popover
-                    triggerRef={triggerRef}
-                    isOpen={
-                      !!(
-                        report.id &&
-                        deleteMenuOpen[report.id as keyof typeof deleteMenuOpen]
-                      )
-                    }
-                    onOpenChange={() =>
-                      onDeleteMenuOpen(
-                        report.id === undefined ? '' : report.id,
-                        false,
-                      )
-                    }
-                    style={{ width: 275, padding: 15 }}
-                  >
-                    <SaveReportDelete
-                      onDelete={() => onDelete(report.id)}
-                      onClose={() =>
-                        onDeleteMenuOpen(
-                          report.id === undefined ? '' : report.id,
-                          false,
-                        )
-                      }
-                      name={report.name}
-                    />
-                  </Popover>
                 </View>
               </View>
             ))}
diff --git a/packages/desktop-client/src/components/reports/reports/ListCardsMenu.tsx b/packages/desktop-client/src/components/reports/reports/ListCardsMenu.tsx
new file mode 100644
index 000000000..7ecd3542c
--- /dev/null
+++ b/packages/desktop-client/src/components/reports/reports/ListCardsMenu.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+
+import { type CustomReportEntity } from 'loot-core/types/models/reports';
+
+import { Menu } from '../../common/Menu';
+
+type ListCardsMenuProps = {
+  onMenuSelect: (item: string, report: CustomReportEntity) => void;
+  report: CustomReportEntity;
+};
+
+export function ListCardsMenu({ onMenuSelect, report }: ListCardsMenuProps) {
+  return (
+    <Menu
+      onMenuSelect={item => {
+        onMenuSelect(item, report);
+      }}
+      items={[
+        {
+          name: 'rename',
+          text: 'Rename report',
+        },
+        {
+          name: 'delete',
+          text: 'Delete report',
+        },
+      ]}
+    />
+  );
+}
diff --git a/packages/desktop-client/src/components/reports/reports/ListCardsPopover.tsx b/packages/desktop-client/src/components/reports/reports/ListCardsPopover.tsx
new file mode 100644
index 000000000..c0daf34b0
--- /dev/null
+++ b/packages/desktop-client/src/components/reports/reports/ListCardsPopover.tsx
@@ -0,0 +1,116 @@
+import React, { createRef, useRef } from 'react';
+
+import { type CustomReportEntity } from 'loot-core/types/models/reports';
+
+import { MenuButton } from '../../common/MenuButton';
+import { Popover } from '../../common/Popover';
+import { SaveReportDelete } from '../SaveReportDelete';
+import { SaveReportName } from '../SaveReportName';
+
+import { ListCardsMenu } from './ListCardsMenu';
+
+type ListCardsPopoverProps = {
+  report: CustomReportEntity;
+  onMenuOpen: (item: string, state: boolean) => void;
+  isCardHovered: string;
+  reportMenu: { [key: string]: boolean }[];
+  onMenuSelect: (item: string, report: CustomReportEntity) => void;
+  nameMenuOpen: { [key: string]: boolean }[];
+  onNameMenuOpen: (item: string, state: boolean) => void;
+  name: string;
+  setName: (name: string) => void;
+  onAddUpdate: ({ reportData }: { reportData?: CustomReportEntity }) => void;
+  err: string;
+  deleteMenuOpen: { [key: string]: boolean }[];
+  onDeleteMenuOpen: (item: string, state: boolean) => void;
+  onDelete: (reportData: string) => void;
+};
+export function ListCardsPopover({
+  report,
+  onMenuOpen,
+  isCardHovered,
+  reportMenu,
+  onMenuSelect,
+  nameMenuOpen,
+  onNameMenuOpen,
+  name,
+  setName,
+  onAddUpdate,
+  err,
+  deleteMenuOpen,
+  onDeleteMenuOpen,
+  onDelete,
+}: ListCardsPopoverProps) {
+  const triggerRef = useRef(null);
+  const inputRef = createRef<HTMLInputElement>();
+
+  return (
+    <>
+      <MenuButton
+        ref={triggerRef}
+        onClick={() =>
+          onMenuOpen(report.id === undefined ? '' : report.id, true)
+        }
+        style={{
+          color: isCardHovered === report.id ? 'inherit' : 'transparent',
+        }}
+      />
+
+      <Popover
+        triggerRef={triggerRef}
+        isOpen={
+          !!(report.id && reportMenu[report.id as keyof typeof reportMenu])
+        }
+        onOpenChange={() =>
+          onMenuOpen(report.id === undefined ? '' : report.id, false)
+        }
+        style={{ width: 120 }}
+      >
+        <ListCardsMenu onMenuSelect={onMenuSelect} report={report} />
+      </Popover>
+
+      <Popover
+        triggerRef={triggerRef}
+        isOpen={
+          !!(report.id && nameMenuOpen[report.id as keyof typeof nameMenuOpen])
+        }
+        onOpenChange={() =>
+          onNameMenuOpen(report.id === undefined ? '' : report.id, false)
+        }
+        style={{ width: 325 }}
+      >
+        <SaveReportName
+          menuItem="rename"
+          name={name}
+          setName={setName}
+          inputRef={inputRef}
+          onAddUpdate={onAddUpdate}
+          err={err}
+          report={report}
+        />
+      </Popover>
+
+      <Popover
+        triggerRef={triggerRef}
+        isOpen={
+          !!(
+            report.id &&
+            deleteMenuOpen[report.id as keyof typeof deleteMenuOpen]
+          )
+        }
+        onOpenChange={() =>
+          onDeleteMenuOpen(report.id === undefined ? '' : report.id, false)
+        }
+        style={{ width: 275, padding: 15 }}
+      >
+        <SaveReportDelete
+          onDelete={() => onDelete(report.id)}
+          onClose={() =>
+            onDeleteMenuOpen(report.id === undefined ? '' : report.id, false)
+          }
+          name={report.name}
+        />
+      </Popover>
+    </>
+  );
+}
diff --git a/upcoming-release-notes/2878.md b/upcoming-release-notes/2878.md
new file mode 100644
index 000000000..149de431f
--- /dev/null
+++ b/upcoming-release-notes/2878.md
@@ -0,0 +1,6 @@
+---
+category: Bugfix
+authors: [carkom]
+---
+
+Fixes a regression that broke the menus for the individual custom report cards.
-- 
GitLab