codex/broker-operations-ui #18

Merged
ksv741 merged 22 commits from codex/broker-operations-ui into main 2026-06-18 06:34:55 +03:00
4 changed files with 61 additions and 2 deletions
Showing only changes of commit 608e521674 - Show all commits

View File

@ -1,5 +1,5 @@
import { afterEach, describe, expect, it, vi } from 'vitest'; import { afterEach, describe, expect, it, vi } from 'vitest';
import { getBrokerOperations } from './broker'; import { getBrokerOperations, getBrokerPositions } from './broker';
describe('broker api', () => { describe('broker api', () => {
afterEach(() => { afterEach(() => {
@ -24,4 +24,23 @@ describe('broker api', () => {
expect.any(Object), expect.any(Object),
); );
}); });
it('serializes positions query parameters', async () => {
vi.spyOn(globalThis, 'fetch').mockResolvedValue({
ok: true,
json: async () => ({
data: {
data: { accountId: 'acc-1', items: [], nextCursor: null, hasNext: false, asOf: 'now' },
meta: { fromCache: false, cachedAt: null },
},
}),
} as Response);
await getBrokerPositions('acc-1', { cursor: 'pos-1', limit: 5 });
expect(fetch).toHaveBeenCalledWith(
expect.stringContaining('/api/v1/broker/accounts/acc-1/positions?cursor=pos-1&limit=5'),
expect.any(Object),
);
});
}); });

View File

@ -4,6 +4,7 @@ import type {
BrokerAccount, BrokerAccount,
BrokerOperationsPage, BrokerOperationsPage,
BrokerPortfolio, BrokerPortfolio,
BrokerPositionsPage,
} from './responses'; } from './responses';
export type BrokerOperationQuery = { export type BrokerOperationQuery = {
@ -49,3 +50,16 @@ export function getBrokerOperations(
}, },
); );
} }
export function getBrokerPositions(
accountId: string,
query: { cursor?: string; limit?: number } = {},
): Promise<{ data: BrokerPositionsPage; meta: ApiResponseMeta }> {
return request<BrokerPositionsPage>(
`/api/v1/broker/accounts/${encodeURIComponent(accountId)}/positions`,
{
cursor: query.cursor,
limit: query.limit ? String(query.limit) : undefined,
},
);
}

View File

@ -299,7 +299,6 @@ export interface BrokerPortfolio {
}; };
cash: BrokerMoney[]; cash: BrokerMoney[];
blockedCash: BrokerMoney[]; blockedCash: BrokerMoney[];
positions: BrokerPosition[];
asOf: string; asOf: string;
} }
@ -314,6 +313,7 @@ export interface BrokerOperation {
type: string; type: string;
category: BrokerOperationCategory; category: BrokerOperationCategory;
description: string | null; description: string | null;
name: string | null;
state: string | null; state: string | null;
instrumentUid: string | null; instrumentUid: string | null;
figi: string | null; figi: string | null;
@ -336,3 +336,11 @@ export interface BrokerOperationsPage {
hasNext: boolean; hasNext: boolean;
asOf: string; asOf: string;
} }
export interface BrokerPositionsPage {
accountId: string;
items: BrokerPosition[];
nextCursor: string | null;
hasNext: boolean;
asOf: string;
}

View File

@ -0,0 +1,18 @@
import { keepPreviousData, useQuery } from '@tanstack/react-query';
import { getBrokerPositions } from '../api/broker';
import type { BrokerPositionsPage } from '../api/responses';
export function useBrokerPositions(
accountId: string | undefined,
query: { cursor?: string; limit?: number } = {},
) {
return useQuery<BrokerPositionsPage>({
queryKey: ['broker', 'positions', accountId, query],
enabled: Boolean(accountId),
queryFn: async () => (await getBrokerPositions(accountId!, query)).data,
staleTime: 60_000,
retry: 2,
placeholderData: keepPreviousData,
refetchOnWindowFocus: false,
});
}