diff --git a/packages/desktop-client/src/components/reports/ChooseGraph.tsx b/packages/desktop-client/src/components/reports/ChooseGraph.tsx index 4f0ec48850..82aecf07dc 100644 --- a/packages/desktop-client/src/components/reports/ChooseGraph.tsx +++ b/packages/desktop-client/src/components/reports/ChooseGraph.tsx @@ -55,12 +55,6 @@ export function ChooseGraph({ const intervals: string[] = monthUtils.rangeInclusive(startDate, endDate); const graphStyle = compact ? { ...style } : { flexGrow: 1 }; const balanceTypeOp = ReportOptions.balanceTypeMap.get(balanceType); - const groupByData = - groupBy === 'Category' - ? 'groupedData' - : groupBy === 'Interval' - ? 'intervalData' - : 'data'; const saveScrollWidth = value => { setScrollWidth(!value ? 0 : value); @@ -175,12 +169,14 @@ export function ChooseGraph({ handleScroll={handleScroll} balanceTypeOp={balanceTypeOp} groupBy={groupBy} - data={data[groupByData]} + data={data} mode={mode} intervalsCount={intervals.length} compact={compact} style={rowStyle} compactStyle={compactStyle} + showHiddenCategories={showHiddenCategories} + showOffBudget={showOffBudget} /> ; groupBy: string; balanceTypeOp: 'totalDebts' | 'totalTotals' | 'totalAssets'; - data: DataEntity[]; + data: GroupedEntity; mode: string; intervalsCount: number; compact: boolean; style?: CSSProperties; compactStyle?: CSSProperties; + showHiddenCategories?: boolean; + showOffBudget?: boolean; }; export function ReportTable({ @@ -42,6 +44,8 @@ export function ReportTable({ compact, style, compactStyle, + showHiddenCategories, + showOffBudget, }: ReportTableProps) { const contentRef = useRef(null); @@ -54,7 +58,9 @@ export function ReportTable({ const renderItem = useCallback( ({ item, - groupByItem, + startDate, + endDate, + groupBy, mode, intervalsCount, compact, @@ -65,12 +71,16 @@ export function ReportTable({ ); }, 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 1cdc0e160b..185991469c 100644 --- a/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx +++ b/packages/desktop-client/src/components/reports/graphs/tableGraph/ReportTableList.tsx @@ -1,14 +1,14 @@ // @ts-strict-ignore import React from 'react'; -import { type DataEntity } from 'loot-core/src/types/models/reports'; +import { type GroupedEntity } from 'loot-core/src/types/models/reports'; import { type CSSProperties, theme } from '../../../../style'; import { View } from '../../../common/View'; import { Row } from '../../../table'; type ReportTableListProps = { - data: DataEntity[]; + data: GroupedEntity; mode?: string; intervalsCount?: number; groupBy: string; @@ -16,6 +16,8 @@ type ReportTableListProps = { compact: boolean; style?: CSSProperties; compactStyle?: CSSProperties; + showHiddenCategories?: boolean; + showOffBudget?: boolean; }; export function ReportTableList({ @@ -27,8 +29,16 @@ export function ReportTableList({ compact, style, compactStyle, + showHiddenCategories, + showOffBudget, }: ReportTableListProps) { - const groupByItem = groupBy === 'Interval' ? 'date' : 'name'; + const groupByData = + groupBy === 'Category' + ? 'groupedData' + : groupBy === 'Interval' + ? 'intervalData' + : 'data'; + const metadata = data[groupByData]; type RenderRowProps = { index: number; @@ -46,25 +56,29 @@ export function ReportTableList({ }: RenderRowProps) { const item = parent_index === undefined - ? data[index] - : data[parent_index].categories[index]; + ? metadata[index] + : metadata[parent_index].categories[index]; return renderItem({ item, - groupByItem, + startDate: data.startDate, + endDate: data.endDate, + groupBy, mode, intervalsCount, compact, style, compactStyle, + showHiddenCategories, + showOffBudget, }); } return ( - {data ? ( + {metadata ? ( - {data.map((item, index) => { + {metadata.map((item, index) => { return ( { const average = amountToInteger(item[balanceTypeOp]) / intervalsCount; + const isClickable = groupBy !== 'Interval' && !item.categories; + const groupByItem = groupBy === 'Interval' ? 'date' : 'name'; + + const navigate = useNavigate(); + const categories = useCategories(); + const accounts = useAccounts(); + + const onShowActivity = (item: DataEntity, intervalItem?: IntervalData) => { + const amount = balanceTypeOp === 'totalDebts' ? 'lte' : 'gte'; + const field = groupBy === 'Interval' ? null : groupBy.toLowerCase(); + const hiddenCategories = categories.list + .filter(f => f.hidden) + .map(e => e.id); + const offBudgetAccounts = accounts + .filter(f => f.offbudget) + .map(e => e.id); + const getDate = + mode === 'time' + ? [ + { + field: 'date', + op: 'is', + value: intervalItem ? intervalItem.dateLookup : null, + options: { date: true }, + }, + ] + : [ + { + field: 'date', + op: 'gte', + value: startDate, + options: { date: true }, + type: 'date', + }, + { + field: 'date', + op: 'lte', + value: endDate, + options: { date: true }, + type: 'date', + }, + ]; + + const conditions = [ + { field, op: 'is', value: item.id, type: 'id' }, + ...getDate, + balanceTypeOp !== 'totalTotals' && { + field: 'amount', + op: amount, + value: 0, + type: 'number', + }, + hiddenCategories.length > 0 && + !showHiddenCategories && { + field: 'category', + op: 'notOneOf', + value: hiddenCategories, + type: 'id', + }, + offBudgetAccounts.length > 0 && + !showOffBudget && { + field: 'account', + op: 'notOneOf', + value: offBudgetAccounts, + type: 'id', + }, + ].filter(f => f); + navigate('/accounts', { + state: { + goBack: true, + conditions, + categoryId: item.id, + }, + }); + }; + return ( 12 ? item[groupByItem] : undefined} + title={item[groupByItem] ?? undefined} style={{ width: compact ? 80 : 125, flexShrink: 0, @@ -59,6 +149,7 @@ export const ReportTableRow = memo( key={amountToCurrency(intervalItem[balanceTypeOp])} style={{ minWidth: compact ? 50 : 85, + cursor: isClickable ? 'pointer' : 'inherit', }} valueStyle={compactStyle} value={amountToCurrency(intervalItem[balanceTypeOp])} @@ -68,6 +159,9 @@ export const ReportTableRow = memo( : undefined } width="flex" + onClick={() => + isClickable && onShowActivity(item, intervalItem) + } privacyFilter /> ); @@ -114,9 +208,11 @@ export const ReportTableRow = memo( style={{ fontWeight: 600, minWidth: compact ? 50 : 85, + cursor: isClickable ? 'pointer' : 'inherit', }} valueStyle={compactStyle} width="flex" + onClick={() => isClickable && onShowActivity(item)} privacyFilter />