Files
frontend/src/features/tbank-connection/model/screen-sync.ts
T
ksv741 3c226f8c29
Frontend verify / commits (push) Skipped
Frontend verify / security (push) Successful in 12s
Frontend verify / verify (push) Successful in 7m41s
feat: render hourly investment states
2026-10-09 21:13:34 +03:00

65 lines
1.6 KiB
TypeScript

import type { QueryKey } from "@tanstack/react-query";
import { useEffect, useRef } from "react";
import type { InvestmentResourceMeta } from "@/shared/api";
type ScreenResource = {
isError: boolean;
isFetching: boolean;
meta?: InvestmentResourceMeta;
queryKey: QueryKey;
refetch: () => Promise<unknown>;
};
type ScreenScope = {
[key: string]: unknown;
screen: string;
};
const READ_INTERVAL_MS = 1_800_000;
function useScreenSync(_scope: ScreenScope, resources: ScreenResource[]) {
const resourcesRef = useRef(resources);
useEffect(() => {
resourcesRef.current = resources;
}, [resources]);
useEffect(() => {
const timer = setInterval(() => {
for (const resource of resourcesRef.current)
void resource.refetch().catch(() => {});
}, READ_INTERVAL_MS);
return () => clearInterval(timer);
}, []);
const isRefreshing = resources.some(resource => resource.isFetching);
const refresh = async () => {
if (isRefreshing) return;
await Promise.allSettled(resources.map(resource => resource.refetch()));
};
// Retry only the HTTP read; source attempts are reported in resource metadata.
const retry = async () => {
const failed = resources.filter(resource => resource.isError);
if (failed.length > 0)
await Promise.allSettled(failed.map(resource => resource.refetch()));
else await refresh();
};
return {
refresh,
refreshing: isRefreshing,
retry,
sourceError: resources.some(
({ meta }) => meta?.lastAttempt.state === "failed",
),
transportError: resources.some(resource => resource.isError),
};
}
export { useScreenSync };