From 55817b0e70324fb47458634682174a32745ec1ca Mon Sep 17 00:00:00 2001
From: Neil <55785687+carkom@users.noreply.github.com>
Date: Wed, 28 Feb 2024 19:47:42 +0000
Subject: [PATCH] Add interval split and menu items to custom reports (#2389)

* Add interval split and menu items

* notes
---
 .../src/components/reports/ChooseGraph.tsx    |  7 +-
 .../src/components/reports/ReportLegend.tsx   |  9 ++-
 .../src/components/reports/ReportOptions.ts   | 31 ++++----
 .../src/components/reports/ReportSidebar.jsx  | 76 ++++++++++---------
 .../src/components/reports/ReportTopbar.jsx   |  6 +-
 .../components/reports/graphs/BarGraph.tsx    |  4 +-
 .../components/reports/graphs/DonutGraph.tsx  |  4 +-
 .../graphs/tableGraph/ReportTableHeader.tsx   | 15 +++-
 .../graphs/tableGraph/ReportTableList.tsx     |  2 +-
 .../reports/reports/CustomReport.jsx          | 14 +++-
 .../reports/reports/CustomReportListCards.tsx |  1 +
 .../reports/spreadsheets/calculateLegend.ts   |  8 +-
 .../src/client/data-hooks/reports.ts          |  1 +
 .../loot-core/src/server/aql/schema/index.ts  |  2 +-
 packages/loot-core/src/server/reports/app.ts  |  2 +
 .../loot-core/src/types/models/reports.d.ts   |  2 +
 upcoming-release-notes/2389.md                |  6 ++
 17 files changed, 114 insertions(+), 76 deletions(-)
 create mode 100644 upcoming-release-notes/2389.md

diff --git a/packages/desktop-client/src/components/reports/ChooseGraph.tsx b/packages/desktop-client/src/components/reports/ChooseGraph.tsx
index dce8850f8..1eef9fabc 100644
--- a/packages/desktop-client/src/components/reports/ChooseGraph.tsx
+++ b/packages/desktop-client/src/components/reports/ChooseGraph.tsx
@@ -27,6 +27,7 @@ type ChooseGraphProps = {
   graphType: string;
   balanceType: string;
   groupBy: string;
+  interval: string;
   setScrollWidth?: (value: number) => void;
   viewLabels?: boolean;
   compact?: boolean;
@@ -41,6 +42,7 @@ export function ChooseGraph({
   graphType,
   balanceType,
   groupBy,
+  interval,
   setScrollWidth,
   viewLabels,
   compact,
@@ -52,7 +54,7 @@ export function ChooseGraph({
   const groupByData =
     groupBy === 'Category'
       ? 'groupedData'
-      : ['Month', 'Year'].includes(groupBy)
+      : groupBy === 'Interval'
         ? 'monthData'
         : 'data';
 
@@ -142,8 +144,9 @@ export function ChooseGraph({
         <ReportTableHeader
           headerScrollRef={headerScrollRef}
           handleScroll={handleScroll}
-          interval={mode === 'time' && data.monthData}
+          data={mode === 'time' && data.monthData}
           groupBy={groupBy}
+          interval={interval}
           balanceType={balanceType}
           compact={compact}
           style={rowStyle}
diff --git a/packages/desktop-client/src/components/reports/ReportLegend.tsx b/packages/desktop-client/src/components/reports/ReportLegend.tsx
index 1c4763331..91ea3f86c 100644
--- a/packages/desktop-client/src/components/reports/ReportLegend.tsx
+++ b/packages/desktop-client/src/components/reports/ReportLegend.tsx
@@ -4,12 +4,15 @@ import { theme, styles } from '../../style';
 import { Text } from '../common/Text';
 import { View } from '../common/View';
 
+import { ReportOptions } from './ReportOptions';
+
 type ReportLegendProps = {
   legend?: Array<{ name: string; color: string }>;
   groupBy: string;
+  interval: string;
 };
 
-export function ReportLegend({ legend, groupBy }: ReportLegendProps) {
+export function ReportLegend({ legend, groupBy, interval }: ReportLegendProps) {
   return (
     <View
       style={{
@@ -28,7 +31,9 @@ export function ReportLegend({ legend, groupBy }: ReportLegendProps) {
           paddingTop: 10,
         }}
       >
-        {groupBy}
+        {groupBy === 'Interval'
+          ? ReportOptions.intervalMap.get(interval)
+          : groupBy}
       </Text>
       <View>
         {legend &&
diff --git a/packages/desktop-client/src/components/reports/ReportOptions.ts b/packages/desktop-client/src/components/reports/ReportOptions.ts
index a79c2059a..1f868ef1f 100644
--- a/packages/desktop-client/src/components/reports/ReportOptions.ts
+++ b/packages/desktop-client/src/components/reports/ReportOptions.ts
@@ -17,6 +17,7 @@ export const defaultReport: CustomReportEntity = {
   dateRange: 'Last 6 months',
   mode: 'total',
   groupBy: 'Category',
+  interval: 'Monthly',
   balanceType: 'Payment',
   showEmpty: false,
   showOffBudget: false,
@@ -38,8 +39,7 @@ const groupByOptions = [
   { description: 'Group' },
   { description: 'Payee' },
   { description: 'Account' },
-  { description: 'Month' },
-  { description: 'Year' },
+  { description: 'Interval' },
 ];
 
 const dateRangeOptions = [
@@ -53,6 +53,14 @@ const dateRangeOptions = [
   { description: 'All time', name: 'allMonths' },
 ];
 
+const intervalOptions = [
+  //{ value: 1, description: 'Daily', name: 'Day'},
+  //{ value: 2, description: 'Weekly', name: 'Week'},
+  //{ value: 3, description: 'Fortnightly', name: 3},
+  { value: 4, description: 'Monthly', name: 'Month' },
+  { value: 5, description: 'Yearly', name: 'Year' },
+];
+
 export const ReportOptions = {
   groupBy: groupByOptions,
   balanceType: balanceTypeOptions,
@@ -63,17 +71,12 @@ export const ReportOptions = {
   dateRangeMap: new Map(
     dateRangeOptions.map(item => [item.description, item.name]),
   ),
+  interval: intervalOptions,
+  intervalMap: new Map(
+    intervalOptions.map(item => [item.description, item.name]),
+  ),
 };
 
-/*
-const intervalOptions = [
-{ value: 1, description: 'Daily', name: 1,
-{ value: 2, description: 'Weekly', name: 2,
-{ value: 3, description: 'Fortnightly', name: 3,
-{ value: 4, description: 'Monthly', name: 4,
-{ value: 5, description: 'Yearly', name: 5,
-];
-*/
 export type QueryDataEntity = {
   date: string;
   category: string;
@@ -181,11 +184,7 @@ export const groupBySelections = (
       groupByList = accounts;
       groupByLabel = 'account';
       break;
-    case 'Month':
-      groupByList = categoryList;
-      groupByLabel = 'category';
-      break;
-    case 'Year':
+    case 'Interval':
       groupByList = categoryList;
       groupByLabel = 'category';
       break;
diff --git a/packages/desktop-client/src/components/reports/ReportSidebar.jsx b/packages/desktop-client/src/components/reports/ReportSidebar.jsx
index 46981a2c0..6bf50b846 100644
--- a/packages/desktop-client/src/components/reports/ReportSidebar.jsx
+++ b/packages/desktop-client/src/components/reports/ReportSidebar.jsx
@@ -31,6 +31,7 @@ export function ReportSidebar({
   setTypeDisabled,
   setGraphType,
   setGroupBy,
+  setInterval,
   setBalanceType,
   setMode,
   setIsDateStatic,
@@ -97,7 +98,7 @@ export function ReportSidebar({
         setGraphType('TableGraph');
         onChangeViews('viewLegend', false);
       }
-      if (['Month', 'Year'].includes(customReportItems.groupBy)) {
+      if (customReportItems.groupBy === 'Interval') {
         setGroupBy('Category');
       }
     } else {
@@ -115,7 +116,7 @@ export function ReportSidebar({
     if (customReportItems.mode === 'total') {
       if (customReportItems.graphType !== 'TableGraph') {
         setTypeDisabled(
-          !['Month', 'Year'].includes(customReportItems.groupBy) ? [] : ['Net'],
+          customReportItems.groupBy !== 'Interval' ? [] : ['Net'],
         );
       }
     }
@@ -161,7 +162,7 @@ export function ReportSidebar({
             alignItems: 'center',
           }}
         >
-          <Text style={{ width: 40, textAlign: 'right', marginRight: 5 }}>
+          <Text style={{ width: 50, textAlign: 'right', marginRight: 5 }}>
             Mode:
           </Text>
           <ModeButton
@@ -184,7 +185,7 @@ export function ReportSidebar({
             alignItems: 'center',
           }}
         >
-          <Text style={{ width: 40, textAlign: 'right', marginRight: 5 }}>
+          <Text style={{ width: 50, textAlign: 'right', marginRight: 5 }}>
             Split:
           </Text>
           <Select
@@ -196,10 +197,10 @@ export function ReportSidebar({
             ])}
             disabledKeys={
               customReportItems.mode === 'time'
-                ? ['Month', 'Year']
+                ? ['Interval']
                 : customReportItems.graphType === 'AreaGraph'
-                  ? ['Category', 'Group', 'Payee', 'Account', 'Year']
-                  : ['Year']
+                  ? ['Category', 'Group', 'Payee', 'Account']
+                  : []
             }
           />
         </View>
@@ -210,7 +211,7 @@ export function ReportSidebar({
             alignItems: 'center',
           }}
         >
-          <Text style={{ width: 40, textAlign: 'right', marginRight: 5 }}>
+          <Text style={{ width: 50, textAlign: 'right', marginRight: 5 }}>
             Type:
           </Text>
           <Select
@@ -223,30 +224,6 @@ export function ReportSidebar({
             disabledKeys={typeDisabled}
           />
         </View>
-        {/* //It would be nice to retain this for future usage
-            <View
-              style={{
-                flexDirection: 'row',
-                padding: 5,
-                alignItems: 'center',
-              }}
-            >
-              <Text style={{ width: 40, textAlign: 'right', marginRight: 5, paddingLeft: -10 }}>
-                Interval:
-              </Text>
-              <Select
-                value={interval}
-                onChange={setInterval}
-                options={intervalOptions.map(option => [
-                  option.value,
-                  option.description,
-                ])}
-                disabledKeys={
-                  [1,2,3,4,5]
-                }
-              />
-            </View>
-            */}
         <View
           style={{
             flexDirection: 'row',
@@ -254,7 +231,34 @@ export function ReportSidebar({
             alignItems: 'center',
           }}
         >
-          <Text style={{ width: 40, textAlign: 'right', marginRight: 5 }} />
+          <Text style={{ width: 50, textAlign: 'right', marginRight: 5 }}>
+            Interval:
+          </Text>
+          <Select
+            value={customReportItems.interval}
+            onChange={e => {
+              setInterval(e);
+              onReportChange({ type: 'modify' });
+            }}
+            options={ReportOptions.interval.map(option => [
+              option.description,
+              option.description,
+            ])}
+            disabledKeys={
+              customReportItems.mode === 'time'
+                ? ['Monthly', 'Yearly']
+                : ['Yearly']
+            }
+          />
+        </View>
+        <View
+          style={{
+            flexDirection: 'row',
+            padding: 5,
+            alignItems: 'center',
+          }}
+        >
+          <Text style={{ width: 50, textAlign: 'right', marginRight: 5 }} />
           <Button
             onClick={() => {
               setMenuOpen(true);
@@ -372,7 +376,7 @@ export function ReportSidebar({
               alignItems: 'center',
             }}
           >
-            <Text style={{ width: 40, textAlign: 'right', marginRight: 5 }}>
+            <Text style={{ width: 50, textAlign: 'right', marginRight: 5 }}>
               Range:
             </Text>
             <Select
@@ -396,7 +400,7 @@ export function ReportSidebar({
                 alignItems: 'center',
               }}
             >
-              <Text style={{ width: 40, textAlign: 'right', marginRight: 5 }}>
+              <Text style={{ width: 50, textAlign: 'right', marginRight: 5 }}>
                 From:
               </Text>
               <Select
@@ -424,7 +428,7 @@ export function ReportSidebar({
                 alignItems: 'center',
               }}
             >
-              <Text style={{ width: 40, textAlign: 'right', marginRight: 5 }}>
+              <Text style={{ width: 50, textAlign: 'right', marginRight: 5 }}>
                 To:
               </Text>
               <Select
diff --git a/packages/desktop-client/src/components/reports/ReportTopbar.jsx b/packages/desktop-client/src/components/reports/ReportTopbar.jsx
index d63744e9b..5ffeaee5c 100644
--- a/packages/desktop-client/src/components/reports/ReportTopbar.jsx
+++ b/packages/desktop-client/src/components/reports/ReportTopbar.jsx
@@ -70,9 +70,7 @@ export function ReportTopbar({
               setBalanceType('Payment');
             }
             setTypeDisabled(
-              ['Month', 'Year'].includes(customReportItems.groupBy)
-                ? []
-                : ['Net'],
+              ['Interval'].includes(customReportItems.groupBy) ? [] : ['Net'],
             );
           } else {
             setGraphType('StackedBarGraph');
@@ -90,7 +88,7 @@ export function ReportTopbar({
         onSelect={() => {
           onReportChange({ type: 'modify' });
           setGraphType('AreaGraph');
-          setGroupBy('Month');
+          setGroupBy('Interval');
           onChangeViews('viewLegend', false);
           setTypeDisabled([]);
         }}
diff --git a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
index 8489e92dd..5ec4783c1 100644
--- a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
@@ -141,8 +141,8 @@ export function BarGraph({
 }: BarGraphProps) {
   const privacyMode = usePrivacyMode();
 
-  const yAxis = ['Month', 'Year'].includes(groupBy) ? 'date' : 'name';
-  const splitData = ['Month', 'Year'].includes(groupBy) ? 'monthData' : 'data';
+  const yAxis = groupBy === 'Interval' ? 'date' : 'name';
+  const splitData = groupBy === 'Interval' ? 'monthData' : 'data';
   const labelsMargin = viewLabels ? 30 : 0;
 
   const getVal = obj => {
diff --git a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
index 8714290b0..40ba708aa 100644
--- a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
@@ -187,8 +187,8 @@ export function DonutGraph({
   compact,
   viewLabels,
 }: DonutGraphProps) {
-  const yAxis = ['Month', 'Year'].includes(groupBy) ? 'date' : 'name';
-  const splitData = ['Month', 'Year'].includes(groupBy) ? 'monthData' : 'data';
+  const yAxis = groupBy === 'Interval' ? 'date' : 'name';
+  const splitData = groupBy === 'Interval' ? 'monthData' : 'data';
 
   const getVal = obj => {
     if (balanceTypeOp === 'totalDebts') {
diff --git a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableHeader.tsx b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableHeader.tsx
index 14cafd14b..2246e4b12 100644
--- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableHeader.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableHeader.tsx
@@ -8,10 +8,12 @@ import { theme } from '../../../../style';
 import { type CSSProperties } from '../../../../style/types';
 import { View } from '../../../common/View';
 import { Row, Cell } from '../../../table';
+import { ReportOptions } from '../../ReportOptions';
 
 type ReportTableHeaderProps = {
   groupBy: string;
-  interval?: DataEntity[];
+  interval?: string;
+  data?: DataEntity[];
   balanceType: string;
   headerScrollRef: RefProp<HTMLDivElement>;
   handleScroll: UIEventHandler<HTMLDivElement>;
@@ -23,6 +25,7 @@ type ReportTableHeaderProps = {
 export function ReportTableHeader({
   groupBy,
   interval,
+  data,
   balanceType,
   headerScrollRef,
   handleScroll,
@@ -61,10 +64,14 @@ export function ReportTableHeader({
             flexShrink: 0,
           }}
           valueStyle={compactStyle}
-          value={groupBy}
+          value={
+            groupBy === 'Interval'
+              ? ReportOptions.intervalMap.get(interval)
+              : groupBy
+          }
         />
-        {interval
-          ? interval.map((header, index) => {
+        {data
+          ? data.map((header, index) => {
               return (
                 <Cell
                   style={{
diff --git a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx
index 33f9431a6..b1e56c312 100644
--- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx
@@ -28,7 +28,7 @@ export function ReportTableList({
   style,
   compactStyle,
 }: ReportTableListProps) {
-  const groupByItem = ['Month', 'Year'].includes(groupBy) ? 'date' : 'name';
+  const groupByItem = groupBy === 'Interval' ? 'date' : 'name';
 
   type RenderRowProps = {
     index: number;
diff --git a/packages/desktop-client/src/components/reports/reports/CustomReport.jsx b/packages/desktop-client/src/components/reports/reports/CustomReport.jsx
index 32b8b7fc2..93559528d 100644
--- a/packages/desktop-client/src/components/reports/reports/CustomReport.jsx
+++ b/packages/desktop-client/src/components/reports/reports/CustomReport.jsx
@@ -67,6 +67,7 @@ export function CustomReport() {
   const [mode, setMode] = useState(loadReport.mode);
   const [isDateStatic, setIsDateStatic] = useState(loadReport.isDateStatic);
   const [groupBy, setGroupBy] = useState(loadReport.groupBy);
+  const [interval, setInterval] = useState(loadReport.interval);
   const [balanceType, setBalanceType] = useState(loadReport.balanceType);
   const [showEmpty, setShowEmpty] = useState(loadReport.showEmpty);
   const [showOffBudget, setShowOffBudget] = useState(loadReport.showOffBudget);
@@ -146,6 +147,7 @@ export function CustomReport() {
     startDate,
     endDate,
     groupBy,
+    interval,
     balanceType,
     categories,
     selectedCategories,
@@ -184,6 +186,7 @@ export function CustomReport() {
     startDate,
     endDate,
     groupBy,
+    interval,
     balanceType,
     categories,
     selectedCategories,
@@ -208,6 +211,7 @@ export function CustomReport() {
     dateRange,
     mode,
     groupBy,
+    interval,
     balanceType,
     showEmpty,
     showOffBudget,
@@ -256,6 +260,7 @@ export function CustomReport() {
     setDateRange(defaultReport.dateRange);
     setMode(defaultReport.mode);
     setGroupBy(defaultReport.groupBy);
+    setInterval(defaultReport.interval);
     setBalanceType(defaultReport.balanceType);
     setShowEmpty(defaultReport.showEmpty);
     setShowOffBudget(defaultReport.showOffBudget);
@@ -297,6 +302,7 @@ export function CustomReport() {
         setDateRange(report.dateRange);
         setMode(report.mode);
         setGroupBy(report.groupBy);
+        setInterval(report.interval);
         setBalanceType(report.balanceType);
         setShowEmpty(report.showEmpty);
         setShowOffBudget(report.showOffBudget);
@@ -334,6 +340,7 @@ export function CustomReport() {
           setTypeDisabled={setTypeDisabled}
           setGraphType={setGraphType}
           setGroupBy={setGroupBy}
+          setInterval={setInterval}
           setBalanceType={setBalanceType}
           setMode={setMode}
           setIsDateStatic={setIsDateStatic}
@@ -446,6 +453,7 @@ export function CustomReport() {
                     graphType={graphType}
                     balanceType={balanceType}
                     groupBy={groupBy}
+                    interval={interval}
                     showEmpty={showEmpty}
                     scrollWidth={scrollWidth}
                     setScrollWidth={setScrollWidth}
@@ -477,7 +485,11 @@ export function CustomReport() {
                     />
                   )}
                   {viewLegend && (
-                    <ReportLegend legend={data.legend} groupBy={groupBy} />
+                    <ReportLegend
+                      legend={data.legend}
+                      groupBy={groupBy}
+                      interval={interval}
+                    />
                   )}
                 </View>
               )}
diff --git a/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx b/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx
index 40d7742a7..cb7b80e66 100644
--- a/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx
+++ b/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx
@@ -154,6 +154,7 @@ export function CustomReportListCards({
                           graphType={report.graphType}
                           balanceType={report.balanceType}
                           groupBy={report.groupBy}
+                          interval={report.interval}
                           compact={true}
                           style={{ height: 'auto', flex: 1 }}
                         />
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts b/packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts
index 9ba3410dd..2190b7ea6 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts
+++ b/packages/desktop-client/src/components/reports/spreadsheets/calculateLegend.ts
@@ -15,16 +15,14 @@ export function calculateLegend(
   balanceTypeOp: string,
 ) {
   const colorScale = getColorScale('qualitative');
-  const chooseData = ['Month', 'Year'].includes(groupBy)
-    ? monthData
-    : calcDataFiltered;
+  const chooseData = groupBy === 'Interval' ? monthData : calcDataFiltered;
   return chooseData.map((c, index) => {
     return {
-      name: ['Month', 'Year'].includes(groupBy) ? c.date : c.name,
+      name: groupBy === 'Interval' ? c.date : c.name,
       color:
         graphType === 'DonutGraph'
           ? colorScale[index % colorScale.length]
-          : ['Month', 'Year'].includes(groupBy)
+          : groupBy === 'Interval'
             ? balanceTypeOp === 'totalDebts'
               ? theme.reportsRed
               : theme.reportsBlue
diff --git a/packages/loot-core/src/client/data-hooks/reports.ts b/packages/loot-core/src/client/data-hooks/reports.ts
index 78246e477..275ef64d1 100644
--- a/packages/loot-core/src/client/data-hooks/reports.ts
+++ b/packages/loot-core/src/client/data-hooks/reports.ts
@@ -18,6 +18,7 @@ function toJS(rows: CustomReportData[]) {
       dateRange: row.date_range,
       mode: row.mode,
       groupBy: row.group_by,
+      interval: row.interval,
       balanceType: row.balance_type,
       showEmpty: row.show_empty === 1,
       showOffBudget: row.show_offbudget === 1,
diff --git a/packages/loot-core/src/server/aql/schema/index.ts b/packages/loot-core/src/server/aql/schema/index.ts
index cb466d6f8..f6799cdd9 100644
--- a/packages/loot-core/src/server/aql/schema/index.ts
+++ b/packages/loot-core/src/server/aql/schema/index.ts
@@ -145,7 +145,7 @@ export const schema = {
     conditions: f('json'),
     conditions_op: f('string'),
     metadata: f('json'),
-    interval: f('string'),
+    interval: f('string', { default: 'Monthly' }),
     color_scheme: f('json'),
     tombstone: f('boolean'),
   },
diff --git a/packages/loot-core/src/server/reports/app.ts b/packages/loot-core/src/server/reports/app.ts
index d78d09cb4..5e1238509 100644
--- a/packages/loot-core/src/server/reports/app.ts
+++ b/packages/loot-core/src/server/reports/app.ts
@@ -35,6 +35,7 @@ const reportModel = {
       dateRange: row.date_range,
       mode: row.mode,
       groupBy: row.group_by,
+      interval: row.interval,
       balanceType: row.balance_type,
       showEmpty: row.show_empty === 1,
       showOffBudget: row.show_offbudget === 1,
@@ -58,6 +59,7 @@ const reportModel = {
       date_range: report.dateRange,
       mode: report.mode,
       group_by: report.groupBy,
+      interval: report.interval,
       balance_type: report.balanceType,
       show_empty: report.showEmpty ? 1 : 0,
       show_offbudget: report.showOffBudget ? 1 : 0,
diff --git a/packages/loot-core/src/types/models/reports.d.ts b/packages/loot-core/src/types/models/reports.d.ts
index 06a6e56e0..cb966d6e3 100644
--- a/packages/loot-core/src/types/models/reports.d.ts
+++ b/packages/loot-core/src/types/models/reports.d.ts
@@ -10,6 +10,7 @@ export interface CustomReportEntity {
   dateRange: string;
   mode: string;
   groupBy: string;
+  interval: string;
   balanceType: string;
   showEmpty: boolean;
   showOffBudget: boolean;
@@ -80,6 +81,7 @@ export interface CustomReportData {
   date_range: string;
   mode: string;
   group_by: string;
+  interval: string;
   balance_type: string;
   show_empty: number;
   show_offbudget: number;
diff --git a/upcoming-release-notes/2389.md b/upcoming-release-notes/2389.md
new file mode 100644
index 000000000..021aa519d
--- /dev/null
+++ b/upcoming-release-notes/2389.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [carkom]
+---
+
+Adding an interval menu to custom reports
-- 
GitLab