mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-11 20:44:32 -05:00
table graphs
This commit is contained in:
@@ -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}
|
||||
/>
|
||||
<ReportTableTotals
|
||||
totalScrollRef={totalScrollRef}
|
||||
|
||||
@@ -7,7 +7,7 @@ import React, {
|
||||
} from 'react';
|
||||
import { type RefProp } from 'react-spring';
|
||||
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
|
||||
import { type CSSProperties } from '../../../../style';
|
||||
import { Block } from '../../../common/Block';
|
||||
@@ -22,12 +22,14 @@ type ReportTableProps = {
|
||||
handleScroll: UIEventHandler<HTMLDivElement>;
|
||||
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<HTMLDivElement>(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({
|
||||
<ReportTableRow
|
||||
item={item}
|
||||
balanceTypeOp={balanceTypeOp}
|
||||
groupByItem={groupByItem}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
groupBy={groupBy}
|
||||
mode={mode}
|
||||
intervalsCount={intervalsCount}
|
||||
compact={compact}
|
||||
style={style}
|
||||
compactStyle={compactStyle}
|
||||
showHiddenCategories={showHiddenCategories}
|
||||
showOffBudget={showOffBudget}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -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 (
|
||||
<View>
|
||||
{data ? (
|
||||
{metadata ? (
|
||||
<View>
|
||||
{data.map((item, index) => {
|
||||
{metadata.map((item, index) => {
|
||||
return (
|
||||
<View key={item.id}>
|
||||
<RenderRow
|
||||
|
||||
@@ -5,34 +5,124 @@ import {
|
||||
amountToInteger,
|
||||
integerToCurrency,
|
||||
} from 'loot-core/src/shared/util';
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
import {
|
||||
type IntervalData,
|
||||
type DataEntity,
|
||||
} from 'loot-core/src/types/models/reports';
|
||||
|
||||
import { useAccounts } from '../../../../hooks/useAccounts';
|
||||
import { useCategories } from '../../../../hooks/useCategories';
|
||||
import { useNavigate } from '../../../../hooks/useNavigate';
|
||||
import { type CSSProperties, theme } from '../../../../style';
|
||||
import { Row, Cell } from '../../../table';
|
||||
|
||||
type ReportTableRowProps = {
|
||||
item: DataEntity;
|
||||
balanceTypeOp: 'totalAssets' | 'totalDebts' | 'totalTotals';
|
||||
groupByItem: 'id' | 'name';
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
groupBy: string;
|
||||
mode: string;
|
||||
intervalsCount: number;
|
||||
compact: boolean;
|
||||
style?: CSSProperties;
|
||||
compactStyle?: CSSProperties;
|
||||
showHiddenCategories?: boolean;
|
||||
showOffBudget?: boolean;
|
||||
};
|
||||
|
||||
export const ReportTableRow = memo(
|
||||
({
|
||||
item,
|
||||
balanceTypeOp,
|
||||
groupByItem,
|
||||
startDate,
|
||||
endDate,
|
||||
groupBy,
|
||||
mode,
|
||||
intervalsCount,
|
||||
compact,
|
||||
style,
|
||||
compactStyle,
|
||||
showHiddenCategories,
|
||||
showOffBudget,
|
||||
}: ReportTableRowProps) => {
|
||||
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 (
|
||||
<Row
|
||||
key={item.id}
|
||||
@@ -45,7 +135,7 @@ export const ReportTableRow = memo(
|
||||
>
|
||||
<Cell
|
||||
value={item[groupByItem]}
|
||||
title={item[groupByItem].length > 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
|
||||
/>
|
||||
<Cell
|
||||
|
||||
@@ -52,6 +52,8 @@ export type ItemEntity = {
|
||||
};
|
||||
|
||||
export type IntervalData = {
|
||||
change: number;
|
||||
dateLookup: string;
|
||||
date: string;
|
||||
totalAssets: number;
|
||||
totalDebts: number;
|
||||
|
||||
Reference in New Issue
Block a user