Add YTD and last year to Reports headers (#4019)
* Add YTD and last year to Reports headers * Add release note * lint * fix end date picker * remove debugger * Update VRT * Update VRT * Fix year to date and last year * remove debugger * pr comments * fix small size * Update VRT --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: youngcw <calebyoung94@gmail.com>
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 79 KiB |
@@ -6,6 +6,7 @@ import {
|
||||
type RuleConditionEntity,
|
||||
type TimeFrame,
|
||||
} from 'loot-core/types/models';
|
||||
import { type SyncedPrefs } from 'loot-core/types/prefs';
|
||||
|
||||
import { Button } from '../common/Button2';
|
||||
import { Select } from '../common/Select';
|
||||
@@ -15,6 +16,7 @@ import { AppliedFilters } from '../filters/AppliedFilters';
|
||||
import { FilterButton } from '../filters/FiltersMenu';
|
||||
import { useResponsive } from '../responsive/ResponsiveProvider';
|
||||
|
||||
import { getLiveRange } from './getLiveRange';
|
||||
import {
|
||||
calculateTimeRange,
|
||||
getFullRange,
|
||||
@@ -29,6 +31,8 @@ type HeaderProps = {
|
||||
mode?: TimeFrame['mode'];
|
||||
show1Month?: boolean;
|
||||
allMonths: Array<{ name: string; pretty: string }>;
|
||||
earliestTransaction: string;
|
||||
firstDayOfWeekIdx?: SyncedPrefs['firstDayOfWeekIdx'];
|
||||
onChangeDates: (
|
||||
start: TimeFrame['start'],
|
||||
end: TimeFrame['end'],
|
||||
@@ -51,6 +55,8 @@ export function Header({
|
||||
mode,
|
||||
show1Month,
|
||||
allMonths,
|
||||
earliestTransaction,
|
||||
firstDayOfWeekIdx,
|
||||
onChangeDates,
|
||||
filters,
|
||||
conditionsOp,
|
||||
@@ -62,6 +68,14 @@ export function Header({
|
||||
}: HeaderProps) {
|
||||
const { t } = useTranslation();
|
||||
const { isNarrowWidth } = useResponsive();
|
||||
function convertToMonth(
|
||||
start: string,
|
||||
end: string,
|
||||
_: TimeFrame['mode'],
|
||||
mode: TimeFrame['mode'],
|
||||
): [string, string, TimeFrame['mode']] {
|
||||
return [monthUtils.getMonth(start), monthUtils.getMonth(end), mode];
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
@@ -129,7 +143,7 @@ export function Header({
|
||||
</SpaceBetween>
|
||||
</SpaceBetween>
|
||||
|
||||
<SpaceBetween>
|
||||
<SpaceBetween gap={3}>
|
||||
{show1Month && (
|
||||
<Button
|
||||
variant="bare"
|
||||
@@ -156,6 +170,42 @@ export function Header({
|
||||
>
|
||||
{t('1 year')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="bare"
|
||||
onPress={() =>
|
||||
onChangeDates(
|
||||
...convertToMonth(
|
||||
...getLiveRange(
|
||||
'Year to date',
|
||||
earliestTransaction,
|
||||
true,
|
||||
firstDayOfWeekIdx,
|
||||
),
|
||||
'yearToDate',
|
||||
),
|
||||
)
|
||||
}
|
||||
>
|
||||
{t('Year to date')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="bare"
|
||||
onPress={() =>
|
||||
onChangeDates(
|
||||
...convertToMonth(
|
||||
...getLiveRange(
|
||||
'Last year',
|
||||
earliestTransaction,
|
||||
false,
|
||||
firstDayOfWeekIdx,
|
||||
),
|
||||
'lastYear',
|
||||
),
|
||||
)
|
||||
}
|
||||
>
|
||||
{t('Last year')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="bare"
|
||||
onPress={() =>
|
||||
|
||||
@@ -196,6 +196,20 @@ export function calculateTimeRange(
|
||||
|
||||
return getLatestRange(offset);
|
||||
}
|
||||
if (mode === 'lastYear') {
|
||||
return [
|
||||
monthUtils.getYearStart(monthUtils.prevYear(monthUtils.currentMonth())),
|
||||
monthUtils.getYearEnd(monthUtils.prevYear(monthUtils.currentDate())),
|
||||
'lastYear',
|
||||
] as const;
|
||||
}
|
||||
if (mode === 'yearToDate') {
|
||||
return [
|
||||
monthUtils.currentYear() + '-01',
|
||||
monthUtils.currentMonth(),
|
||||
'yearToDate',
|
||||
] as const;
|
||||
}
|
||||
|
||||
return [start, end, 'static'] as const;
|
||||
}
|
||||
|
||||
@@ -460,6 +460,8 @@ function CalendarInner({ widget, parameters }: CalendarInnerProps) {
|
||||
},
|
||||
);
|
||||
|
||||
const [earliestTransaction, _] = useState('');
|
||||
|
||||
return (
|
||||
<Page
|
||||
header={
|
||||
@@ -492,6 +494,8 @@ function CalendarInner({ widget, parameters }: CalendarInnerProps) {
|
||||
allMonths={allMonths}
|
||||
start={start}
|
||||
end={end}
|
||||
earliestTransaction={earliestTransaction}
|
||||
firstDayOfWeekIdx={firstDayOfWeekIdx}
|
||||
mode={mode}
|
||||
onChangeDates={onChangeDates}
|
||||
filters={conditions}
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
|
||||
import { useFilters } from '../../../hooks/useFilters';
|
||||
import { useNavigate } from '../../../hooks/useNavigate';
|
||||
import { useSyncedPref } from '../../../hooks/useSyncedPref';
|
||||
import { useDispatch } from '../../../redux';
|
||||
import { theme } from '../../../style';
|
||||
import { AlignedText } from '../../common/AlignedText';
|
||||
@@ -187,6 +188,10 @@ function CashFlowInner({ widget }: CashFlowInnerProps) {
|
||||
});
|
||||
};
|
||||
|
||||
const [earliestTransaction, _] = useState('');
|
||||
const [_firstDayOfWeekIdx] = useSyncedPref('firstDayOfWeekIdx');
|
||||
const firstDayOfWeekIdx = _firstDayOfWeekIdx || '0';
|
||||
|
||||
if (!allMonths || !data) {
|
||||
return null;
|
||||
}
|
||||
@@ -224,6 +229,8 @@ function CashFlowInner({ widget }: CashFlowInnerProps) {
|
||||
allMonths={allMonths}
|
||||
start={start}
|
||||
end={end}
|
||||
earliestTransaction={earliestTransaction}
|
||||
firstDayOfWeekIdx={firstDayOfWeekIdx}
|
||||
mode={mode}
|
||||
show1Month
|
||||
onChangeDates={onChangeDates}
|
||||
|
||||
@@ -14,6 +14,7 @@ import { type TimeFrame, type NetWorthWidget } from 'loot-core/types/models';
|
||||
import { useAccounts } from '../../../hooks/useAccounts';
|
||||
import { useFilters } from '../../../hooks/useFilters';
|
||||
import { useNavigate } from '../../../hooks/useNavigate';
|
||||
import { useSyncedPref } from '../../../hooks/useSyncedPref';
|
||||
import { useDispatch } from '../../../redux';
|
||||
import { theme, styles } from '../../../style';
|
||||
import { Button } from '../../common/Button2';
|
||||
@@ -162,6 +163,10 @@ function NetWorthInner({ widget }: NetWorthInnerProps) {
|
||||
});
|
||||
};
|
||||
|
||||
const [earliestTransaction, _] = useState('');
|
||||
const [_firstDayOfWeekIdx] = useSyncedPref('firstDayOfWeekIdx');
|
||||
const firstDayOfWeekIdx = _firstDayOfWeekIdx || '0';
|
||||
|
||||
if (!allMonths || !data) {
|
||||
return null;
|
||||
}
|
||||
@@ -197,6 +202,8 @@ function NetWorthInner({ widget }: NetWorthInnerProps) {
|
||||
allMonths={allMonths}
|
||||
start={start}
|
||||
end={end}
|
||||
earliestTransaction={earliestTransaction}
|
||||
firstDayOfWeekIdx={firstDayOfWeekIdx}
|
||||
mode={mode}
|
||||
onChangeDates={onChangeDates}
|
||||
filters={conditions}
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
|
||||
import { useFilters } from '../../../hooks/useFilters';
|
||||
import { useNavigate } from '../../../hooks/useNavigate';
|
||||
import { useSyncedPref } from '../../../hooks/useSyncedPref';
|
||||
import { SvgEquals } from '../../../icons/v1';
|
||||
import { SvgCloseParenthesis } from '../../../icons/v2/CloseParenthesis';
|
||||
import { SvgOpenParenthesis } from '../../../icons/v2/OpenParenthesis';
|
||||
@@ -147,6 +148,10 @@ function SummaryInner({ widget }: SummaryInnerProps) {
|
||||
}>
|
||||
>([]);
|
||||
|
||||
const [earliestTransaction, _] = useState('');
|
||||
const [_firstDayOfWeekIdx] = useSyncedPref('firstDayOfWeekIdx');
|
||||
const firstDayOfWeekIdx = _firstDayOfWeekIdx || '0';
|
||||
|
||||
useEffect(() => {
|
||||
async function run() {
|
||||
const trans = await send('get-earliest-transaction');
|
||||
@@ -219,7 +224,6 @@ function SummaryInner({ widget }: SummaryInnerProps) {
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await send('dashboard-update-widget', {
|
||||
id: widget.id,
|
||||
meta: {
|
||||
@@ -273,6 +277,8 @@ function SummaryInner({ widget }: SummaryInnerProps) {
|
||||
allMonths={allMonths}
|
||||
start={start}
|
||||
end={end}
|
||||
earliestTransaction={earliestTransaction}
|
||||
firstDayOfWeekIdx={firstDayOfWeekIdx}
|
||||
mode={mode}
|
||||
onChangeDates={onChangeDates}
|
||||
onApply={dividendFilters.onApply}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { type RuleConditionEntity } from './rule';
|
||||
export type TimeFrame = {
|
||||
start: string;
|
||||
end: string;
|
||||
mode: 'sliding-window' | 'static' | 'full';
|
||||
mode: 'sliding-window' | 'static' | 'full' | 'lastYear' | 'yearToDate';
|
||||
};
|
||||
|
||||
type AbstractWidget<
|
||||
|
||||
6
upcoming-release-notes/4019.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
category: Enhancements
|
||||
authors: [rodriguestiago0]
|
||||
---
|
||||
|
||||
Add "Year to date" and "Last year" to reports header.
|
||||