319 lines
8.6 KiB
Markdown
319 lines
8.6 KiB
Markdown
# Broker Operations UI Improvements — Implementation Plan
|
|
|
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
|
**Goal:** Clean up operations table badges, add "+" for positive amounts, smooth pagination with styled buttons.
|
|
|
|
**Architecture:** All changes are frontend-only (React components, TanStack Query hook, display helpers, tests). No backend changes.
|
|
|
|
**Tech Stack:** React 18, TanStack Query v5, Vitest + Testing Library
|
|
|
|
---
|
|
|
|
### Task 1: Remove `getBrokerOperationImpactLabel` from brokerDisplay
|
|
|
|
**Files:**
|
|
- Modify: `apps/frontend/src/pages/broker/brokerDisplay.ts:165-176`
|
|
- Modify: `apps/frontend/src/pages/broker/brokerDisplay.test.ts:195-201`
|
|
|
|
- [ ] **Step 1: Remove the test for impact labels**
|
|
|
|
In `brokerDisplay.test.ts`, delete the test block "provides Russian impact labels" (lines 195-201) and remove `getBrokerOperationImpactLabel` from the import.
|
|
|
|
```tsx
|
|
// Import line changes from:
|
|
import {
|
|
getBrokerInstrumentPath,
|
|
getBrokerOperationImpact,
|
|
getBrokerOperationImpactLabel,
|
|
getBrokerOperationTypeLabel,
|
|
getBrokerPositionGroup,
|
|
} from './brokerDisplay';
|
|
// to:
|
|
import {
|
|
getBrokerInstrumentPath,
|
|
getBrokerOperationImpact,
|
|
getBrokerOperationTypeLabel,
|
|
getBrokerPositionGroup,
|
|
} from './brokerDisplay';
|
|
```
|
|
|
|
Delete the entire `it('provides Russian impact labels', ...)` block (lines 195-201).
|
|
|
|
- [ ] **Step 2: Run tests to verify the test removal succeeds**
|
|
|
|
Run: `npx vitest run apps/frontend/src/pages/broker/brokerDisplay.test.ts`
|
|
Expected: PASS (1 less test)
|
|
|
|
- [ ] **Step 3: Remove `getBrokerOperationImpactLabel` from source**
|
|
|
|
In `brokerDisplay.ts`, delete the `getBrokerOperationImpactLabel` function (lines 165-176) and remove its export.
|
|
|
|
- [ ] **Step 4: Run tests to verify**
|
|
|
|
Run: `npx vitest run apps/frontend/src/pages/broker/brokerDisplay.test.ts`
|
|
Expected: PASS
|
|
|
|
- [ ] **Step 5: Commit**
|
|
|
|
```bash
|
|
git add apps/frontend/src/pages/broker/brokerDisplay.ts apps/frontend/src/pages/broker/brokerDisplay.test.ts
|
|
git commit -m "refactor: remove unused getBrokerOperationImpactLabel helper"
|
|
```
|
|
|
|
---
|
|
|
|
### Task 2: Update BrokerPages.test.tsx for new expectations
|
|
|
|
**Files:**
|
|
- Modify: `apps/frontend/src/pages/broker/BrokerPages.test.tsx`
|
|
|
|
- [ ] **Step 1: Update test to expect no badges and "+" prefix**
|
|
|
|
Remove lines 314-315 (badge checks):
|
|
```tsx
|
|
expect(screen.getByText('Пополняет')).toBeInTheDocument();
|
|
expect(screen.getByText('Списывает')).toBeInTheDocument();
|
|
```
|
|
|
|
Update test name at line 225 from:
|
|
```
|
|
it('renders broker operations with Russian labels, linked instruments and impact badges', () => {
|
|
```
|
|
to:
|
|
```
|
|
it('renders broker operations with Russian labels, linked instruments and colored amounts', () => {
|
|
```
|
|
|
|
Add a check for the "+" prefix on positive amounts after the existing check at line 312-313:
|
|
```tsx
|
|
expect(screen.getByText('Выплата купона')).toBeInTheDocument();
|
|
expect(screen.getByText('Налог')).toBeInTheDocument();
|
|
// Add:
|
|
expect(screen.getByText(/\+120,00\s*₽/)).toBeInTheDocument();
|
|
```
|
|
|
|
Remove the old checks for "Страница 1" and "Страница 2" text (lines 424-437) and instead verify the pagination buttons exist. Update the pagination test block at line 322:
|
|
```tsx
|
|
it('requests broker operations by cursor with a page size of 10', async () => {
|
|
// ...setup stays the same...
|
|
|
|
// Replace these:
|
|
// expect(screen.getByText('Страница 1')).toBeInTheDocument();
|
|
// with check that page buttons exist:
|
|
const nextButton = screen.getByRole('button', { name: '→' });
|
|
const prevButton = screen.getByRole('button', { name: '←' });
|
|
expect(prevButton).toBeDisabled();
|
|
expect(nextButton).not.toBeDisabled();
|
|
|
|
await user.click(nextButton);
|
|
|
|
expect(operationsSpy).toHaveBeenLastCalledWith('acc-1', {
|
|
limit: 10,
|
|
cursor: 'cursor-page-2',
|
|
});
|
|
// expect(screen.getByText('Страница 2')).toBeInTheDocument(); // remove
|
|
expect(screen.getByText('2')).toBeInTheDocument(); // page number shown without label
|
|
|
|
await user.click(screen.getByRole('button', { name: '←' }));
|
|
|
|
expect(operationsSpy).toHaveBeenLastCalledWith('acc-1', { limit: 10, cursor: undefined });
|
|
expect(screen.getByText('1')).toBeInTheDocument();
|
|
});
|
|
```
|
|
|
|
- [ ] **Step 2: Run tests to verify they fail**
|
|
|
|
Run: `npx vitest run apps/frontend/src/pages/broker/BrokerPages.test.tsx`
|
|
Expected: FAIL (buttons named '→' / '←' not found yet, "+" text not found)
|
|
|
|
- [ ] **Step 3: Commit**
|
|
|
|
```bash
|
|
git add apps/frontend/src/pages/broker/BrokerPages.test.tsx
|
|
git commit -m "test: update broker page tests for new UI expectations"
|
|
```
|
|
|
|
---
|
|
|
|
### Task 3: Remove badges and add "+" prefix, style pagination buttons
|
|
|
|
**Files:**
|
|
- Modify: `apps/frontend/src/pages/broker/BrokerOperationsTable.tsx`
|
|
|
|
- [ ] **Step 1: Remove badge-related code**
|
|
|
|
In `BrokerOperationsTable.tsx`:
|
|
|
|
Delete the `impactStyles` object (lines 30-47).
|
|
|
|
Delete the `OperationType` component (lines 87-108).
|
|
|
|
Update imports — remove `getBrokerOperationImpactLabel` and `BrokerOperationImpact`:
|
|
```tsx
|
|
import {
|
|
getBrokerInstrumentPath,
|
|
getBrokerOperationImpact,
|
|
getBrokerOperationTypeLabel,
|
|
} from './brokerDisplay';
|
|
```
|
|
|
|
Update the "Тип" column cell — replace `<OperationType operation={operation} />` with just:
|
|
```tsx
|
|
<span>{getBrokerOperationTypeLabel(operation)}</span>
|
|
```
|
|
|
|
- [ ] **Step 2: Add "+" prefix to positive amounts**
|
|
|
|
Modify `formatMoney` function:
|
|
```tsx
|
|
function formatMoney(value: BrokerMoney | null | undefined) {
|
|
if (!value) return '-';
|
|
const formatted = new Intl.NumberFormat('ru-RU', {
|
|
style: 'currency',
|
|
currency: value.currency || 'RUB',
|
|
maximumFractionDigits: 2,
|
|
}).format(value.value);
|
|
return value.value > 0 ? `+${formatted}` : formatted;
|
|
}
|
|
```
|
|
|
|
- [ ] **Step 3: Style pagination buttons**
|
|
|
|
Add button style constants before the component:
|
|
```tsx
|
|
const pagButtonStyle: React.CSSProperties = {
|
|
padding: '6px 14px',
|
|
borderRadius: 6,
|
|
border: '1px solid #e0e0e0',
|
|
background: 'var(--color-surface)',
|
|
color: 'var(--color-text)',
|
|
fontSize: 14,
|
|
fontWeight: 600,
|
|
cursor: 'pointer',
|
|
lineHeight: 1.4,
|
|
};
|
|
|
|
const pagButtonDisabledStyle: React.CSSProperties = {
|
|
...pagButtonStyle,
|
|
opacity: 0.35,
|
|
cursor: 'not-allowed',
|
|
};
|
|
```
|
|
|
|
Update pagination controls — replace existing "Назад" / "Вперед" buttons and "Страница N" text:
|
|
```tsx
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
|
<button
|
|
type="button"
|
|
onClick={onPrevious}
|
|
disabled={!canGoBack}
|
|
style={canGoBack ? pagButtonStyle : pagButtonDisabledStyle}
|
|
>
|
|
←
|
|
</button>
|
|
<span
|
|
style={{
|
|
minWidth: 20,
|
|
textAlign: 'center',
|
|
color: 'var(--color-text-secondary)',
|
|
fontSize: 14,
|
|
fontWeight: 600,
|
|
}}
|
|
>
|
|
{pageNumber}
|
|
</span>
|
|
<button
|
|
type="button"
|
|
onClick={onNext}
|
|
disabled={!canGoForward}
|
|
style={canGoForward ? pagButtonStyle : pagButtonDisabledStyle}
|
|
>
|
|
→
|
|
</button>
|
|
</div>
|
|
```
|
|
|
|
- [ ] **Step 4: Run tests**
|
|
|
|
Run: `npx vitest run apps/frontend/src/pages/broker/BrokerPages.test.tsx`
|
|
Expected: PASS
|
|
|
|
- [ ] **Step 5: Run full test suite**
|
|
|
|
Run: `npm run test:frontend`
|
|
Expected: PASS
|
|
|
|
- [ ] **Step 6: Commit**
|
|
|
|
```bash
|
|
git add apps/frontend/src/pages/broker/BrokerOperationsTable.tsx
|
|
git commit -m "feat: remove impact badges, add + prefix, style pagination buttons"
|
|
```
|
|
|
|
---
|
|
|
|
### Task 4: Add keepPreviousData to operations query
|
|
|
|
**Files:**
|
|
- Modify: `apps/frontend/src/hooks/useBrokerOperations.ts`
|
|
|
|
- [ ] **Step 1: Add keepPreviousData**
|
|
|
|
Update `useBrokerOperations.ts`:
|
|
```tsx
|
|
import { keepPreviousData, useQuery } from '@tanstack/react-query';
|
|
|
|
export function useBrokerOperations(
|
|
accountId: string | undefined,
|
|
query: BrokerOperationQuery = {},
|
|
) {
|
|
return useQuery<BrokerOperationsPage>({
|
|
queryKey: ['broker', 'operations', accountId, query],
|
|
enabled: Boolean(accountId),
|
|
queryFn: async () => (await getBrokerOperations(accountId!, query)).data,
|
|
placeholderData: keepPreviousData,
|
|
staleTime: 300_000,
|
|
retry: 2,
|
|
refetchOnWindowFocus: false,
|
|
});
|
|
}
|
|
```
|
|
|
|
- [ ] **Step 2: Run full test suite**
|
|
|
|
Run: `npm run test:frontend`
|
|
Expected: PASS
|
|
|
|
- [ ] **Step 3: Commit**
|
|
|
|
```bash
|
|
git add apps/frontend/src/hooks/useBrokerOperations.ts
|
|
git commit -m "feat: add keepPreviousData for smooth pagination"
|
|
```
|
|
|
|
---
|
|
|
|
### Task 5: Run lint and verify
|
|
|
|
- [ ] **Step 1: Run lint**
|
|
|
|
Run: `npm run lint`
|
|
Expected: PASS (no lint errors)
|
|
|
|
- [ ] **Step 2: Run full test suite**
|
|
|
|
Run: `npm run test:frontend`
|
|
Expected: PASS
|
|
|
|
- [ ] **Step 3: Verify build**
|
|
|
|
Run: `npm run build:frontend`
|
|
Expected: PASS
|
|
|
|
- [ ] **Step 4: Final commit if any fixes**
|
|
|
|
```bash
|
|
git commit -m "chore: fix lint issues"
|
|
```
|