upcoming schedule setting: move setting to modal (#4164)

* upcoming schedule setting: move setting to modal

* note

* change nomenclature

* remove strict override
This commit is contained in:
Matt Fiddaman
2025-01-16 15:13:45 +00:00
committed by GitHub
parent 26907d3b12
commit b831d15eab
6 changed files with 115 additions and 116 deletions

View File

@@ -74,6 +74,7 @@ import { DiscoverSchedules } from './schedules/DiscoverSchedules';
import { PostsOfflineNotification } from './schedules/PostsOfflineNotification';
import { ScheduleDetails } from './schedules/ScheduleDetails';
import { ScheduleLink } from './schedules/ScheduleLink';
import { UpcomingLength } from './schedules/UpcomingLength';
import { NamespaceContext } from './spreadsheet/NamespaceContext';
export function Modals() {
@@ -373,6 +374,9 @@ export function Modals() {
case 'schedules-discover':
return <DiscoverSchedules key={name} />;
case 'schedules-upcoming-length':
return <UpcomingLength key={name} />;
case 'schedule-posts-offline-notification':
return <PostsOfflineNotification key={name} />;

View File

@@ -0,0 +1,80 @@
import React from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { type SyncedPrefs } from 'loot-core/types/prefs';
import { useSyncedPref } from '../../hooks/useSyncedPref';
import { Modal, ModalCloseButton, ModalHeader } from '../common/Modal';
import { Paragraph } from '../common/Paragraph';
import { Select } from '../common/Select';
import { View } from '../common/View';
function useUpcomingLengthOptions() {
const { t } = useTranslation();
const upcomingLengthOptions: {
value: SyncedPrefs['upcomingScheduledTransactionLength'];
label: string;
}[] = [
{ value: '1', label: t('1 day') },
{ value: '7', label: t('1 week') },
{ value: '14', label: t('2 weeks') },
{ value: '30', label: t('1 month') },
];
return { upcomingLengthOptions };
}
export function UpcomingLength() {
const { t } = useTranslation();
const [_upcomingLength, setUpcomingLength] = useSyncedPref(
'upcomingScheduledTransactionLength',
);
const { upcomingLengthOptions } = useUpcomingLengthOptions();
const upcomingLength = _upcomingLength || '7';
return (
<Modal
name="schedules-upcoming-length"
containerProps={{ style: { width: 600 } }}
>
{({ state: { close } }) => (
<>
<ModalHeader
title={t('Change upcoming length')}
rightContent={<ModalCloseButton onPress={close} />}
/>
<Paragraph>
<Trans>
Change how many days in advance of the scheduled date a scheduled
transaction appears in the account ledger as upcoming.
</Trans>
</Paragraph>
<Paragraph>
<Trans>
This only affects how schedules are displayed and not how budget
data is stored. It can be changed at any time.
</Trans>
</Paragraph>
<Paragraph>
<Trans>
Only the first instance of a recurring transaction will be shown.
</Trans>
</Paragraph>
<View>
<Select
options={upcomingLengthOptions.map(x => [
x.value || '7',
x.label,
])}
value={upcomingLength}
onChange={newValue => setUpcomingLength(newValue)}
/>
</View>
</>
)}
</Modal>
);
}

View File

@@ -7,13 +7,13 @@ import { useSchedules } from 'loot-core/src/client/data-hooks/schedules';
import { send } from 'loot-core/src/platform/client/fetch';
import { type ScheduleEntity } from 'loot-core/src/types/models';
import { useFeatureFlag } from '../../hooks/useFeatureFlag';
import { useDispatch } from '../../redux';
import { theme } from '../../style';
import { Button } from '../common/Button2';
import { Search } from '../common/Search';
import { View } from '../common/View';
import { Page } from '../Page';
import { UpcomingLengthSettings } from '../settings/Upcoming';
import { type ScheduleItemAction, SchedulesTable } from './SchedulesTable';
@@ -23,6 +23,8 @@ export function Schedules() {
const dispatch = useDispatch();
const [filter, setFilter] = useState('');
const upcomingLengthEnabled = useFeatureFlag('upcomingLengthAdjustment');
const onEdit = useCallback(
(id: ScheduleEntity['id']) => {
dispatch(pushModal('schedule-edit', { id }));
@@ -38,6 +40,10 @@ export function Schedules() {
dispatch(pushModal('schedules-discover'));
}, [dispatch]);
const onChangeUpcomingLength = useCallback(() => {
dispatch(pushModal('schedules-upcoming-length'));
}, [dispatch]);
const onAction = useCallback(
async (name: ScheduleItemAction, id: ScheduleEntity['id']) => {
switch (name) {
@@ -84,15 +90,6 @@ export function Schedules() {
padding: '0 0 15px',
}}
>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
padding: '15px 0 0',
}}
>
<UpcomingLengthSettings />
</View>
<View
style={{
flex: 1,
@@ -127,9 +124,22 @@ export function Schedules() {
flexShrink: 0,
}}
>
<Button onPress={onDiscover}>
<Trans>Find schedules</Trans>
</Button>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
gap: '1em',
}}
>
<Button onPress={onDiscover}>
<Trans>Find schedules</Trans>
</Button>
{upcomingLengthEnabled && (
<Button onPress={onChangeUpcomingLength}>
<Trans>Change upcoming length</Trans>
</Button>
)}
</View>
<Button variant="primary" onPress={onAdd}>
<Trans>Add new schedule</Trans>
</Button>

View File

@@ -1,103 +0,0 @@
import React, { useState } from 'react';
import { useTranslation, Trans } from 'react-i18next';
import { useLocation } from 'react-router-dom';
import { type SyncedPrefs } from 'loot-core/types/prefs';
import { useFeatureFlag } from '../../hooks/useFeatureFlag';
import { useSyncedPref } from '../../hooks/useSyncedPref';
import { Button } from '../common/Button2';
import { InfoBubble } from '../common/InfoBubble';
import { Select } from '../common/Select';
import { Text } from '../common/Text';
import { View } from '../common/View';
import { Setting } from './UI';
function useUpcomingLengthOptions() {
const { t } = useTranslation();
const upcomingLengthOptions: {
value: SyncedPrefs['upcomingScheduledTransactionLength'];
label: string;
}[] = [
{ value: '1', label: t('1 day') },
{ value: '7', label: t('1 week') },
{ value: '14', label: t('2 weeks') },
{ value: '30', label: t('1 month') },
];
return { upcomingLengthOptions };
}
export function UpcomingLengthSettings() {
const { t } = useTranslation();
const [_upcomingLength, setUpcomingLength] = useSyncedPref(
'upcomingScheduledTransactionLength',
);
const { upcomingLengthOptions } = useUpcomingLengthOptions();
const upcomingLength = _upcomingLength || '7';
const enabled = useFeatureFlag('upcomingLengthAdjustment');
const location = useLocation();
const [expanded, setExpanded] = useState(location.hash === '#upcomingLength');
if (!enabled) return null;
return expanded ? (
<Setting
primaryAction={
<View style={{ flexDirection: 'row', gap: '1em' }}>
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 20 }}>
<View title={t('Upcoming Length')}>
<Select
options={upcomingLengthOptions.map(x => [
x.value || '7',
x.label,
])}
value={upcomingLength}
onChange={newValue => setUpcomingLength(newValue)}
/>
</View>
<InfoBubble
label={t(
'Only the first instance of a recurring transaction will be shown.',
)}
/>
</View>
</View>
}
>
<View style={{ flexDirection: 'row', gap: 20 }}>
<Text>
<Trans>
<strong>Upcoming Length</strong> does not affect how budget data is
stored, and can be changed at any time.
</Trans>
</Text>
<Button
onPress={() => setExpanded(false)}
aria-label="Close upcoming length settings"
>
<Trans>Close</Trans>
</Button>
</View>
</Setting>
) : (
<View>
<Button
aria-label="Edit upcoming length settings"
variant="primary"
onPress={() => setExpanded(true)}
>
<Trans>Edit Upcoming Length</Trans> (
{upcomingLengthOptions.find(x => x.value === upcomingLength)?.label ??
t('1 week')}
)
</Button>
</View>
);
}

View File

@@ -181,6 +181,8 @@ type FinanceModals = {
'schedules-discover': null;
'schedules-upcoming-length': null;
'schedule-posts-offline-notification': null;
'account-menu': {
accountId: string;

View File

@@ -0,0 +1,6 @@
---
category: Enhancements
authors: [matt-fidd]
---
Move upcoming schedule length setting