Add useSchedule and Fix loading states

This commit is contained in:
Joel Jeremy Marquez
2026-02-12 17:17:08 +00:00
parent 089ad26419
commit ecc95084f5
11 changed files with 46 additions and 50 deletions

View File

@@ -94,9 +94,9 @@ function SelectedBalance({ selectedItems, account }: SelectedBalanceProps) {
let scheduleBalance = 0;
const { data: schedules = [], isFetching } = useCachedSchedules();
const { data: schedules = [], isPending } = useCachedSchedules();
if (isFetching) {
if (isPending) {
return null;
}

View File

@@ -39,11 +39,9 @@ export function MobileSchedulesPage() {
const format = useFormat();
const dateFormat = useDateFormat() || 'MM/dd/yyyy';
const { isFetching: isSchedulesLoading, data: schedules = [] } = useSchedules(
{
query: q('schedules').select('*'),
},
);
const { isPending: isSchedulesLoading, data: schedules = [] } = useSchedules({
query: q('schedules').select('*'),
});
const { data: { statusLookup = {} } = {} } = useScheduleStatus({ schedules });
const payees = usePayees();

View File

@@ -315,7 +315,7 @@ type PayeeIconsProps = {
function PayeeIcons({ transaction, transferAccount }: PayeeIconsProps) {
const { id, schedule: scheduleId } = transaction;
const { isFetching: isSchedulesLoading, data: schedules = [] } =
const { isPending: isSchedulesLoading, data: schedules = [] } =
useCachedSchedules();
const isPreview = isPreviewId(id);
const schedule = schedules.find(s => s.id === scheduleId);

View File

@@ -9,7 +9,6 @@ import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { format } from 'loot-core/shared/months';
import { q } from 'loot-core/shared/query';
import {
extractScheduleConds,
scheduleIsRecurring,
@@ -22,8 +21,8 @@ import {
ModalTitle,
} from '@desktop-client/components/common/Modal';
import { useLocale } from '@desktop-client/hooks/useLocale';
import { useSchedules } from '@desktop-client/hooks/useSchedules';
import type { Modal as ModalType } from '@desktop-client/modals/modalsSlice';
import { useSchedule } from '@desktop-client/hooks/useSchedule';
type ScheduledTransactionMenuModalProps = Extract<
ModalType,
@@ -44,17 +43,11 @@ export function ScheduledTransactionMenuModal({
borderTop: `1px solid ${theme.pillBorder}`,
};
const scheduleId = transactionId?.split('/')?.[1];
const { isFetching: isSchedulesLoading, data: schedules = [] } = useSchedules(
{
query: q('schedules').filter({ id: scheduleId }).select('*'),
},
);
if (isSchedulesLoading) {
const { isPending: isSchedulesLoading, data: schedule } = useSchedule(scheduleId);
if (isSchedulesLoading || !schedule) {
return null;
}
const schedule = schedules[0];
const { date: dateCond } = extractScheduleConds(schedule._conditions);
const canBeSkipped = scheduleIsRecurring(dateCond);
@@ -65,7 +58,7 @@ export function ScheduledTransactionMenuModal({
{({ state: { close } }) => (
<>
<ModalHeader
title={<ModalTitle title={schedule?.name || ''} shrinkOnOverflow />}
title={<ModalTitle title={schedule.name || ''} shrinkOnOverflow />}
rightContent={<ModalCloseButton onPress={close} />}
/>
<View
@@ -79,7 +72,7 @@ export function ScheduledTransactionMenuModal({
<Trans>Scheduled date</Trans>
</Text>
<Text style={{ fontSize: 17, fontWeight: 700 }}>
{format(schedule?.next_date || '', 'MMMM dd, yyyy', locale)}
{format(schedule.next_date || '', 'MMMM dd, yyyy', locale)}
</Text>
</View>
<ScheduledTransactionMenu

View File

@@ -58,7 +58,6 @@ import { GenericInput } from '@desktop-client/components/util/GenericInput';
import { useDateFormat } from '@desktop-client/hooks/useDateFormat';
import { useFeatureFlag } from '@desktop-client/hooks/useFeatureFlag';
import { useFormat } from '@desktop-client/hooks/useFormat';
import { useSchedules } from '@desktop-client/hooks/useSchedules';
import { useScheduleStatus } from '@desktop-client/hooks/useScheduleStatus';
import {
SelectedProvider,
@@ -69,6 +68,7 @@ import { getPayees } from '@desktop-client/payees/payeesSlice';
import { aqlQuery } from '@desktop-client/queries/aqlQuery';
import { useDispatch } from '@desktop-client/redux';
import { disableUndo, enableUndo } from '@desktop-client/undo';
import { useSchedule } from '@desktop-client/hooks/useSchedule';
function updateValue(array, value, update) {
return array.map(v => (v === value ? update() : v));
@@ -367,23 +367,18 @@ function ScheduleDescription({ id }) {
const { isNarrowWidth } = useResponsive();
const dateFormat = useDateFormat() || 'MM/dd/yyyy';
const format = useFormat();
const { data: schedules = [], isFetching: isSchedulesLoading } = useSchedules(
{
query: q('schedules').filter({ id }).select('*'),
},
);
const { data: schedule, isPending: isSchedulesLoading } = useSchedule(id);
const {
data: { statusLookup = {} },
} = useScheduleStatus({ schedules });
data: { statusLookup = {} } = {},
isPending: isScheduleStatusLoading,
} = useScheduleStatus({ schedules: [schedule] });
if (isSchedulesLoading) {
if (isSchedulesLoading || isScheduleStatusLoading) {
return null;
}
const [schedule] = schedules;
if (schedule && schedules.length === 0) {
if (!schedule) {
return <View style={{ flex: 1 }}>{id}</View>;
}

View File

@@ -22,11 +22,9 @@ export function ScheduleValue({ value }: ScheduleValueProps) {
const { t } = useTranslation();
const payees = usePayees();
const byId = getPayeesById(payees);
const { data: schedules = [], isFetching: isSchedulesLoading } = useSchedules(
{
query: q('schedules').select('*'),
},
);
const { data: schedules = [], isPending: isSchedulesLoading } = useSchedules({
query: q('schedules').select('*'),
});
if (isSchedulesLoading) {
return (

View File

@@ -41,11 +41,9 @@ export function ScheduleLink({
const dispatch = useDispatch();
const [filter, setFilter] = useState(accountName || '');
const { isFetching: isSchedulesLoading, data: schedules = [] } = useSchedules(
{
query: q('schedules').filter({ completed: false }).select('*'),
},
);
const { isPending: isSchedulesLoading, data: schedules = [] } = useSchedules({
query: q('schedules').filter({ completed: false }).select('*'),
});
const {
data: { statusLookup = {} },

View File

@@ -81,11 +81,9 @@ export function Schedules() {
[],
);
const { isFetching: isSchedulesLoading, data: schedules = [] } = useSchedules(
{
query: q('schedules').select('*'),
},
);
const { isPending: isSchedulesLoading, data: schedules = [] } = useSchedules({
query: q('schedules').select('*'),
});
const { data: { statusLookup = {} } = {} } = useScheduleStatus({ schedules });

View File

@@ -764,9 +764,9 @@ function PayeeIcons({
const { t } = useTranslation();
const scheduleId = transaction.schedule;
const { isFetching, data: schedules = [] } = useCachedSchedules();
const { isPending, data: schedules = [] } = useCachedSchedules();
if (isFetching) {
if (isPending) {
return null;
}

View File

@@ -41,7 +41,7 @@ export function usePreviewTransactions({
TransactionEntity[]
>([]);
const {
isFetching: isSchedulesLoading,
isPending: isSchedulesLoading,
error: scheduleQueryError,
data: schedules = [],
} = useCachedSchedules();

View File

@@ -0,0 +1,16 @@
import { scheduleQueries } from "@desktop-client/schedules";
import { useQuery } from "@tanstack/react-query";
import { q } from "loot-core/shared/query";
import type { ScheduleEntity } from 'loot-core/types/models';
export function useSchedule(id?: ScheduleEntity['id'] | null) {
return useQuery({
...scheduleQueries.aql({
// Re-use the results of the get all schedules query
// since it's most likely already in the cache
query: q('schedules').select('*'),
}),
select: schedules => schedules.find(schedule => schedule.id === id),
enabled: !!id,
})
}