mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-09 03:32:54 -05:00
* TS strict changes * notes * renderRowProps * RenderTableRow
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// @ts-strict-ignore
|
||||
import React, { useRef } from 'react';
|
||||
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
|
||||
|
||||
import { type CSSProperties } from '../../style';
|
||||
@@ -20,7 +20,7 @@ import { ReportTableTotals } from './graphs/tableGraph/ReportTableTotals';
|
||||
import { ReportOptions } from './ReportOptions';
|
||||
|
||||
type ChooseGraphProps = {
|
||||
data: GroupedEntity;
|
||||
data: DataEntity;
|
||||
filters?: RuleConditionEntity[];
|
||||
mode: string;
|
||||
graphType: string;
|
||||
@@ -160,13 +160,14 @@ export function ChooseGraph({
|
||||
<ReportTableHeader
|
||||
headerScrollRef={headerScrollRef}
|
||||
handleScroll={handleScroll}
|
||||
data={mode === 'time' && data.intervalData}
|
||||
data={data.intervalData}
|
||||
groupBy={groupBy}
|
||||
interval={interval}
|
||||
balanceType={balanceType}
|
||||
compact={compact}
|
||||
style={rowStyle}
|
||||
compactStyle={compactStyle}
|
||||
mode={mode}
|
||||
/>
|
||||
<ReportTable
|
||||
saveScrollWidth={saveScrollWidth}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-strict-ignore
|
||||
import React from 'react';
|
||||
|
||||
import * as monthUtils from 'loot-core/src/shared/months';
|
||||
@@ -7,7 +6,7 @@ import {
|
||||
integerToCurrency,
|
||||
amountToInteger,
|
||||
} from 'loot-core/src/shared/util';
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
|
||||
import { theme, styles } from '../../style';
|
||||
import { Text } from '../common/Text';
|
||||
@@ -19,8 +18,8 @@ import { ReportOptions } from './ReportOptions';
|
||||
type ReportSummaryProps = {
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
data: GroupedEntity;
|
||||
balanceTypeOp: string;
|
||||
data: DataEntity;
|
||||
balanceTypeOp: 'totalDebts' | 'totalAssets' | 'totalTotals';
|
||||
interval: string;
|
||||
intervalsCount: number;
|
||||
};
|
||||
@@ -63,20 +62,20 @@ export function ReportSummary({
|
||||
>
|
||||
{monthUtils.format(
|
||||
startDate,
|
||||
ReportOptions.intervalFormat.get(interval),
|
||||
ReportOptions.intervalFormat.get(interval) || '',
|
||||
)}
|
||||
{monthUtils.format(
|
||||
startDate,
|
||||
ReportOptions.intervalFormat.get(interval),
|
||||
ReportOptions.intervalFormat.get(interval) || '',
|
||||
) !==
|
||||
monthUtils.format(
|
||||
endDate,
|
||||
ReportOptions.intervalFormat.get(interval),
|
||||
ReportOptions.intervalFormat.get(interval) || '',
|
||||
) &&
|
||||
' to ' +
|
||||
monthUtils.format(
|
||||
endDate,
|
||||
ReportOptions.intervalFormat.get(interval),
|
||||
ReportOptions.intervalFormat.get(interval) || '',
|
||||
)}
|
||||
</Text>
|
||||
</View>
|
||||
@@ -153,7 +152,7 @@ export function ReportSummary({
|
||||
</PrivacyFilter>
|
||||
</Text>
|
||||
<Text style={{ fontWeight: 600 }}>
|
||||
Per {ReportOptions.intervalMap.get(interval).toLowerCase()}
|
||||
Per {(ReportOptions.intervalMap.get(interval) || '').toLowerCase()}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
amountToCurrency,
|
||||
amountToCurrencyNoDecimal,
|
||||
} from 'loot-core/src/shared/util';
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
|
||||
import { usePrivacyMode } from '../../../hooks/usePrivacyMode';
|
||||
import { useResponsive } from '../../../ResponsiveProvider';
|
||||
@@ -105,14 +105,14 @@ const customLabel = (props, width, end) => {
|
||||
const textAnchor = props.index === 0 ? 'left' : 'middle';
|
||||
const display =
|
||||
props.value !== 0 && `${amountToCurrencyNoDecimal(props.value)}`;
|
||||
const textSize = adjustTextSize(width, 'area');
|
||||
const textSize = adjustTextSize({ sized: width, type: 'area' });
|
||||
|
||||
return renderCustomLabel(calcX, calcY, textAnchor, display, textSize);
|
||||
};
|
||||
|
||||
type AreaGraphProps = {
|
||||
style?: CSSProperties;
|
||||
data: GroupedEntity;
|
||||
data: DataEntity;
|
||||
balanceTypeOp: string;
|
||||
compact?: boolean;
|
||||
viewLabels: boolean;
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
amountToCurrency,
|
||||
amountToCurrencyNoDecimal,
|
||||
} from 'loot-core/src/shared/util';
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
|
||||
|
||||
import { useAccounts } from '../../../hooks/useAccounts';
|
||||
@@ -122,18 +122,18 @@ const customLabel = (props, typeOp) => {
|
||||
const textAnchor = 'middle';
|
||||
const display =
|
||||
props.value !== 0 && `${amountToCurrencyNoDecimal(props.value)}`;
|
||||
const textSize = adjustTextSize(
|
||||
props.width,
|
||||
typeOp === 'totalTotals' ? 'default' : 'variable',
|
||||
props.value,
|
||||
);
|
||||
const textSize = adjustTextSize({
|
||||
sized: props.width,
|
||||
type: typeOp === 'totalTotals' ? 'default' : 'variable',
|
||||
values: props.value,
|
||||
});
|
||||
|
||||
return renderCustomLabel(calcX, calcY, textAnchor, display, textSize);
|
||||
};
|
||||
|
||||
type BarGraphProps = {
|
||||
style?: CSSProperties;
|
||||
data: GroupedEntity;
|
||||
data: DataEntity;
|
||||
filters: RuleConditionEntity[];
|
||||
groupBy: string;
|
||||
balanceTypeOp: string;
|
||||
|
||||
@@ -4,7 +4,7 @@ import React, { useState } from 'react';
|
||||
import { PieChart, Pie, Cell, Sector, ResponsiveContainer } from 'recharts';
|
||||
|
||||
import { amountToCurrency } from 'loot-core/src/shared/util';
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
|
||||
|
||||
import { useAccounts } from '../../../hooks/useAccounts';
|
||||
@@ -158,7 +158,7 @@ const customLabel = props => {
|
||||
const calcY = props.cy + radius * Math.sin(-props.midAngle * RADIAN);
|
||||
const textAnchor = calcX > props.cx ? 'start' : 'end';
|
||||
const display = props.value !== 0 && `${(props.percent * 100).toFixed(0)}%`;
|
||||
const textSize = adjustTextSize(size, 'donut');
|
||||
const textSize = adjustTextSize({ sized: size, type: 'donut' });
|
||||
const showLabel = props.percent;
|
||||
const showLabelThreshold = 0.05;
|
||||
const fill = theme.reportsInnerLabel;
|
||||
@@ -177,7 +177,7 @@ const customLabel = props => {
|
||||
|
||||
type DonutGraphProps = {
|
||||
style?: CSSProperties;
|
||||
data: GroupedEntity;
|
||||
data: DataEntity;
|
||||
filters: RuleConditionEntity[];
|
||||
groupBy: string;
|
||||
balanceTypeOp: string;
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
amountToCurrency,
|
||||
amountToCurrencyNoDecimal,
|
||||
} from 'loot-core/src/shared/util';
|
||||
import { type GroupedEntity } from 'loot-core/types/models/reports';
|
||||
import { type DataEntity } from 'loot-core/types/models/reports';
|
||||
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
|
||||
|
||||
import { useAccounts } from '../../../hooks/useAccounts';
|
||||
@@ -109,7 +109,7 @@ const CustomTooltip = ({
|
||||
|
||||
type LineGraphProps = {
|
||||
style?: CSSProperties;
|
||||
data: GroupedEntity;
|
||||
data: DataEntity;
|
||||
filters: RuleConditionEntity[];
|
||||
groupBy: string;
|
||||
compact?: boolean;
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
amountToCurrency,
|
||||
amountToCurrencyNoDecimal,
|
||||
} from 'loot-core/src/shared/util';
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
|
||||
|
||||
import { useAccounts } from '../../../hooks/useAccounts';
|
||||
@@ -138,7 +138,7 @@ const customLabel = props => {
|
||||
|
||||
type StackedBarGraphProps = {
|
||||
style?: CSSProperties;
|
||||
data: GroupedEntity;
|
||||
data: DataEntity;
|
||||
filters: RuleConditionEntity[];
|
||||
groupBy: string;
|
||||
compact?: boolean;
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
// @ts-strict-ignore
|
||||
export const adjustTextSize = (
|
||||
sized: number,
|
||||
type: string,
|
||||
values?: number,
|
||||
): `${number}px` => {
|
||||
let source;
|
||||
export const adjustTextSize = ({
|
||||
sized,
|
||||
type,
|
||||
values = 0,
|
||||
}: {
|
||||
sized: number;
|
||||
type: string;
|
||||
values?: number;
|
||||
}): `${number}px` => {
|
||||
let source: {
|
||||
size: number;
|
||||
font: number;
|
||||
}[] = [{ size: -1, font: -1 }];
|
||||
switch (type) {
|
||||
case 'variable':
|
||||
source = variableLookup.find(({ value }) => values >= value).arr;
|
||||
const findLookup = variableLookup.find(({ value }) => values >= value);
|
||||
if (!findLookup) {
|
||||
break;
|
||||
}
|
||||
source = findLookup.arr;
|
||||
break;
|
||||
case 'donut':
|
||||
source = donutLookup;
|
||||
@@ -15,8 +25,12 @@ export const adjustTextSize = (
|
||||
default:
|
||||
source = defaultLookup;
|
||||
}
|
||||
const lookup = source.find(({ size }) => sized >= size);
|
||||
return `${lookup.font}px`;
|
||||
const findSource = source.find(({ size }) => sized >= size);
|
||||
if (!findSource) {
|
||||
return '13px';
|
||||
}
|
||||
|
||||
return `${findSource.font}px`;
|
||||
};
|
||||
|
||||
const defaultLookup = [
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import React, { type ReactNode } from 'react';
|
||||
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
|
||||
import { type CSSProperties } from '../../../../style';
|
||||
import { View } from '../../../common/View';
|
||||
|
||||
import { type renderRowProps } from './ReportTable';
|
||||
|
||||
type RenderTableRowProps = {
|
||||
index: number;
|
||||
parent_index?: number;
|
||||
compact: boolean;
|
||||
renderRow: (arg: renderRowProps) => ReactNode;
|
||||
intervalsCount: number;
|
||||
mode: string;
|
||||
metadata: GroupedEntity[];
|
||||
style?: CSSProperties;
|
||||
compactStyle?: CSSProperties;
|
||||
};
|
||||
|
||||
export function RenderTableRow({
|
||||
index,
|
||||
parent_index,
|
||||
compact,
|
||||
renderRow,
|
||||
intervalsCount,
|
||||
mode,
|
||||
metadata,
|
||||
style,
|
||||
compactStyle,
|
||||
}: RenderTableRowProps) {
|
||||
const child = metadata[index];
|
||||
const parent =
|
||||
parent_index !== undefined ? metadata[parent_index] : ({} as GroupedEntity);
|
||||
|
||||
const item =
|
||||
parent_index === undefined
|
||||
? child
|
||||
: (parent.categories && parent.categories[index]) ||
|
||||
({} as GroupedEntity);
|
||||
|
||||
return (
|
||||
<View>
|
||||
{renderRow({
|
||||
item,
|
||||
mode,
|
||||
intervalsCount,
|
||||
compact,
|
||||
style,
|
||||
compactStyle,
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
// @ts-strict-ignore
|
||||
import React, {
|
||||
type RefObject,
|
||||
useCallback,
|
||||
useLayoutEffect,
|
||||
useRef,
|
||||
type UIEventHandler,
|
||||
} from 'react';
|
||||
import { type RefProp } from 'react-spring';
|
||||
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
import {
|
||||
type GroupedEntity,
|
||||
type DataEntity,
|
||||
} from 'loot-core/src/types/models/reports';
|
||||
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
|
||||
|
||||
import { type CSSProperties } from '../../../../style';
|
||||
@@ -19,11 +21,11 @@ import { ReportTableRow } from './ReportTableRow';
|
||||
|
||||
type ReportTableProps = {
|
||||
saveScrollWidth: (value: number) => void;
|
||||
listScrollRef: RefProp<HTMLDivElement>;
|
||||
listScrollRef: RefObject<HTMLDivElement>;
|
||||
handleScroll: UIEventHandler<HTMLDivElement>;
|
||||
groupBy: string;
|
||||
balanceTypeOp: 'totalDebts' | 'totalTotals' | 'totalAssets';
|
||||
data: GroupedEntity;
|
||||
data: DataEntity;
|
||||
filters?: RuleConditionEntity[];
|
||||
mode: string;
|
||||
intervalsCount: number;
|
||||
@@ -34,6 +36,15 @@ type ReportTableProps = {
|
||||
showOffBudget?: boolean;
|
||||
};
|
||||
|
||||
export type renderRowProps = {
|
||||
item: GroupedEntity;
|
||||
mode: string;
|
||||
intervalsCount: number;
|
||||
compact: boolean;
|
||||
style?: CSSProperties;
|
||||
compactStyle?: CSSProperties;
|
||||
};
|
||||
|
||||
export function ReportTable({
|
||||
saveScrollWidth,
|
||||
listScrollRef,
|
||||
@@ -58,8 +69,15 @@ export function ReportTable({
|
||||
}
|
||||
});
|
||||
|
||||
const renderItem = useCallback(
|
||||
({ item, mode, intervalsCount, compact, style, compactStyle }) => {
|
||||
const renderRow = useCallback(
|
||||
({
|
||||
item,
|
||||
mode,
|
||||
intervalsCount,
|
||||
compact,
|
||||
style,
|
||||
compactStyle,
|
||||
}: renderRowProps) => {
|
||||
return (
|
||||
<ReportTableRow
|
||||
item={item}
|
||||
@@ -109,7 +127,7 @@ export function ReportTable({
|
||||
intervalsCount={intervalsCount}
|
||||
mode={mode}
|
||||
groupBy={groupBy}
|
||||
renderItem={renderItem}
|
||||
renderRow={renderRow}
|
||||
compact={compact}
|
||||
style={style}
|
||||
compactStyle={compactStyle}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// @ts-strict-ignore
|
||||
import React, { type UIEventHandler } from 'react';
|
||||
import { type RefProp } from 'react-spring';
|
||||
import React, { type RefObject, type UIEventHandler } from 'react';
|
||||
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type IntervalEntity } from 'loot-core/src/types/models/reports';
|
||||
|
||||
import { theme } from '../../../../style';
|
||||
import { type CSSProperties } from '../../../../style/types';
|
||||
@@ -12,14 +10,15 @@ import { ReportOptions } from '../../ReportOptions';
|
||||
|
||||
type ReportTableHeaderProps = {
|
||||
groupBy: string;
|
||||
interval?: string;
|
||||
data?: DataEntity[];
|
||||
interval: string;
|
||||
data: IntervalEntity[];
|
||||
balanceType: string;
|
||||
headerScrollRef: RefProp<HTMLDivElement>;
|
||||
headerScrollRef: RefObject<HTMLDivElement>;
|
||||
handleScroll: UIEventHandler<HTMLDivElement>;
|
||||
compact: boolean;
|
||||
style?: CSSProperties;
|
||||
compactStyle?: CSSProperties;
|
||||
style: CSSProperties;
|
||||
compactStyle: CSSProperties;
|
||||
mode: string;
|
||||
};
|
||||
|
||||
export function ReportTableHeader({
|
||||
@@ -32,6 +31,7 @@ export function ReportTableHeader({
|
||||
compact,
|
||||
style,
|
||||
compactStyle,
|
||||
mode,
|
||||
}: ReportTableHeaderProps) {
|
||||
return (
|
||||
<Row
|
||||
@@ -70,7 +70,7 @@ export function ReportTableHeader({
|
||||
: groupBy
|
||||
}
|
||||
/>
|
||||
{data
|
||||
{mode === 'time'
|
||||
? data.map((header, index) => {
|
||||
return (
|
||||
<Cell
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
// @ts-strict-ignore
|
||||
import React from 'react';
|
||||
import React, { type ReactNode } from 'react';
|
||||
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
import {
|
||||
type GroupedEntity,
|
||||
type DataEntity,
|
||||
} from 'loot-core/src/types/models/reports';
|
||||
|
||||
import { type CSSProperties, theme } from '../../../../style';
|
||||
import { View } from '../../../common/View';
|
||||
import { Row } from '../../../table';
|
||||
|
||||
import { RenderTableRow } from './RenderTableRow';
|
||||
import { type renderRowProps } from './ReportTable';
|
||||
|
||||
type ReportTableListProps = {
|
||||
data: GroupedEntity;
|
||||
mode?: string;
|
||||
intervalsCount?: number;
|
||||
data: DataEntity;
|
||||
mode: string;
|
||||
intervalsCount: number;
|
||||
groupBy: string;
|
||||
renderItem;
|
||||
renderRow: (arg: renderRowProps) => ReactNode;
|
||||
compact: boolean;
|
||||
style?: CSSProperties;
|
||||
compactStyle?: CSSProperties;
|
||||
@@ -23,47 +28,28 @@ export function ReportTableList({
|
||||
intervalsCount,
|
||||
mode,
|
||||
groupBy,
|
||||
renderItem,
|
||||
renderRow,
|
||||
compact,
|
||||
style,
|
||||
compactStyle,
|
||||
}: ReportTableListProps) {
|
||||
const groupByData =
|
||||
const metadata: GroupedEntity[] | undefined =
|
||||
groupBy === 'Category'
|
||||
? 'groupedData'
|
||||
? data.groupedData || []
|
||||
: groupBy === 'Interval'
|
||||
? 'intervalData'
|
||||
: 'data';
|
||||
const metadata = data[groupByData];
|
||||
|
||||
type RenderRowProps = {
|
||||
index: number;
|
||||
parent_index?: number;
|
||||
compact: boolean;
|
||||
style?: CSSProperties;
|
||||
compactStyle?: CSSProperties;
|
||||
};
|
||||
function RenderRow({
|
||||
index,
|
||||
parent_index,
|
||||
compact,
|
||||
style,
|
||||
compactStyle,
|
||||
}: RenderRowProps) {
|
||||
const item =
|
||||
parent_index === undefined
|
||||
? metadata[index]
|
||||
: metadata[parent_index].categories[index];
|
||||
|
||||
return renderItem({
|
||||
item,
|
||||
mode,
|
||||
intervalsCount,
|
||||
compact,
|
||||
style,
|
||||
compactStyle,
|
||||
});
|
||||
}
|
||||
? data.intervalData.map(interval => {
|
||||
return {
|
||||
id: '',
|
||||
name: '',
|
||||
date: interval.date,
|
||||
totalAssets: interval.totalAssets,
|
||||
totalDebts: interval.totalDebts,
|
||||
totalTotals: interval.totalTotals,
|
||||
intervalData: [],
|
||||
categories: [],
|
||||
};
|
||||
})
|
||||
: data.data;
|
||||
|
||||
return (
|
||||
<View>
|
||||
@@ -71,10 +57,14 @@ export function ReportTableList({
|
||||
<View>
|
||||
{metadata.map((item, index) => {
|
||||
return (
|
||||
<View key={item.id}>
|
||||
<RenderRow
|
||||
<View key={index}>
|
||||
<RenderTableRow
|
||||
index={index}
|
||||
compact={compact}
|
||||
renderRow={renderRow}
|
||||
intervalsCount={intervalsCount}
|
||||
mode={mode}
|
||||
metadata={metadata}
|
||||
style={{
|
||||
...(item.categories && {
|
||||
color: theme.tableRowHeaderText,
|
||||
@@ -88,18 +78,24 @@ export function ReportTableList({
|
||||
{item.categories && (
|
||||
<>
|
||||
<View>
|
||||
{item.categories.map((category, i) => {
|
||||
return (
|
||||
<RenderRow
|
||||
key={category.id}
|
||||
index={i}
|
||||
compact={compact}
|
||||
parent_index={index}
|
||||
style={style}
|
||||
compactStyle={compactStyle}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{item.categories.map(
|
||||
(category: GroupedEntity, i: number) => {
|
||||
return (
|
||||
<RenderTableRow
|
||||
key={category.id}
|
||||
index={i}
|
||||
compact={compact}
|
||||
renderRow={renderRow}
|
||||
intervalsCount={intervalsCount}
|
||||
mode={mode}
|
||||
metadata={metadata}
|
||||
parent_index={index}
|
||||
style={style}
|
||||
compactStyle={compactStyle}
|
||||
/>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</View>
|
||||
<Row height={20} />
|
||||
</>
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
amountToInteger,
|
||||
integerToCurrency,
|
||||
} from 'loot-core/src/shared/util';
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type GroupedEntity } from 'loot-core/types/models/reports';
|
||||
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
|
||||
|
||||
import { useAccounts } from '../../../../hooks/useAccounts';
|
||||
@@ -17,7 +17,7 @@ import { Row, Cell } from '../../../table';
|
||||
import { showActivity } from '../showActivity';
|
||||
|
||||
type ReportTableRowProps = {
|
||||
item: DataEntity;
|
||||
item: GroupedEntity;
|
||||
balanceTypeOp: 'totalAssets' | 'totalDebts' | 'totalTotals';
|
||||
groupBy: string;
|
||||
mode: string;
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
// @ts-strict-ignore
|
||||
import React, { type UIEventHandler, useLayoutEffect, useState } from 'react';
|
||||
import { type RefProp } from 'react-spring';
|
||||
import React, {
|
||||
type UIEventHandler,
|
||||
useLayoutEffect,
|
||||
useState,
|
||||
type RefObject,
|
||||
} from 'react';
|
||||
|
||||
import {
|
||||
amountToCurrency,
|
||||
amountToInteger,
|
||||
integerToCurrency,
|
||||
} from 'loot-core/src/shared/util';
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
|
||||
|
||||
import { useAccounts } from '../../../../hooks/useAccounts';
|
||||
@@ -22,11 +25,11 @@ import { Row, Cell } from '../../../table';
|
||||
import { showActivity } from '../showActivity';
|
||||
|
||||
type ReportTableTotalsProps = {
|
||||
data: GroupedEntity;
|
||||
balanceTypeOp: string;
|
||||
data: DataEntity;
|
||||
balanceTypeOp: 'totalAssets' | 'totalDebts' | 'totalTotals';
|
||||
mode: string;
|
||||
intervalsCount: number;
|
||||
totalScrollRef: RefProp<HTMLDivElement>;
|
||||
totalScrollRef: RefObject<HTMLDivElement>;
|
||||
handleScroll: UIEventHandler<HTMLDivElement>;
|
||||
compact: boolean;
|
||||
style?: CSSProperties;
|
||||
@@ -58,11 +61,13 @@ export function ReportTableTotals({
|
||||
if (totalScrollRef.current) {
|
||||
const [parent, child] = [
|
||||
totalScrollRef.current.offsetParent
|
||||
? totalScrollRef.current.parentElement.scrollHeight || 0
|
||||
? (totalScrollRef.current.parentElement
|
||||
? totalScrollRef.current.parentElement.scrollHeight
|
||||
: 0) || 0
|
||||
: 0,
|
||||
totalScrollRef.current ? totalScrollRef.current.scrollHeight : 0,
|
||||
];
|
||||
setScrollWidthTotals(parent > 0 && child > 0 && parent - child);
|
||||
setScrollWidthTotals(parent > 0 && child > 0 ? parent - child : 0);
|
||||
}
|
||||
});
|
||||
const average = amountToInteger(data[balanceTypeOp]) / intervalsCount;
|
||||
|
||||
@@ -8,8 +8,8 @@ import * as monthUtils from 'loot-core/src/shared/months';
|
||||
import { amountToCurrency } from 'loot-core/src/shared/util';
|
||||
import { type CategoryEntity } from 'loot-core/types/models/category';
|
||||
import {
|
||||
type GroupedEntity,
|
||||
type CustomReportEntity,
|
||||
type DataEntity,
|
||||
} from 'loot-core/types/models/reports';
|
||||
import { type RuleConditionEntity } from 'loot-core/types/models/rule';
|
||||
|
||||
@@ -240,7 +240,7 @@ export function CustomReport() {
|
||||
}
|
||||
}, [interval, startDate, endDate, firstDayOfWeekIdx]);
|
||||
|
||||
const balanceTypeOp =
|
||||
const balanceTypeOp: 'totalAssets' | 'totalDebts' | 'totalTotals' =
|
||||
ReportOptions.balanceTypeMap.get(balanceType) || 'totalDebts';
|
||||
const payees = usePayees();
|
||||
const accounts = useAccounts();
|
||||
@@ -321,7 +321,7 @@ export function CustomReport() {
|
||||
const graphData = useReport('default', getGraphData);
|
||||
const groupedData = useReport('grouped', getGroupData);
|
||||
|
||||
const data: GroupedEntity = { ...graphData, groupedData } as GroupedEntity;
|
||||
const data: DataEntity = { ...graphData, groupedData } as DataEntity;
|
||||
|
||||
const customReportItems: CustomReportEntity = {
|
||||
id: '',
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import {
|
||||
type IntervalData,
|
||||
type ItemEntity,
|
||||
type LegendEntity,
|
||||
type IntervalEntity,
|
||||
type GroupedEntity,
|
||||
} from 'loot-core/src/types/models/reports';
|
||||
|
||||
import { theme } from '../../../style';
|
||||
import { getColorScale } from '../chart-theme';
|
||||
|
||||
export function calculateLegend(
|
||||
intervalData: IntervalData[],
|
||||
calcDataFiltered: ItemEntity[],
|
||||
intervalData: IntervalEntity[],
|
||||
calcDataFiltered: GroupedEntity[],
|
||||
groupBy: string,
|
||||
graphType: string,
|
||||
balanceTypeOp: string,
|
||||
) {
|
||||
graphType?: string,
|
||||
balanceTypeOp?: keyof GroupedEntity,
|
||||
): LegendEntity[] {
|
||||
const colorScale = getColorScale('qualitative');
|
||||
const chooseData =
|
||||
groupBy === 'Interval'
|
||||
@@ -22,10 +23,11 @@ export function calculateLegend(
|
||||
: calcDataFiltered.map(c => {
|
||||
return { name: c.name, id: c.id };
|
||||
});
|
||||
return chooseData.map((item, index) => {
|
||||
|
||||
const legend: LegendEntity[] = chooseData.map((item, index) => {
|
||||
return {
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
id: item.id || '',
|
||||
name: item.name || '',
|
||||
color:
|
||||
graphType === 'DonutGraph'
|
||||
? colorScale[index % colorScale.length]
|
||||
@@ -36,4 +38,5 @@ export function calculateLegend(
|
||||
: colorScale[index % colorScale.length],
|
||||
};
|
||||
});
|
||||
return legend;
|
||||
}
|
||||
|
||||
@@ -13,10 +13,7 @@ import {
|
||||
type RuleConditionEntity,
|
||||
type CategoryGroupEntity,
|
||||
} from 'loot-core/src/types/models';
|
||||
import {
|
||||
type DataEntity,
|
||||
type GroupedEntity,
|
||||
} from 'loot-core/src/types/models/reports';
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type LocalPrefs } from 'loot-core/types/prefs';
|
||||
|
||||
import {
|
||||
@@ -44,7 +41,7 @@ export type createCustomSpreadsheetProps = {
|
||||
showHiddenCategories: boolean;
|
||||
showUncategorized: boolean;
|
||||
groupBy?: string;
|
||||
balanceTypeOp?: keyof DataEntity;
|
||||
balanceTypeOp?: 'totalAssets' | 'totalDebts' | 'totalTotals';
|
||||
payees?: PayeeEntity[];
|
||||
accounts?: AccountEntity[];
|
||||
graphType?: string;
|
||||
@@ -65,7 +62,7 @@ export function createCustomSpreadsheet({
|
||||
showHiddenCategories,
|
||||
showUncategorized,
|
||||
groupBy,
|
||||
balanceTypeOp,
|
||||
balanceTypeOp = 'totalDebts',
|
||||
payees,
|
||||
accounts,
|
||||
graphType,
|
||||
@@ -92,7 +89,7 @@ export function createCustomSpreadsheet({
|
||||
|
||||
return async (
|
||||
spreadsheet: ReturnType<typeof useSpreadsheet>,
|
||||
setData: (data: GroupedEntity) => void,
|
||||
setData: (data: DataEntity) => void,
|
||||
) => {
|
||||
if (groupByList.length === 0) {
|
||||
return;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { type useSpreadsheet } from 'loot-core/src/client/SpreadsheetProvider';
|
||||
import { send } from 'loot-core/src/platform/client/fetch';
|
||||
import * as monthUtils from 'loot-core/src/shared/months';
|
||||
import { integerToAmount } from 'loot-core/src/shared/util';
|
||||
import { type DataEntity } from 'loot-core/src/types/models/reports';
|
||||
import { type GroupedEntity } from 'loot-core/src/types/models/reports';
|
||||
|
||||
import { categoryLists, ReportOptions } from '../ReportOptions';
|
||||
|
||||
@@ -41,7 +41,7 @@ export function createGroupedSpreadsheet({
|
||||
|
||||
return async (
|
||||
spreadsheet: ReturnType<typeof useSpreadsheet>,
|
||||
setData: (data: DataEntity[]) => void,
|
||||
setData: (data: GroupedEntity[]) => void,
|
||||
) => {
|
||||
if (categoryList.length === 0) {
|
||||
return;
|
||||
@@ -100,7 +100,7 @@ export function createGroupedSpreadsheet({
|
||||
endDate,
|
||||
);
|
||||
|
||||
const groupedData: DataEntity[] = categoryGroup.map(
|
||||
const groupedData: GroupedEntity[] = categoryGroup.map(
|
||||
group => {
|
||||
let totalAssets = 0;
|
||||
let totalDebts = 0;
|
||||
|
||||
32
packages/loot-core/src/types/models/reports.d.ts
vendored
32
packages/loot-core/src/types/models/reports.d.ts
vendored
@@ -57,10 +57,10 @@ export interface SpendingEntity {
|
||||
totalTotals: number;
|
||||
}
|
||||
|
||||
export interface GroupedEntity {
|
||||
data?: DataEntity[];
|
||||
intervalData: DataEntity[];
|
||||
groupedData?: DataEntity[] | null;
|
||||
export interface DataEntity {
|
||||
data?: GroupedEntity[];
|
||||
intervalData: IntervalEntity[];
|
||||
groupedData?: GroupedEntity[] | null;
|
||||
legend?: LegendEntity[];
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
@@ -75,33 +75,25 @@ type LegendEntity = {
|
||||
color: string;
|
||||
};
|
||||
|
||||
export type ItemEntity = {
|
||||
id: string;
|
||||
name: string;
|
||||
intervalData: IntervalData[];
|
||||
export type IntervalEntity = {
|
||||
date?: string;
|
||||
dateStart?: string;
|
||||
change?: number;
|
||||
dateLookup?: string;
|
||||
totalAssets: number;
|
||||
totalDebts: number;
|
||||
totalTotals: number;
|
||||
};
|
||||
|
||||
export type IntervalData = {
|
||||
date: string;
|
||||
dateLookup: string;
|
||||
totalAssets: number;
|
||||
totalDebts: number;
|
||||
totalTotals: number;
|
||||
};
|
||||
|
||||
export interface DataEntity {
|
||||
export interface GroupedEntity {
|
||||
id: string;
|
||||
name: string;
|
||||
date?: string;
|
||||
dateStart?: string;
|
||||
intervalData: IntervalData[];
|
||||
categories?: ItemEntity[];
|
||||
intervalData: IntervalEntity[];
|
||||
totalAssets: number;
|
||||
totalDebts: number;
|
||||
totalTotals: number;
|
||||
categories?: GroupedEntity[];
|
||||
}
|
||||
|
||||
export type Interval = {
|
||||
|
||||
6
upcoming-release-notes/2726.md
Normal file
6
upcoming-release-notes/2726.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Maintenance
|
||||
authors: [carkom]
|
||||
---
|
||||
|
||||
Making files in custom reports to comply with TS strict - stage #1.
|
||||
Reference in New Issue
Block a user