2026-06-25 06:44:31 +03:00

117 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Индикация загрузки при переключении страниц в таблицах брокера
Дата: 2026-06-18
Статус: реализовано
## Контекст
Страница детального просмотра брокерского счёта (`BrokerAccountDetailPage.tsx`) содержит несколько таблиц с пагинацией:
- **PositionGroupTable** — Акции, Облигации, ETF, Фонды (4 независимые таблицы с курсорной пагинацией)
- **BrokerOperationsTable** — Операции (курсорная пагинация, управляемая из родительского компонента)
Текущее поведение при переключении страниц: `isLoading === true` → таблица скрывается, показывается `TableSkeleton` (shimmer-строки). Это создаёт визуальный flash: контент исчезает → скелетон → новые данные. При этом `placeholderData: keepPreviousData` уже настроен в хуках, но компоненты его не используют — они проверяют `isLoading`, а не `data`.
## Цель
Добавить плавную индикацию загрузки при переключении страниц, чтобы пользователь видел, что данные обновляются, но не терял визуальный контекст.
## Дизайн (выбран C3)
### Визуальное поведение
1. При нажатии «→» (вперед) или «←» (назад):
- Текущее содержимое таблицы **остаётся видимым** (предыдущая страница)
- Поверх таблицы появляется **полупрозрачный overlay** с центрированным спиннером
- Кнопка пагинации показывает спиннер и блокируется
2. Когда новые данные загружены:
- Overlay исчезает с fade-out
- Таблица обновляется новыми данными
3. При первой загрузке (initial load):
- Overlay не используется (нет старых данных для показа)
- Показывается `TableSkeleton` (как сейчас)
### Как это работает технически
TanStack Query v5 предоставляет два флага:
- `isLoading` — true, когда данных **нет** и идёт первый запрос (initial load)
- `isFetching` — true при любом запросе (включая фоновые refetch'и при смене cursor)
Логика рендеринга для таблиц:
```
if isLoading → TableSkeleton (первая загрузка, данных нет)
if isFetching && data → TableLoadingOverlay + старые данные (переключение страниц)
иначе → рендер таблицы с данными
```
### Компонент TableLoadingOverlay
```tsx
interface TableLoadingOverlayProps {
pageNumber?: number;
}
function TableLoadingOverlay({ pageNumber }: TableLoadingOverlayProps) {
return (
<div style={{
position: 'absolute', inset: 0,
background: 'rgba(255,255,255,0.65)',
display: 'flex', alignItems: 'center', justifyContent: 'center',
flexDirection: 'column', gap: 12,
transition: 'opacity 0.2s ease',
}}>
<div className="loading-spinner" />
{pageNumber !== undefined && (
<span style={{ fontSize: 13, color: 'var(--color-text-secondary)' }}>
Загрузка страницы {pageNumber}
</span>
)}
</div>
);
}
```
### Пагинация: спиннер в кнопке
При `isFetching` кнопка «→» или «←» показывает спиннер вместо стрелки и становится disabled.
```css
@keyframes loading-spin {
to { transform: rotate(360deg); }
}
.loading-spinner {
width: 20px; height: 20px;
border: 2px solid var(--color-border);
border-top-color: var(--color-accent);
border-radius: 50%;
animation: loading-spin 0.8s linear infinite;
}
```
## Где применяется
| Компонент | Что меняется |
|---|---|
| `BrokerPositionsSection.tsx` (PositionGroupTable) | Overlay вместо TableSkeleton при isFetching. Спиннер в кнопках пагинации |
| `BrokerOperationsTable.tsx` | Overlay вместо TableSkeleton при isFetching. Спиннер в кнопках пагинации |
## Файлы для изменения
| Файл | Изменение |
|---|---|
| `apps/frontend/src/styles.css` | Добавить `@keyframes loading-spin`, `.loading-spinner`, `.table-loading-overlay` |
| `apps/frontend/src/pages/broker/BrokerPositionsSection.tsx` | Overlay + спиннер в пагинации. Использовать `isFetching` из хука |
| `apps/frontend/src/pages/broker/BrokerOperationsTable.tsx` | Overlay + спиннер в пагинации. Использовать `isFetching` из хука |
| `apps/frontend/src/pages/broker/BrokerAccountDetailPage.tsx` | Прокинуть `isFetching` для операций (из useBrokerOperations) |
| `apps/frontend/src/pages/broker/BrokerPages.test.tsx` | Обновить тесты для overlay-логики |
## Тестирование
- `npm run test:frontend` — существующие тесты проходят с учётом изменений
- Ручная проверка: переключение страниц в Акциях, Облигациях, Операциях — overlay появляется/исчезает
- Ручная проверка: при первой загрузке — skeleton (не overlay)
- Ручная проверка: при быстром переключении (быстрее, чем загрузка) — overlay остаётся, данные не мигают