From 485902af6bc08ad670ea212cd6a0a72abc10aabd Mon Sep 17 00:00:00 2001
From: Neil <55785687+carkom@users.noreply.github.com>
Date: Sat, 10 Feb 2024 13:54:47 -0800
Subject: [PATCH] Update Custom Report styles (#2345)

* updated saved work

* merge fixes

* Disable CREATE TABLE

* notes

* turn on db table

* Fix TableGraph recall crash

* table format changes

* type fixes

* fixing some card displays

* merge fixes

* revert table change

* Revert Changes

* notes

* merge fixes

* notes

* notes

* revert notes

* Area changes
---
 .../src/components/reports/ChooseGraph.tsx    |  23 +++-
 .../src/components/reports/SaveReport.tsx     |   3 +-
 .../src/components/reports/SaveReportName.tsx |   9 +-
 .../components/reports/graphs/AreaGraph.tsx   |  32 +++++-
 .../components/reports/graphs/DonutGraph.tsx  |  86 +++++++++++---
 .../reports/graphs/StackedBarGraph.tsx        |  10 +-
 .../reports/graphs/renderCustomLabel.tsx      |   3 +-
 .../reports/graphs/tableGraph/ReportTable.tsx |  23 +++-
 .../graphs/tableGraph/ReportTableHeader.tsx   |  32 +++---
 .../graphs/tableGraph/ReportTableList.tsx     |  56 +++++----
 .../graphs/tableGraph/ReportTableRow.tsx      |  32 +++---
 .../graphs/tableGraph/ReportTableTotals.tsx   |  32 +++---
 .../reports/reports/CustomReport.jsx          |   3 +-
 .../src/client/data-hooks/reports.ts          |  22 +++-
 packages/loot-core/src/server/reports/app.ts  | 107 +++++++++++++-----
 .../loot-core/src/types/models/reports.d.ts   |  22 +++-
 upcoming-release-notes/2345.md                |   6 +
 17 files changed, 367 insertions(+), 134 deletions(-)
 create mode 100644 upcoming-release-notes/2345.md

diff --git a/packages/desktop-client/src/components/reports/ChooseGraph.tsx b/packages/desktop-client/src/components/reports/ChooseGraph.tsx
index 6fcddebb3..ad8f0c3a8 100644
--- a/packages/desktop-client/src/components/reports/ChooseGraph.tsx
+++ b/packages/desktop-client/src/components/reports/ChooseGraph.tsx
@@ -1,12 +1,11 @@
 // @ts-strict-ignore
 import React, { useRef } from 'react';
 
-import {
-  type GroupedEntity,
-  type Month,
-} from 'loot-core/src/types/models/reports';
+import * as monthUtils from 'loot-core/src/shared/months';
+import { type GroupedEntity } from 'loot-core/src/types/models/reports';
 
 import { type CSSProperties } from '../../style';
+import { styles } from '../../style/styles';
 import { View } from '../common/View';
 
 import { AreaGraph } from './graphs/AreaGraph';
@@ -21,30 +20,33 @@ import { ReportTableTotals } from './graphs/tableGraph/ReportTableTotals';
 import { ReportOptions } from './ReportOptions';
 
 type ChooseGraphProps = {
+  startDate: string;
+  endDate: string;
   data: GroupedEntity;
   mode: string;
   graphType: string;
   balanceType: string;
   groupBy: string;
   setScrollWidth?: (value: number) => void;
-  months?: Month[];
   viewLabels?: boolean;
   compact?: boolean;
   style?: CSSProperties;
 };
 
 export function ChooseGraph({
+  startDate,
+  endDate,
   data,
   mode,
   graphType,
   balanceType,
   groupBy,
   setScrollWidth,
-  months,
   viewLabels,
   compact,
   style,
 }: ChooseGraphProps) {
+  const months: string[] = monthUtils.rangeInclusive(startDate, endDate);
   const graphStyle = compact ? { ...style } : { flexGrow: 1 };
   const balanceTypeOp = ReportOptions.balanceTypeMap.get(balanceType);
   const groupByData =
@@ -58,6 +60,9 @@ export function ChooseGraph({
     setScrollWidth(!value ? 0 : value);
   };
 
+  const rowStyle = compact && { flex: '0 0 20px', height: 20 };
+  const compactStyle = compact && { ...styles.tinyText };
+
   const headerScrollRef = useRef<HTMLDivElement>(null);
   const listScrollRef = useRef<HTMLDivElement>(null);
   const totalScrollRef = useRef<HTMLDivElement>(null);
@@ -141,6 +146,8 @@ export function ChooseGraph({
           groupBy={groupBy}
           balanceType={balanceType}
           compact={compact}
+          style={rowStyle}
+          compactStyle={compactStyle}
         />
         <ReportTable
           saveScrollWidth={saveScrollWidth}
@@ -152,6 +159,8 @@ export function ChooseGraph({
           mode={mode}
           monthsCount={months.length}
           compact={compact}
+          style={rowStyle}
+          compactStyle={compactStyle}
         />
         <ReportTableTotals
           totalScrollRef={totalScrollRef}
@@ -161,6 +170,8 @@ export function ChooseGraph({
           balanceTypeOp={balanceTypeOp}
           monthsCount={months.length}
           compact={compact}
+          style={rowStyle}
+          compactStyle={compactStyle}
         />
       </View>
     );
diff --git a/packages/desktop-client/src/components/reports/SaveReport.tsx b/packages/desktop-client/src/components/reports/SaveReport.tsx
index e7e26a3a5..37ca8e4e9 100644
--- a/packages/desktop-client/src/components/reports/SaveReport.tsx
+++ b/packages/desktop-client/src/components/reports/SaveReport.tsx
@@ -39,7 +39,7 @@ export function SaveReport({
   const [menuItem, setMenuItem] = useState('');
   const [err, setErr] = useState('');
   const [res, setRes] = useState('');
-  const [name, setName] = useState(report.name);
+  const [name, setName] = useState(report.name ?? '');
   const inputRef = createRef<HTMLInputElement>();
 
   const onAddUpdate = async (menuChoice: string) => {
@@ -167,6 +167,7 @@ export function SaveReport({
         <SaveReportName
           onClose={() => setNameMenuOpen(false)}
           menuItem={menuItem}
+          name={name}
           setName={setName}
           inputRef={inputRef}
           onAddUpdate={onAddUpdate}
diff --git a/packages/desktop-client/src/components/reports/SaveReportName.tsx b/packages/desktop-client/src/components/reports/SaveReportName.tsx
index 34c1d8176..c6ef39ed6 100644
--- a/packages/desktop-client/src/components/reports/SaveReportName.tsx
+++ b/packages/desktop-client/src/components/reports/SaveReportName.tsx
@@ -11,6 +11,7 @@ import { FormField, FormLabel } from '../forms';
 type SaveReportNameProps = {
   onClose: () => void;
   menuItem: string;
+  name: string;
   setName: (name: string) => void;
   inputRef: RefObject<HTMLInputElement>;
   onAddUpdate: (menuItem: string) => void;
@@ -20,6 +21,7 @@ type SaveReportNameProps = {
 export function SaveReportName({
   onClose,
   menuItem,
+  name,
   setName,
   inputRef,
   onAddUpdate,
@@ -47,7 +49,12 @@ export function SaveReportName({
                 htmlFor="name-field"
                 style={{ userSelect: 'none' }}
               />
-              <Input inputRef={inputRef} onUpdate={setName} />
+              <Input
+                value={name}
+                id="name-field"
+                inputRef={inputRef}
+                onUpdate={setName}
+              />
             </FormField>
             <Button
               type="primary"
diff --git a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
index 58caaebb8..a261be8e3 100644
--- a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx
@@ -220,7 +220,13 @@ export function AreaGraph({
                   isAnimationActive={false}
                 />
                 <defs>
-                  <linearGradient id="splitColor" x1="0" y1="0" x2="0" y2="1">
+                  <linearGradient
+                    id={`fill${balanceTypeOp}`}
+                    x1="0"
+                    y1="0"
+                    x2="0"
+                    y2="1"
+                  >
                     <stop
                       offset={off}
                       stopColor={theme.reportsBlue}
@@ -232,6 +238,24 @@ export function AreaGraph({
                       stopOpacity={0.2}
                     />
                   </linearGradient>
+                  <linearGradient
+                    id={`stroke${balanceTypeOp}`}
+                    x1="0"
+                    y1="0"
+                    x2="0"
+                    y2="1"
+                  >
+                    <stop
+                      offset={off}
+                      stopColor={theme.reportsBlue}
+                      stopOpacity={1}
+                    />
+                    <stop
+                      offset={off}
+                      stopColor={theme.reportsRed}
+                      stopOpacity={1}
+                    />
+                  </linearGradient>
                 </defs>
 
                 <Area
@@ -240,11 +264,11 @@ export function AreaGraph({
                   activeDot={false}
                   animationDuration={0}
                   dataKey={balanceTypeOp}
-                  stroke={theme.reportsBlue}
-                  fill="url(#splitColor)"
+                  stroke={`url(#stroke${balanceTypeOp})`}
+                  fill={`url(#fill${balanceTypeOp})`}
                   fillOpacity={1}
                 >
-                  {viewLabels && (
+                  {viewLabels && !compact && (
                     <LabelList
                       dataKey={balanceTypeOp}
                       content={e => customLabel(e, width, lastLabel)}
diff --git a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
index 6fb3ebc03..e60bfa1e0 100644
--- a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx
@@ -7,12 +7,62 @@ import { amountToCurrency } from 'loot-core/src/shared/util';
 import { type GroupedEntity } from 'loot-core/src/types/models/reports';
 
 import { theme, type CSSProperties } from '../../../style';
+import { PrivacyFilter } from '../../PrivacyFilter';
 import { Container } from '../Container';
 
 import { adjustTextSize } from './adjustTextSize';
 import { renderCustomLabel } from './renderCustomLabel';
 
 const RADIAN = Math.PI / 180;
+
+const ActiveShapeMobile = props => {
+  const {
+    cx,
+    cy,
+    innerRadius,
+    outerRadius,
+    startAngle,
+    endAngle,
+    fill,
+    payload,
+    percent,
+    value,
+  } = props;
+  const yAxis = payload.name ?? payload.date;
+
+  return (
+    <g>
+      <text x={cx} y={cy + 65} dy={-8} textAnchor="middle" fill={fill}>
+        {`${yAxis}`}
+      </text>
+      <text x={cx - 30} y={cy + 40} dy={0} textAnchor="end" fill={fill}>
+        {`${amountToCurrency(value)}`}
+      </text>
+      <text x={cx + 30} y={cy + 40} dy={0} textAnchor="start" fill="#999">
+        {`${(percent * 100).toFixed(2)}%`}
+      </text>
+      <Sector
+        cx={cx}
+        cy={cy}
+        innerRadius={innerRadius}
+        outerRadius={outerRadius}
+        startAngle={startAngle}
+        endAngle={endAngle}
+        fill={fill}
+      />
+      <Sector
+        cx={cx}
+        cy={cy}
+        startAngle={startAngle}
+        endAngle={endAngle}
+        innerRadius={innerRadius - 8}
+        outerRadius={innerRadius - 6}
+        fill={fill}
+      />
+    </g>
+  );
+};
+
 const ActiveShape = props => {
   const {
     cx,
@@ -70,22 +120,24 @@ const ActiveShape = props => {
         textAnchor={textAnchor}
         fill={fill}
       >{`${yAxis}`}</text>
-      <text
-        x={ex + (cos <= 0 ? 1 : -1) * 16}
-        y={ey}
-        dy={18}
-        textAnchor={textAnchor}
-        fill={fill}
-      >{`${amountToCurrency(value)}`}</text>
-      <text
-        x={ex + (cos <= 0 ? 1 : -1) * 16}
-        y={ey}
-        dy={36}
-        textAnchor={textAnchor}
-        fill="#999"
-      >
-        {`(${(percent * 100).toFixed(2)}%)`}
-      </text>
+      <PrivacyFilter>
+        <text
+          x={ex + (cos <= 0 ? 1 : -1) * 16}
+          y={ey}
+          dy={18}
+          textAnchor={textAnchor}
+          fill={fill}
+        >{`${amountToCurrency(value)}`}</text>
+        <text
+          x={ex + (cos <= 0 ? 1 : -1) * 16}
+          y={ey}
+          dy={36}
+          textAnchor={textAnchor}
+          fill="#999"
+        >
+          {`(${(percent * 100).toFixed(2)}%)`}
+        </text>
+      </PrivacyFilter>
     </g>
   );
 };
@@ -165,7 +217,7 @@ export function DonutGraph({
               <PieChart width={width} height={height}>
                 <Pie
                   activeIndex={activeIndex}
-                  activeShape={ActiveShape}
+                  activeShape={compact ? ActiveShapeMobile : ActiveShape}
                   dataKey={val => getVal(val)}
                   nameKey={yAxis}
                   isAnimationActive={false}
diff --git a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
index 67d0ec1d1..ab2fcf993 100644
--- a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
@@ -166,14 +166,14 @@ export function StackedBarGraph({
                   isAnimationActive={false}
                   cursor={{ fill: 'transparent' }}
                 />
+                <XAxis
+                  dataKey="date"
+                  tick={{ fill: theme.pageText }}
+                  tickLine={{ stroke: theme.pageText }}
+                />
                 {!compact && (
                   <>
                     <CartesianGrid strokeDasharray="3 3" />
-                    <XAxis
-                      dataKey="date"
-                      tick={{ fill: theme.pageText }}
-                      tickLine={{ stroke: theme.pageText }}
-                    />
                     <YAxis
                       tickFormatter={value =>
                         getCustomTick(
diff --git a/packages/desktop-client/src/components/reports/graphs/renderCustomLabel.tsx b/packages/desktop-client/src/components/reports/graphs/renderCustomLabel.tsx
index 303773cce..187b50394 100644
--- a/packages/desktop-client/src/components/reports/graphs/renderCustomLabel.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/renderCustomLabel.tsx
@@ -2,6 +2,7 @@
 import React from 'react';
 
 import { theme } from '../../../style';
+import { PrivacyFilter } from '../../PrivacyFilter';
 
 export const renderCustomLabel = (
   calcX: number,
@@ -22,7 +23,7 @@ export const renderCustomLabel = (
       dominantBaseline="middle"
       fontSize={textSize}
     >
-      {display}
+      <PrivacyFilter>{display}</PrivacyFilter>
     </text>
   ) : (
     <text />
diff --git a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTable.tsx b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTable.tsx
index 9aa4e7a92..284200c6c 100644
--- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTable.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTable.tsx
@@ -20,26 +20,28 @@ type ReportTableProps = {
   saveScrollWidth: (value: number) => void;
   listScrollRef: RefProp<HTMLDivElement>;
   handleScroll: UIEventHandler<HTMLDivElement>;
-  style?: CSSProperties;
   groupBy: string;
   balanceTypeOp: 'totalDebts' | 'totalTotals' | 'totalAssets';
   data: DataEntity[];
   mode: string;
   monthsCount: number;
   compact: boolean;
+  style?: CSSProperties;
+  compactStyle?: CSSProperties;
 };
 
 export function ReportTable({
   saveScrollWidth,
   listScrollRef,
   handleScroll,
-  style,
   groupBy,
   balanceTypeOp,
   data,
   mode,
   monthsCount,
   compact,
+  style,
+  compactStyle,
 }: ReportTableProps) {
   const contentRef = useRef<HTMLDivElement>(null);
 
@@ -50,16 +52,25 @@ export function ReportTable({
   });
 
   const renderItem = useCallback(
-    ({ item, groupByItem, mode, style, monthsCount, compact }) => {
+    ({
+      item,
+      groupByItem,
+      mode,
+      monthsCount,
+      compact,
+      style,
+      compactStyle,
+    }) => {
       return (
         <ReportTableRow
           item={item}
           balanceTypeOp={balanceTypeOp}
           groupByItem={groupByItem}
           mode={mode}
-          style={style}
           monthsCount={monthsCount}
           compact={compact}
+          style={style}
+          compactStyle={compactStyle}
         />
       );
     },
@@ -73,7 +84,6 @@ export function ReportTable({
         flexDirection: 'row',
         outline: 'none',
         '& .animated .animated-row': { transition: '.25s transform' },
-        ...style,
       }}
       tabIndex={1}
     >
@@ -88,7 +98,6 @@ export function ReportTable({
           flex: 1,
           outline: 'none',
           '& .animated .animated-row': { transition: '.25s transform' },
-          ...style,
         }}
       >
         <ReportTableList
@@ -98,6 +107,8 @@ export function ReportTable({
           groupBy={groupBy}
           renderItem={renderItem}
           compact={compact}
+          style={style}
+          compactStyle={compactStyle}
         />
       </Block>
     </View>
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 4bb20248c..14cafd14b 100644
--- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableHeader.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableHeader.tsx
@@ -4,7 +4,8 @@ import { type RefProp } from 'react-spring';
 
 import { type DataEntity } from 'loot-core/src/types/models/reports';
 
-import { styles, theme } from '../../../../style';
+import { theme } from '../../../../style';
+import { type CSSProperties } from '../../../../style/types';
 import { View } from '../../../common/View';
 import { Row, Cell } from '../../../table';
 
@@ -15,6 +16,8 @@ type ReportTableHeaderProps = {
   headerScrollRef: RefProp<HTMLDivElement>;
   handleScroll: UIEventHandler<HTMLDivElement>;
   compact: boolean;
+  style?: CSSProperties;
+  compactStyle?: CSSProperties;
 };
 
 export function ReportTableHeader({
@@ -24,6 +27,8 @@ export function ReportTableHeader({
   headerScrollRef,
   handleScroll,
   compact,
+  style,
+  compactStyle,
 }: ReportTableHeaderProps) {
   return (
     <Row
@@ -35,6 +40,7 @@ export function ReportTableHeader({
         color: theme.tableHeaderText,
         backgroundColor: theme.tableHeaderBackground,
         fontWeight: 600,
+        ...style,
       }}
     >
       <View
@@ -51,10 +57,10 @@ export function ReportTableHeader({
       >
         <Cell
           style={{
-            width: 120,
+            width: compact ? 80 : 125,
             flexShrink: 0,
-            ...styles.tnum,
           }}
+          valueStyle={compactStyle}
           value={groupBy}
         />
         {interval
@@ -62,9 +68,9 @@ export function ReportTableHeader({
               return (
                 <Cell
                   style={{
-                    minWidth: compact ? 80 : 125,
-                    ...styles.tnum,
+                    minWidth: compact ? 50 : 85,
                   }}
+                  valueStyle={compactStyle}
                   key={index}
                   value={header.date}
                   width="flex"
@@ -75,17 +81,17 @@ export function ReportTableHeader({
               <>
                 <Cell
                   style={{
-                    minWidth: compact ? 80 : 125,
-                    ...styles.tnum,
+                    minWidth: compact ? 50 : 85,
                   }}
+                  valueStyle={compactStyle}
                   value="Deposits"
                   width="flex"
                 />
                 <Cell
                   style={{
-                    minWidth: compact ? 80 : 125,
-                    ...styles.tnum,
+                    minWidth: compact ? 50 : 85,
                   }}
+                  valueStyle={compactStyle}
                   value="Payments"
                   width="flex"
                 />
@@ -93,17 +99,17 @@ export function ReportTableHeader({
             )}
         <Cell
           style={{
-            minWidth: compact ? 80 : 125,
-            ...styles.tnum,
+            minWidth: compact ? 50 : 85,
           }}
+          valueStyle={compactStyle}
           value="Totals"
           width="flex"
         />
         <Cell
           style={{
-            minWidth: compact ? 80 : 125,
-            ...styles.tnum,
+            minWidth: compact ? 50 : 85,
           }}
+          valueStyle={compactStyle}
           value="Average"
           width="flex"
         />
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 d961144b6..33f9431a6 100644
--- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx
@@ -5,7 +5,7 @@ import { type DataEntity } from 'loot-core/src/types/models/reports';
 
 import { type CSSProperties, theme } from '../../../../style';
 import { View } from '../../../common/View';
-import { Cell, Row } from '../../../table';
+import { Row } from '../../../table';
 
 type ReportTableListProps = {
   data: DataEntity[];
@@ -14,6 +14,8 @@ type ReportTableListProps = {
   groupBy: string;
   renderItem;
   compact: boolean;
+  style?: CSSProperties;
+  compactStyle?: CSSProperties;
 };
 
 export function ReportTableList({
@@ -23,16 +25,25 @@ export function ReportTableList({
   groupBy,
   renderItem,
   compact,
+  style,
+  compactStyle,
 }: ReportTableListProps) {
   const groupByItem = ['Month', 'Year'].includes(groupBy) ? 'date' : 'name';
 
   type RenderRowProps = {
     index: number;
     parent_index?: number;
-    style?: CSSProperties;
     compact: boolean;
+    style?: CSSProperties;
+    compactStyle?: CSSProperties;
   };
-  function RenderRow({ index, parent_index, style, compact }: RenderRowProps) {
+  function RenderRow({
+    index,
+    parent_index,
+    compact,
+    style,
+    compactStyle,
+  }: RenderRowProps) {
     const item =
       parent_index === undefined
         ? data[index]
@@ -42,29 +53,32 @@ export function ReportTableList({
       item,
       groupByItem,
       mode,
-      style,
       monthsCount,
       compact,
+      style,
+      compactStyle,
     });
   }
 
   return (
     <View>
-      {data.map((item, index) => {
-        return (
-          <View key={item.id}>
-            {data ? (
-              <>
+      {data ? (
+        <View>
+          {data.map((item, index) => {
+            return (
+              <View key={item.id}>
                 <RenderRow
                   index={index}
                   compact={compact}
-                  style={
-                    item.categories && {
+                  style={{
+                    ...(item.categories && {
                       color: theme.tableRowHeaderText,
                       backgroundColor: theme.tableRowHeaderBackground,
                       fontWeight: 600,
-                    }
-                  }
+                    }),
+                    ...style,
+                  }}
+                  compactStyle={compactStyle}
                 />
                 {item.categories && (
                   <>
@@ -76,6 +90,8 @@ export function ReportTableList({
                             index={i}
                             compact={compact}
                             parent_index={index}
+                            style={style}
+                            compactStyle={compactStyle}
                           />
                         );
                       })}
@@ -83,13 +99,13 @@ export function ReportTableList({
                     <Row height={20} />
                   </>
                 )}
-              </>
-            ) : (
-              <Cell width="flex" />
-            )}
-          </View>
-        );
-      })}
+              </View>
+            );
+          })}
+        </View>
+      ) : (
+        <View width="flex" />
+      )}
     </View>
   );
 }
diff --git a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableRow.tsx b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableRow.tsx
index 4779f22df..831f0b091 100644
--- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableRow.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableRow.tsx
@@ -7,7 +7,7 @@ import {
 } from 'loot-core/src/shared/util';
 import { type DataEntity } from 'loot-core/src/types/models/reports';
 
-import { type CSSProperties, styles, theme } from '../../../../style';
+import { type CSSProperties, theme } from '../../../../style';
 import { Row, Cell } from '../../../table';
 
 type ReportTableRowProps = {
@@ -15,9 +15,10 @@ type ReportTableRowProps = {
   balanceTypeOp: 'totalAssets' | 'totalDebts' | 'totalTotals';
   groupByItem: 'id' | 'name';
   mode: string;
-  style?: CSSProperties;
   monthsCount: number;
   compact: boolean;
+  style?: CSSProperties;
+  compactStyle?: CSSProperties;
 };
 
 export const ReportTableRow = memo(
@@ -26,9 +27,10 @@ export const ReportTableRow = memo(
     balanceTypeOp,
     groupByItem,
     mode,
-    style,
     monthsCount,
     compact,
+    style,
+    compactStyle,
   }: ReportTableRowProps) => {
     const average = amountToInteger(item[balanceTypeOp]) / monthsCount;
     return (
@@ -45,10 +47,10 @@ export const ReportTableRow = memo(
           value={item[groupByItem]}
           title={item[groupByItem].length > 12 ? item[groupByItem] : undefined}
           style={{
-            width: 120,
+            width: compact ? 80 : 125,
             flexShrink: 0,
-            ...styles.tnum,
           }}
+          valueStyle={compactStyle}
         />
         {item.monthData && mode === 'time'
           ? item.monthData.map(month => {
@@ -56,9 +58,9 @@ export const ReportTableRow = memo(
                 <Cell
                   key={amountToCurrency(month[balanceTypeOp])}
                   style={{
-                    minWidth: compact ? 80 : 125,
-                    ...styles.tnum,
+                    minWidth: compact ? 50 : 85,
                   }}
+                  valueStyle={compactStyle}
                   value={amountToCurrency(month[balanceTypeOp])}
                   title={
                     Math.abs(month[balanceTypeOp]) > 100000
@@ -82,9 +84,9 @@ export const ReportTableRow = memo(
                   width="flex"
                   privacyFilter
                   style={{
-                    minWidth: compact ? 80 : 125,
-                    ...styles.tnum,
+                    minWidth: compact ? 50 : 85,
                   }}
+                  valueStyle={compactStyle}
                 />
                 <Cell
                   value={amountToCurrency(item.totalDebts)}
@@ -96,9 +98,9 @@ export const ReportTableRow = memo(
                   width="flex"
                   privacyFilter
                   style={{
-                    minWidth: compact ? 80 : 125,
-                    ...styles.tnum,
+                    minWidth: compact ? 50 : 85,
                   }}
+                  valueStyle={compactStyle}
                 />
               </>
             )}
@@ -111,9 +113,9 @@ export const ReportTableRow = memo(
           }
           style={{
             fontWeight: 600,
-            minWidth: compact ? 80 : 125,
-            ...styles.tnum,
+            minWidth: compact ? 50 : 85,
           }}
+          valueStyle={compactStyle}
           width="flex"
           privacyFilter
         />
@@ -126,9 +128,9 @@ export const ReportTableRow = memo(
           }
           style={{
             fontWeight: 600,
-            minWidth: compact ? 80 : 125,
-            ...styles.tnum,
+            minWidth: compact ? 50 : 85,
           }}
+          valueStyle={compactStyle}
           width="flex"
           privacyFilter
         />
diff --git a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableTotals.tsx b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableTotals.tsx
index 5153ae1b0..40228d0d2 100644
--- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableTotals.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableTotals.tsx
@@ -9,7 +9,8 @@ import {
 } from 'loot-core/src/shared/util';
 import { type GroupedEntity } from 'loot-core/src/types/models/reports';
 
-import { styles, theme } from '../../../../style';
+import { theme } from '../../../../style';
+import { type CSSProperties } from '../../../../style/types';
 import { View } from '../../../common/View';
 import { Row, Cell } from '../../../table';
 
@@ -21,6 +22,8 @@ type ReportTableTotalsProps = {
   totalScrollRef: RefProp<HTMLDivElement>;
   handleScroll: UIEventHandler<HTMLDivElement>;
   compact: boolean;
+  style?: CSSProperties;
+  compactStyle?: CSSProperties;
 };
 
 export function ReportTableTotals({
@@ -31,6 +34,8 @@ export function ReportTableTotals({
   totalScrollRef,
   handleScroll,
   compact,
+  style,
+  compactStyle,
 }: ReportTableTotalsProps) {
   const [scrollWidthTotals, setScrollWidthTotals] = useState(0);
 
@@ -58,6 +63,7 @@ export function ReportTableTotals({
         color: theme.tableHeaderText,
         backgroundColor: theme.tableHeaderBackground,
         fontWeight: 600,
+        ...style,
       }}
     >
       <View
@@ -72,10 +78,10 @@ export function ReportTableTotals({
       >
         <Cell
           style={{
-            width: 120,
+            width: compact ? 80 : 125,
             flexShrink: 0,
-            ...styles.tnum,
           }}
+          valueStyle={compactStyle}
           value="Totals"
         />
         {mode === 'time'
@@ -83,9 +89,9 @@ export function ReportTableTotals({
               return (
                 <Cell
                   style={{
-                    minWidth: compact ? 80 : 125,
-                    ...styles.tnum,
+                    minWidth: compact ? 50 : 85,
                   }}
+                  valueStyle={compactStyle}
                   key={amountToCurrency(item[balanceTypeOp])}
                   value={amountToCurrency(item[balanceTypeOp])}
                   title={
@@ -102,9 +108,9 @@ export function ReportTableTotals({
               <>
                 <Cell
                   style={{
-                    minWidth: compact ? 80 : 125,
-                    ...styles.tnum,
+                    minWidth: compact ? 50 : 85,
                   }}
+                  valueStyle={compactStyle}
                   value={amountToCurrency(data.totalAssets)}
                   title={
                     Math.abs(data.totalAssets) > 100000
@@ -116,9 +122,9 @@ export function ReportTableTotals({
                 />
                 <Cell
                   style={{
-                    minWidth: compact ? 80 : 125,
-                    ...styles.tnum,
+                    minWidth: compact ? 50 : 85,
                   }}
+                  valueStyle={compactStyle}
                   value={amountToCurrency(data.totalDebts)}
                   title={
                     Math.abs(data.totalDebts) > 100000
@@ -132,9 +138,9 @@ export function ReportTableTotals({
             )}
         <Cell
           style={{
-            minWidth: compact ? 80 : 125,
-            ...styles.tnum,
+            minWidth: compact ? 50 : 85,
           }}
+          valueStyle={compactStyle}
           value={amountToCurrency(data[balanceTypeOp])}
           title={
             Math.abs(data[balanceTypeOp]) > 100000
@@ -146,9 +152,9 @@ export function ReportTableTotals({
         />
         <Cell
           style={{
-            minWidth: compact ? 80 : 125,
-            ...styles.tnum,
+            minWidth: compact ? 50 : 85,
           }}
+          valueStyle={compactStyle}
           value={integerToCurrency(Math.round(average))}
           title={
             Math.abs(Math.round(average / 100)) > 100000
diff --git a/packages/desktop-client/src/components/reports/reports/CustomReport.jsx b/packages/desktop-client/src/components/reports/reports/CustomReport.jsx
index 97fd06aaa..f786572ef 100644
--- a/packages/desktop-client/src/components/reports/reports/CustomReport.jsx
+++ b/packages/desktop-client/src/components/reports/reports/CustomReport.jsx
@@ -440,6 +440,8 @@ export function CustomReport() {
 
                 {dataCheck ? (
                   <ChooseGraph
+                    startDate={startDate}
+                    endDate={endDate}
                     data={data}
                     mode={mode}
                     graphType={graphType}
@@ -448,7 +450,6 @@ export function CustomReport() {
                     showEmpty={showEmpty}
                     scrollWidth={scrollWidth}
                     setScrollWidth={setScrollWidth}
-                    months={months}
                     viewLabels={viewLabels}
                     compact={false}
                   />
diff --git a/packages/loot-core/src/client/data-hooks/reports.ts b/packages/loot-core/src/client/data-hooks/reports.ts
index 07142d2cb..95b023ff3 100644
--- a/packages/loot-core/src/client/data-hooks/reports.ts
+++ b/packages/loot-core/src/client/data-hooks/reports.ts
@@ -9,11 +9,27 @@ import { useLiveQuery } from '../query-hooks';
 
 function toJS(rows: CustomReportData[]) {
   const reports: CustomReportEntity[] = rows.map(row => {
-    const test: CustomReportEntity = {
-      ...row,
+    const report: CustomReportEntity = {
+      id: row.id,
+      name: row.name,
+      startDate: row.start_date,
+      endDate: row.end_date,
+      isDateStatic: row.date_static === 1,
+      dateRange: row.date_range,
+      mode: row.mode,
+      groupBy: row.group_by,
+      balanceType: row.balance_type,
+      showEmpty: row.show_empty === 1,
+      showOffBudget: row.show_offbudget === 1,
+      showHiddenCategories: row.show_hidden === 1,
+      showUncategorized: row.show_uncategorized === 1,
+      selectedCategories: row.selected_categories,
+      graphType: row.graph_type,
+      conditions: row.conditions,
       conditionsOp: row.conditions_op ?? 'and',
+      data: row.metadata,
     };
-    return test;
+    return report;
   });
   return reports;
 }
diff --git a/packages/loot-core/src/server/reports/app.ts b/packages/loot-core/src/server/reports/app.ts
index e311bed65..d78d09cb4 100644
--- a/packages/loot-core/src/server/reports/app.ts
+++ b/packages/loot-core/src/server/reports/app.ts
@@ -14,7 +14,7 @@ import { ReportsHandlers } from './types/handlers';
 
 const reportModel = {
   validate(report: CustomReportEntity, { update }: { update?: boolean } = {}) {
-    requiredFields('reports', report, ['conditionsOp'], update);
+    requiredFields('Report', report, ['conditionsOp'], update);
 
     if (!update || 'conditionsOp' in report) {
       if (!['and', 'or'].includes(report.conditionsOp)) {
@@ -27,66 +27,121 @@ const reportModel = {
 
   toJS(row: CustomReportData) {
     return {
-      ...row,
+      id: row.id,
+      name: row.name,
+      startDate: row.start_date,
+      endDate: row.end_date,
+      isDateStatic: row.date_static === 1,
+      dateRange: row.date_range,
+      mode: row.mode,
+      groupBy: row.group_by,
+      balanceType: row.balance_type,
+      showEmpty: row.show_empty === 1,
+      showOffBudget: row.show_offbudget === 1,
+      showHiddenCategories: row.show_hidden === 1,
+      showUncategorized: row.show_uncategorized === 1,
+      selectedCategories: row.selected_categories,
+      graphType: row.graph_type,
+      conditions: row.conditions,
       conditionsOp: row.conditions_op,
+      data: row.metadata,
     };
   },
 
   fromJS(report: CustomReportEntity) {
-    const { conditionsOp, ...row }: CustomReportData = report;
-    if (conditionsOp) {
-      row.conditions_op = conditionsOp;
-    }
-    return row;
+    return {
+      id: report.id,
+      name: report.name,
+      start_date: report.startDate,
+      end_date: report.endDate,
+      date_static: report.isDateStatic ? 1 : 0,
+      date_range: report.dateRange,
+      mode: report.mode,
+      group_by: report.groupBy,
+      balance_type: report.balanceType,
+      show_empty: report.showEmpty ? 1 : 0,
+      show_offbudget: report.showOffBudget ? 1 : 0,
+      show_hidden: report.showHiddenCategories ? 1 : 0,
+      show_uncategorized: report.showUncategorized ? 1 : 0,
+      selected_categories: report.selectedCategories,
+      graph_type: report.graphType,
+      conditions: report.conditions,
+      conditions_op: report.conditionsOp,
+      metadata: report.data,
+    };
   },
 };
 
 async function reportNameExists(
-  name: string | undefined,
-  reportId: string | undefined,
+  name: string,
+  reportId: string,
   newItem: boolean,
 ) {
-  if (!name) {
-    throw new Error('Report name is required');
-  }
-
-  if (!reportId) {
-    throw new Error('Report recall error');
-  }
-
   const idForName: { id: string } = await db.first(
-    'SELECT id from reports WHERE tombstone = 0 AND name = ?',
+    'SELECT id from custom_reports WHERE tombstone = 0 AND name = ?',
     [name],
   );
 
-  if (!newItem && idForName.id !== reportId) {
-    throw new Error('There is already a report named ' + name);
+  //no existing name found
+  if (idForName === null) {
+    return false;
+  }
+
+  //for update/rename
+  if (!newItem) {
+    /*
+    -if the found item is the same as the existing item 
+    then no name change was made.
+    -if they are not the same then there is another
+    item with that name already.
+    */
+    return idForName.id !== reportId;
   }
+
+  //default return: item was found but does not match current name
+  return true;
 }
 
 async function createReport(report: CustomReportEntity) {
   const reportId = uuidv4();
-  const item: CustomReportData = {
+  const item: CustomReportEntity = {
     ...report,
     id: reportId,
   };
+  if (!item.name) {
+    throw new Error('Report name is required');
+  }
 
-  reportNameExists(item.name, item.id, true);
+  const nameExists = await reportNameExists(item.name, item.id ?? '', true);
+  if (nameExists) {
+    throw new Error('There is already a filter named ' + item.name);
+  }
 
   // Create the report here based on the info
-  await db.insertWithSchema('reports', reportModel.fromJS(item));
+  await db.insertWithSchema('custom_reports', reportModel.fromJS(item));
 
   return reportId;
 }
 
 async function updateReport(item: CustomReportEntity) {
-  reportNameExists(item.name, item.id, false);
+  if (!item.name) {
+    throw new Error('Report name is required');
+  }
+
+  if (!item.id) {
+    throw new Error('Report recall error');
+  }
+
+  const nameExists = await reportNameExists(item.name, item.id, false);
+  if (nameExists) {
+    throw new Error('There is already a filter named ' + item.name);
+  }
 
-  await db.insertWithSchema('reports', reportModel.fromJS(item));
+  await db.insertWithSchema('custom_reports', reportModel.fromJS(item));
 }
 
 async function deleteReport(id: string) {
-  await db.delete_('reports', id);
+  await db.delete_('custom_reports', id);
 }
 
 // Expose functions to the client
diff --git a/packages/loot-core/src/types/models/reports.d.ts b/packages/loot-core/src/types/models/reports.d.ts
index ef888a2a8..06a6e56e0 100644
--- a/packages/loot-core/src/types/models/reports.d.ts
+++ b/packages/loot-core/src/types/models/reports.d.ts
@@ -71,7 +71,25 @@ export type Month = {
   month: string;
 };
 
-export interface CustomReportData extends CustomReportEntity {
-  conditions_op?: string;
+export interface CustomReportData {
+  id?: string;
+  name?: string;
+  start_date: string;
+  end_date: string;
+  date_static: number;
+  date_range: string;
+  mode: string;
+  group_by: string;
+  balance_type: string;
+  show_empty: number;
+  show_offbudget: number;
+  show_hidden: number;
+  show_uncategorized: number;
+  selected_categories?: CategoryEntity[];
+  graph_type: string;
   conditions?: RuleConditionEntity[];
+  conditions_op: string;
+  metadata?: GroupedEntity;
+  interval?: string;
+  color_scheme?: string;
 }
diff --git a/upcoming-release-notes/2345.md b/upcoming-release-notes/2345.md
new file mode 100644
index 000000000..8e7f48a8a
--- /dev/null
+++ b/upcoming-release-notes/2345.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [carkom]
+---
+
+Changing graph styles so that they can be used for cards on Reports Dashboard. Also updating Entities and create/update calls for saved reports.
-- 
GitLab