114 lines
2.8 KiB
TypeScript
114 lines
2.8 KiB
TypeScript
import { useState } from "react";
|
|
import { useParams } from "react-router";
|
|
|
|
import {
|
|
type BrokerageEvent,
|
|
useBrokerageEvents,
|
|
} from "@/entities/brokerage-event";
|
|
import { useScreenSync } from "@/features/tbank-connection";
|
|
import { isValidPeriod, useUrlPeriod } from "@/shared/lib";
|
|
|
|
type AccountEventsPageViewModel
|
|
= | {
|
|
canApply: boolean;
|
|
draftPeriod: [null | string, null | string];
|
|
events: BrokerageEvent[];
|
|
lastSuccessfulAt?: null | string;
|
|
onApply: () => void;
|
|
onPeriodChange: (value: [null | string, null | string]) => void;
|
|
onReset: () => void;
|
|
partial?: boolean;
|
|
refreshError: boolean;
|
|
refreshing: boolean;
|
|
retry: () => void;
|
|
sourceError?: boolean;
|
|
state: "loaded";
|
|
}
|
|
| { onReset: () => void; retry: () => void; state: "error" }
|
|
| { state: "loading" };
|
|
|
|
function useAccountEventsPageViewModel(): AccountEventsPageViewModel {
|
|
const { accountId = "" } = useParams();
|
|
|
|
const {
|
|
from: appliedFrom,
|
|
setParameters: setSearchParameters,
|
|
to: appliedTo,
|
|
} = useUrlPeriod();
|
|
|
|
const [draftPeriod, setDraftPeriod] = useState<[
|
|
null | string,
|
|
null | string,
|
|
]>([appliedFrom, appliedTo]);
|
|
|
|
const [draftFrom, draftTo] = draftPeriod;
|
|
|
|
const scope = JSON.stringify([accountId, appliedFrom, appliedTo]);
|
|
const [previousScope, setPreviousScope] = useState(scope);
|
|
|
|
if (previousScope !== scope) {
|
|
setPreviousScope(scope);
|
|
setDraftPeriod([appliedFrom, appliedTo]);
|
|
}
|
|
|
|
const events = useBrokerageEvents(accountId, {
|
|
...(appliedFrom && { from: appliedFrom }),
|
|
...(appliedTo && { to: appliedTo }),
|
|
});
|
|
|
|
const sync = useScreenSync(
|
|
{
|
|
accountId,
|
|
screen: "events",
|
|
...(appliedFrom && { from: appliedFrom }),
|
|
...(appliedTo && { to: appliedTo }),
|
|
},
|
|
[events],
|
|
);
|
|
|
|
if (events.isLoading) return { state: "loading" };
|
|
|
|
const onReset = () => {
|
|
setDraftPeriod([null, null]);
|
|
setSearchParameters({});
|
|
};
|
|
|
|
if ((events.isError || events.meta?.sync.state === "failed") && !events.data)
|
|
return {
|
|
onReset,
|
|
retry: () => {
|
|
void sync.retry();
|
|
},
|
|
state: "error",
|
|
};
|
|
if (!events.data) return { state: "loading" };
|
|
|
|
return {
|
|
canApply:
|
|
(draftFrom !== appliedFrom || draftTo !== appliedTo)
|
|
&& isValidPeriod(draftFrom, draftTo),
|
|
draftPeriod,
|
|
events: events.data.events,
|
|
lastSuccessfulAt: events.meta?.lastSuccessfulAt,
|
|
onApply: () => {
|
|
if (!isValidPeriod(draftFrom, draftTo)) return;
|
|
setSearchParameters({
|
|
...(draftFrom && { from: draftFrom }),
|
|
...(draftTo && { to: draftTo }),
|
|
});
|
|
},
|
|
onPeriodChange: setDraftPeriod,
|
|
onReset,
|
|
partial: events.meta?.availability !== "complete",
|
|
refreshError: events.isError || sync.sourceError || sync.transportError,
|
|
refreshing: events.isFetching || sync.refreshing,
|
|
retry: () => {
|
|
void sync.retry();
|
|
},
|
|
sourceError: sync.sourceError,
|
|
state: "loaded",
|
|
};
|
|
}
|
|
|
|
export { type AccountEventsPageViewModel, useAccountEventsPageViewModel };
|