Files
frontend/src/entities/broker-operation/model/useBrokerageOperationHistory.ts
T
ksv741 5b30bb802a feat: add quiet reading with rare confirmations
Part of the quiet-user-feedback change; docs and specs land in their own repositories.
2026-10-06 07:01:58 +03:00

81 lines
2.0 KiB
TypeScript

import { hashKey, useQueryClient } from "@tanstack/react-query";
import { useEffect, useState } from "react";
import { ApiErrorCode, apiErrorCode, isApiErrorCode } from "@/shared/api";
import {
type BrokerageOperationsQuery,
brokerageOperationsQueryOptions,
useBrokerageOperations,
} from "../api/useBrokerageOperations";
function useBrokerageOperationHistory(
accountId: string | undefined,
firstPage: Omit<BrokerageOperationsQuery, "cursor">,
) {
const { queryKey } = brokerageOperationsQueryOptions(accountId, firstPage);
const scope = hashKey(queryKey);
const [pagination, setPagination] = useState<{
cursors: string[];
scope: string;
}>({ cursors: [], scope });
const cursors = pagination.scope === scope ? pagination.cursors : [];
const client = useQueryClient();
const operations = useBrokerageOperations(accountId, {
...firstPage,
cursor: cursors.at(-1),
});
const isInvalidCursor = isApiErrorCode(
apiErrorCode(operations.error),
ApiErrorCode.InvalidOperationsCursor,
);
const isRecoveringInvalidCursor = cursors.length > 0 && isInvalidCursor;
const reset = () => setPagination({ cursors: [], scope });
useEffect(() => {
if (!isRecoveringInvalidCursor) return;
const timeout = setTimeout(() => {
setPagination({ cursors: [], scope });
void client.invalidateQueries({ exact: true, queryKey });
}, 0);
return () => clearTimeout(timeout);
}, [client, isRecoveringInvalidCursor, queryKey, scope]);
const retry = (retryScreen: () => unknown) => {
if (isInvalidCursor) {
reset();
void client.invalidateQueries({
exact: true,
queryKey,
});
}
else void retryScreen();
};
return {
hasPrevious: cursors.length > 0,
isRecoveringInvalidCursor,
onNext: () => {
if (operations.data?.nextCursor)
setPagination({
cursors: [...cursors, operations.data.nextCursor],
scope,
});
},
onPrevious: () => setPagination({ cursors: cursors.slice(0, -1), scope }),
operations,
reset,
retry,
};
}
export { useBrokerageOperationHistory };