From c96c957a34244a899c75079e39988976e101e0cb Mon Sep 17 00:00:00 2001
From: Ryan Bianchi <1435081+qedi-r@users.noreply.github.com>
Date: Thu, 4 Apr 2024 10:38:30 -0400
Subject: [PATCH] modify existing LineGraph to track budget items over time
 (#2506)

* modify exiting LineGraph to track budget items over time

* linter pass 1

* increase line weight, add sorting and colour to tooltip

* second lint pass

* add release note

* use new disabledLists, format tooltip, other nits from review

* add margins to LineGraph

* adding missed linting

* remove new line icon, add disable options for split, legend, label

* Update ReportTopbar.jsx

Remove unneeded lines

* lint fix

* SVGChart

---------

Co-authored-by: Neil <55785687+carkom@users.noreply.github.com>
---
 .../src/components/reports/ChooseGraph.tsx    |  6 +--
 .../src/components/reports/ReportTopbar.jsx   | 14 +++++
 .../src/components/reports/disabledList.ts    | 11 +++-
 .../reports/graphs/BarLineGraph.tsx           |  8 +--
 .../components/reports/graphs/LineGraph.tsx   | 52 ++++++++++++-------
 upcoming-release-notes/2506.md                |  6 +++
 6 files changed, 70 insertions(+), 27 deletions(-)
 create mode 100644 upcoming-release-notes/2506.md

diff --git a/packages/desktop-client/src/components/reports/ChooseGraph.tsx b/packages/desktop-client/src/components/reports/ChooseGraph.tsx
index ab945112d..1e47c0c61 100644
--- a/packages/desktop-client/src/components/reports/ChooseGraph.tsx
+++ b/packages/desktop-client/src/components/reports/ChooseGraph.tsx
@@ -108,9 +108,7 @@ export function ChooseGraph({
     );
   }
   if (graphType === 'BarLineGraph') {
-    return (
-      <BarLineGraph style={graphStyle} compact={compact} graphData={data} />
-    );
+    return <BarLineGraph style={graphStyle} compact={compact} data={data} />;
   }
   if (graphType === 'DonutGraph') {
     return (
@@ -125,7 +123,7 @@ export function ChooseGraph({
     );
   }
   if (graphType === 'LineGraph') {
-    return <LineGraph style={graphStyle} compact={compact} graphData={data} />;
+    return <LineGraph style={graphStyle} compact={compact} data={data} />;
   }
   if (graphType === 'StackedBarGraph') {
     return (
diff --git a/packages/desktop-client/src/components/reports/ReportTopbar.jsx b/packages/desktop-client/src/components/reports/ReportTopbar.jsx
index 2051aca8c..ab23885b0 100644
--- a/packages/desktop-client/src/components/reports/ReportTopbar.jsx
+++ b/packages/desktop-client/src/components/reports/ReportTopbar.jsx
@@ -2,6 +2,7 @@ import React from 'react';
 
 import {
   SvgCalculator,
+  SvgChart,
   SvgChartBar,
   SvgChartPie,
   SvgListBullet,
@@ -76,6 +77,19 @@ export function ReportTopbar({
       >
         <SvgChartBar width={15} height={15} />
       </GraphButton>
+      <GraphButton
+        title="Line Graph"
+        selected={customReportItems.graphType === 'LineGraph'}
+        onSelect={() => {
+          onReportChange({ type: 'modify' });
+          setGraphType('LineGraph');
+          defaultItems('LineGraph');
+        }}
+        style={{ marginRight: 15 }}
+        disabled={disabledItems('LineGraph')}
+      >
+        <SvgChart width={15} height={15} />
+      </GraphButton>
       <GraphButton
         title="Area Graph"
         selected={customReportItems.graphType === 'AreaGraph'}
diff --git a/packages/desktop-client/src/components/reports/disabledList.ts b/packages/desktop-client/src/components/reports/disabledList.ts
index b8fdb89d4..7b5a94122 100644
--- a/packages/desktop-client/src/components/reports/disabledList.ts
+++ b/packages/desktop-client/src/components/reports/disabledList.ts
@@ -49,13 +49,22 @@ const timeGraphOptions = [
     disabledType: ['Net'],
     defaultType: 'Payment',
   },
+  {
+    description: 'LineGraph',
+    disabledSplit: ['Interval'],
+    defaultSplit: 'Category',
+    disabledType: ['Net'],
+    defaultType: 'Payment',
+    disableLegend: false,
+    disableLabel: true,
+  },
 ];
 
 const modeOptions = [
   {
     description: 'total',
     graphs: totalGraphOptions,
-    disabledGraph: [],
+    disabledGraph: ['LineGraph'],
     defaultGraph: 'TableGraph',
   },
   {
diff --git a/packages/desktop-client/src/components/reports/graphs/BarLineGraph.tsx b/packages/desktop-client/src/components/reports/graphs/BarLineGraph.tsx
index 26e823288..ffdac1e01 100644
--- a/packages/desktop-client/src/components/reports/graphs/BarLineGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/BarLineGraph.tsx
@@ -71,11 +71,11 @@ const CustomTooltip = ({ active, payload }: CustomTooltipProps) => {
 
 type BarLineGraphProps = {
   style?: CSSProperties;
-  graphData;
+  data;
   compact?: boolean;
 };
 
-export function BarLineGraph({ style, graphData, compact }: BarLineGraphProps) {
+export function BarLineGraph({ style, data, compact }: BarLineGraphProps) {
   const tickFormatter = tick => {
     return `${Math.round(tick).toLocaleString()}`; // Formats the tick values as strings with commas
   };
@@ -88,14 +88,14 @@ export function BarLineGraph({ style, graphData, compact }: BarLineGraphProps) {
       }}
     >
       {(width, height) =>
-        graphData && (
+        data && (
           <ResponsiveContainer>
             <div>
               {!compact && <div style={{ marginTop: '15px' }} />}
               <ComposedChart
                 width={width}
                 height={height}
-                data={graphData.data}
+                data={data.data}
                 margin={{ top: 0, right: 0, left: 0, bottom: 0 }}
               >
                 <Tooltip
diff --git a/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx b/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx
index 819528439..2fe7f59bc 100644
--- a/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx
@@ -12,6 +12,8 @@ import {
   ResponsiveContainer,
 } from 'recharts';
 
+import { amountToCurrency } from 'loot-core/src/shared/util';
+
 import { theme } from '../../../style';
 import { type CSSProperties } from '../../../style';
 import { AlignedText } from '../../common/AlignedText';
@@ -20,12 +22,12 @@ import { Container } from '../Container';
 import { numberFormatterTooltip } from '../numberFormatter';
 
 type PayloadItem = {
+  dataKey: string;
+  value: number;
+  date: string;
+  color: string;
   payload: {
     date: string;
-    assets: number | string;
-    debt: number | string;
-    networth: number | string;
-    change: number | string;
   };
 };
 
@@ -54,12 +56,16 @@ const CustomTooltip = ({ active, payload }: CustomTooltipProps) => {
           </div>
           <div style={{ lineHeight: 1.5 }}>
             <PrivacyFilter>
-              <AlignedText left="Assets:" right={payload[0].payload.assets} />
-              <AlignedText left="Debt:" right={payload[0].payload.debt} />
-              <AlignedText
-                left="Change:"
-                right={<strong>{payload[0].payload.change}</strong>}
-              />
+              {payload
+                .sort((p1: PayloadItem, p2: PayloadItem) => p2.value - p1.value)
+                .map((p: PayloadItem, index: number) => (
+                  <AlignedText
+                    key={index}
+                    left={p.dataKey}
+                    right={amountToCurrency(p.value)}
+                    style={{ color: p.color }}
+                  />
+                ))}
             </PrivacyFilter>
           </div>
         </div>
@@ -70,11 +76,11 @@ const CustomTooltip = ({ active, payload }: CustomTooltipProps) => {
 
 type LineGraphProps = {
   style?: CSSProperties;
-  graphData;
+  data;
   compact?: boolean;
 };
 
-export function LineGraph({ style, graphData, compact }: LineGraphProps) {
+export function LineGraph({ style, data, compact }: LineGraphProps) {
   const tickFormatter = tick => {
     return `${Math.round(tick).toLocaleString()}`; // Formats the tick values as strings with commas
   };
@@ -87,15 +93,15 @@ export function LineGraph({ style, graphData, compact }: LineGraphProps) {
       }}
     >
       {(width, height) =>
-        graphData && (
+        data && (
           <ResponsiveContainer>
             <div>
               {!compact && <div style={{ marginTop: '15px' }} />}
               <LineChart
                 width={width}
                 height={height}
-                data={graphData.data}
-                margin={{ top: 0, right: 0, left: 0, bottom: 0 }}
+                data={data.intervalData}
+                margin={{ top: 10, right: 10, left: 10, bottom: 10 }}
               >
                 <Tooltip
                   content={<CustomTooltip />}
@@ -105,11 +111,21 @@ export function LineGraph({ style, graphData, compact }: LineGraphProps) {
                 {!compact && (
                   <>
                     <CartesianGrid strokeDasharray="3 3" />
-                    <XAxis dataKey="x" />
-                    <YAxis dataKey="y" tickFormatter={tickFormatter} />
+                    <XAxis dataKey="date" />
+                    <YAxis name="Value" tickFormatter={tickFormatter} />
                   </>
                 )}
-                <Line type="monotone" dataKey="y" stroke="#8884d8" />
+                {data.legend.map((entry, index) => {
+                  return (
+                    <Line
+                      key={index}
+                      strokeWidth={2}
+                      type="monotone"
+                      dataKey={entry.name}
+                      stroke={entry.color}
+                    />
+                  );
+                })}
               </LineChart>
             </div>
           </ResponsiveContainer>
diff --git a/upcoming-release-notes/2506.md b/upcoming-release-notes/2506.md
new file mode 100644
index 000000000..cb2e47361
--- /dev/null
+++ b/upcoming-release-notes/2506.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [qedi-r]
+---
+
+Add line chart option for displaying budget amounts over time
\ No newline at end of file
-- 
GitLab