Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 23 additions & 16 deletions packages/desktop-client/src/components/reports/ReportSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
type CustomReportEntity,
type sortByOpType,
type TimeFrame,
type TransactionEntity,
} from 'loot-core/types/models';
import { type SyncedPrefs } from 'loot-core/types/prefs';

Expand All @@ -39,20 +40,26 @@ type ReportSidebarProps = {
categories: { list: CategoryEntity[]; grouped: CategoryGroupEntity[] };
dateRangeLine: number;
allIntervals: { name: string; pretty: string }[];
setDateRange: (value: string) => void;
setGraphType: (value: string) => void;
setGroupBy: (value: string) => void;
setInterval: (value: string) => void;
setBalanceType: (value: string) => void;
setSortBy: (value: string) => void;
setMode: (value: string) => void;
setIsDateStatic: (value: boolean) => void;
setShowEmpty: (value: boolean) => void;
setShowOffBudget: (value: boolean) => void;
setShowHiddenCategories: (value: boolean) => void;
setShowUncategorized: (value: boolean) => void;
setTrimIntervals: (value: boolean) => void;
setIncludeCurrentInterval: (value: boolean) => void;
setDateRange: (value: CustomReportEntity['dateRange']) => void;
setGraphType: (value: CustomReportEntity['graphType']) => void;
setGroupBy: (value: CustomReportEntity['groupBy']) => void;
setInterval: (value: CustomReportEntity['interval']) => void;
setBalanceType: (value: CustomReportEntity['balanceType']) => void;
setSortBy: (value: CustomReportEntity['sortBy']) => void;
setMode: (value: CustomReportEntity['mode']) => void;
setIsDateStatic: (value: CustomReportEntity['isDateStatic']) => void;
setShowEmpty: (value: CustomReportEntity['showEmpty']) => void;
setShowOffBudget: (value: CustomReportEntity['showOffBudget']) => void;
setShowHiddenCategories: (
value: CustomReportEntity['showHiddenCategories'],
) => void;
setShowUncategorized: (
value: CustomReportEntity['showUncategorized'],
) => void;
setTrimIntervals: (value: CustomReportEntity['trimIntervals']) => void;
setIncludeCurrentInterval: (
value: CustomReportEntity['includeCurrentInterval'],
) => void;
setSelectedCategories: (value: CategoryEntity[]) => void;
onChangeDates: (
dateStart: string,
Expand All @@ -63,8 +70,8 @@ type ReportSidebarProps = {
disabledItems: (type: string) => string[];
defaultItems: (item: string) => void;
defaultModeItems: (graph: string, item: string) => void;
earliestTransaction: string;
latestTransaction: string;
earliestTransaction: TransactionEntity['date'];
latestTransaction: TransactionEntity['date'];
firstDayOfWeekIdx: SyncedPrefs['firstDayOfWeekIdx'];
isComplexCategoryCondition?: boolean;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {

import { GraphButton } from './GraphButton';
import { SaveReportWrapper } from './SaveReport';
import { type SavedStatus } from './SaveReportMenu';
import { setSessionReport } from './setSessionReport';
import { SnapshotButton } from './SnapshotButton';

Expand All @@ -33,7 +34,7 @@ import { FilterButton } from '@desktop-client/components/filters/FiltersMenu';
type ReportTopbarProps = {
customReportItems: CustomReportEntity;
report: CustomReportEntity;
savedStatus: string;
savedStatus: SavedStatus;
setGraphType: (value: string) => void;
viewLegend: boolean;
viewSummary: boolean;
Expand Down
4 changes: 2 additions & 2 deletions packages/desktop-client/src/components/reports/SaveReport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
import { LoadingIndicator } from './LoadingIndicator';
import { SaveReportChoose } from './SaveReportChoose';
import { SaveReportDelete } from './SaveReportDelete';
import { SaveReportMenu } from './SaveReportMenu';
import { SaveReportMenu, type SavedStatus } from './SaveReportMenu';
import { SaveReportName } from './SaveReportName';

import { FormField, FormLabel } from '@desktop-client/components/forms';
Expand All @@ -28,7 +28,7 @@ import { useReports } from '@desktop-client/hooks/useReports';
type SaveReportProps<T extends CustomReportEntity = CustomReportEntity> = {
customReportItems: T;
report: CustomReportEntity;
savedStatus: string;
savedStatus: SavedStatus;
onReportChange: (
params:
| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { useTranslation } from 'react-i18next';

import { Menu, type MenuItem } from '@actual-app/components/menu';

export type SavedStatus = 'saved' | 'new' | 'modified';

export function SaveReportMenu({
onMenuSelect,
savedStatus,
listReports,
}: {
onMenuSelect: (item: string) => void;
savedStatus: string;
savedStatus: SavedStatus;
listReports: number;
}) {
const { t } = useTranslation();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useState } from 'react';
import React, { useEffect, useEffectEvent, useMemo, useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { useLocation, useParams } from 'react-router';

Expand All @@ -20,6 +20,7 @@ import {
type DataEntity,
type RuleConditionEntity,
type sortByOpType,
type TransactionEntity,
} from 'loot-core/types/models';
import { type TransObjectLiteral } from 'loot-core/types/util';

Expand Down Expand Up @@ -52,6 +53,7 @@ import {
import { ReportSidebar } from '@desktop-client/components/reports/ReportSidebar';
import { ReportSummary } from '@desktop-client/components/reports/ReportSummary';
import { ReportTopbar } from '@desktop-client/components/reports/ReportTopbar';
import { type SavedStatus } from '@desktop-client/components/reports/SaveReportMenu';
import { setSessionReport } from '@desktop-client/components/reports/setSessionReport';
import { createCustomSpreadsheet } from '@desktop-client/components/reports/spreadsheets/custom-spreadsheet';
import { createGroupedSpreadsheet } from '@desktop-client/components/reports/spreadsheets/grouped-spreadsheet';
Expand Down Expand Up @@ -168,11 +170,11 @@ function CustomReportInner({ report: initialReport }: CustomReportInnerProps) {
if (['/reports'].includes(prevUrl)) sessionStorage.clear();

const reportFromSessionStorage = sessionStorage.getItem('report');
const session = reportFromSessionStorage
const session: Partial<CustomReportEntity> = reportFromSessionStorage
? JSON.parse(reportFromSessionStorage)
: {};
const combine = initialReport ?? defaultReport;
const loadReport = { ...combine, ...session };
const loadReport: CustomReportEntity = { ...combine, ...session };

const [allIntervals, setAllIntervals] = useState<
Array<{
Expand Down Expand Up @@ -274,39 +276,44 @@ function CustomReportInner({ report: initialReport }: CustomReportInnerProps) {
const [intervals, setIntervals] = useState(
monthUtils.rangeInclusive(startDate, endDate),
);
const [earliestTransaction, setEarliestTransaction] = useState('');
const [latestTransaction, setLatestTransaction] = useState('');
const [earliestTransactionDate, setEarliestTransactionDate] =
useState<TransactionEntity['date']>('');
const [latestTransactionDate, setLatestTransactionDate] =
useState<TransactionEntity['date']>('');
const [report, setReport] = useState(loadReport);
const [savedStatus, setSavedStatus] = useState(
session.savedStatus ?? (initialReport ? 'saved' : 'new'),
const [savedStatus, setSavedStatus] = useState<SavedStatus>(
'savedStatus' in session
? (session.savedStatus as SavedStatus)
: initialReport
? 'saved'
: 'new',
);

useEffect(() => {
async function run() {
const onApplyFilterConditions = useEffectEvent(
(
currentConditions?: RuleConditionEntity[],
currentConditionsOp?: RuleConditionEntity['conditionsOp'],
) => {
onApplyFilter(null);

const filtersToApply =
savedStatus !== 'saved' ? conditions : report.conditions;
savedStatus !== 'saved' ? conditions : currentConditions;
const conditionsOpToApply =
savedStatus !== 'saved' ? conditionsOp : report.conditionsOp;
savedStatus !== 'saved' ? conditionsOp : currentConditionsOp;

filtersToApply?.forEach((condition: RuleConditionEntity) =>
onApplyFilter(condition),
);
onConditionsOpChange(conditionsOpToApply);

const earliestTransaction = await send('get-earliest-transaction');
setEarliestTransaction(
earliestTransaction
? earliestTransaction.date
: monthUtils.currentDay(),
);

const latestTransaction = await send('get-latest-transaction');
setLatestTransaction(
latestTransaction ? latestTransaction.date : monthUtils.currentDay(),
);
filtersToApply?.forEach(onApplyFilter);
if (conditionsOpToApply) {
onConditionsOpChange(conditionsOpToApply);
}
},
);
Comment thread
coderabbitai[bot] marked this conversation as resolved.

const onSetAllIntervals = useEffectEvent(
async (
earliestTransaction: TransactionEntity,
latestTransaction: TransactionEntity,
interval: CustomReportEntity['interval'],
) => {
const fromDate =
interval === 'Weekly'
? 'dayFromDate'
Expand Down Expand Up @@ -380,7 +387,17 @@ function CustomReportInner({ report: initialReport }: CustomReportInnerProps) {
.reverse();

setAllIntervals(allIntervalsMap);
},
);

const onSetStartAndEndDates = useEffectEvent(
(
earliestTransaction: TransactionEntity,
latestTransaction: TransactionEntity,
dateRange: CustomReportEntity['dateRange'],
isDateStatic: CustomReportEntity['isDateStatic'],
includeCurrentInterval: CustomReportEntity['includeCurrentInterval'],
) => {
if (!isDateStatic) {
const [dateStart, dateEnd] = getLiveRange(
dateRange,
Expand All @@ -394,22 +411,44 @@ function CustomReportInner({ report: initialReport }: CustomReportInnerProps) {
setStartDate(dateStart);
setEndDate(dateEnd);
}
},
);

useEffect(() => {
async function run() {
onApplyFilterConditions(report.conditions, report.conditionsOp);

const earliestTransaction = await send('get-earliest-transaction');
setEarliestTransactionDate(
earliestTransaction
? earliestTransaction.date
: monthUtils.currentDay(),
);

const latestTransaction = await send('get-latest-transaction');
setLatestTransactionDate(
latestTransaction ? latestTransaction.date : monthUtils.currentDay(),
);

onSetAllIntervals(earliestTransaction, latestTransaction, interval);
onSetStartAndEndDates(
earliestTransaction,
latestTransaction,
dateRange,
isDateStatic,
includeCurrentInterval,
);
}

run();
// omitted `conditions` and `conditionsOp` from dependencies to avoid infinite loops
// oxlint-disable-next-line react/exhaustive-deps
}, [
interval,
dateRange,
firstDayOfWeekIdx,
isDateStatic,
onApplyFilter,
onConditionsOpChange,
report.conditions,
report.conditionsOp,
includeCurrentInterval,
locale,
savedStatus,
]);
Comment thread
matt-fidd marked this conversation as resolved.

Expand Down Expand Up @@ -619,7 +658,7 @@ function CustomReportInner({ report: initialReport }: CustomReportInnerProps) {
const defaultSort = defaultsGraphList(mode, chooseGraph, 'defaultSort');
if (defaultSort) {
setSessionReport('sortBy', defaultSort);
setSortBy(defaultSort);
setSortBy(defaultSort as CustomReportEntity['sortBy']);
}
};

Expand Down Expand Up @@ -834,8 +873,8 @@ function CustomReportInner({ report: initialReport }: CustomReportInnerProps) {
disabledItems={disabledItems}
defaultItems={defaultItems}
defaultModeItems={defaultModeItems}
earliestTransaction={earliestTransaction}
latestTransaction={latestTransaction}
earliestTransaction={earliestTransactionDate}
latestTransaction={latestTransactionDate}
firstDayOfWeekIdx={firstDayOfWeekIdx}
isComplexCategoryCondition={isComplexCategoryCondition}
/>
Expand Down
2 changes: 1 addition & 1 deletion packages/loot-core/src/types/models/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type BaseConditionEntity<
month?: boolean;
year?: boolean;
};
conditionsOp?: string;
conditionsOp?: 'and' | 'or';
type?: 'id' | 'boolean' | 'date' | 'number' | 'string';
customName?: string;
queryFilter?: Record<string, { $oneof: string[] }>;
Expand Down
6 changes: 6 additions & 0 deletions upcoming-release-notes/6867.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Maintenance
authors: [joel-jeremy]
---

Fix type safety issues and react-hooks/exhaustive-deps errors in CustomReport
Loading