58 lines
6.2 KiB
Markdown
58 lines
6.2 KiB
Markdown
## Context
|
||
|
||
См. `proposal.md` для мотивации и `specs/app-breadcrumb-navigation/spec.md` для контрактов поведения. `AppShell` является общим layout защищённых маршрутов и уже располагает содержимое над `<Outlet />`, но находится в shared-слое. Название Brokerage Account доступно через существующий query списка счетов и может отсутствовать при прямом переходе на маршрут счёта.
|
||
|
||
## Goals / Non-Goals
|
||
|
||
**Goals:**
|
||
- Показывать единый маршрутный trail над защищённым page content без изменения API.
|
||
- Использовать настоящее название Brokerage Account, когда оно доступно, и безопасный fallback в противном случае.
|
||
- Сохранить понятную навигацию на узких экранах.
|
||
|
||
**Non-Goals:**
|
||
- Не добавлять крошки на public и not-found маршруты.
|
||
- Не создавать endpoint отдельного Brokerage Account и не менять cache policy списка счетов.
|
||
- Не заменять существующую боковую или нижнюю навигацию.
|
||
|
||
## Decisions
|
||
|
||
### Route-aware компонент остаётся в app-слое
|
||
|
||
Добавить app-level компонент, который строит trail из текущего маршрута, его параметра `accountId` и локализованных строк. `AppRoutes` передаёт его в shared `AppShell` как content slot перед `<Outlet />`.
|
||
|
||
Это сохраняет FSD-направление зависимостей: shared layout не импортирует entity или feature. Альтернатива с определением маршрутов и загрузкой счета внутри `AppShell` смешала бы shared-слой с доменными данными.
|
||
|
||
### Название счёта берётся из существующего query списка
|
||
|
||
Подкомпонент для маршрутов `/accounts/:accountId` и `/accounts/:accountId/operations` использует существующий query Brokerage Account и находит запись по `accountId`. Пока query не вернул соответствующее название, trail показывает «Счёт».
|
||
|
||
Это поддерживает прямые переходы и повторно использует query cache списка. Альтернатива с передачей имени из каждой страницы дублировала бы route-логику и не покрывала бы loading/error state до отображения page content. Новый API endpoint не нужен: список уже содержит стабильный id и непустое name.
|
||
|
||
### Trail строится из фиксированной карты защищённых маршрутов
|
||
|
||
Карта определяет `Брокерские счета`, `Настройки`, Portfolio счёта и Account Ledger, а также destination URL для предшествующих элементов. Текущий элемент рендерится текстом, остальные - router links. Неизвестные и public routes возвращают отсутствие trail.
|
||
|
||
Фиксированная карта соответствует текущему небольшому набору маршрутов и исключает разбор URL по сегментам. Автоматическое построение из pathname было бы хрупким для динамического `accountId` и не предоставляло бы локализованного названия счёта.
|
||
|
||
### Крошки заменяют локальный возврат из Account Ledger
|
||
|
||
Удалить действие «К счёту» из заголовка Account Ledger: trail уже предоставляет ссылку на Portfolio текущего Brokerage Account.
|
||
|
||
Это устраняет дублирующий navigation control. Боковая и нижняя навигация остаются без изменений, поскольку ведут к другим разделам приложения.
|
||
|
||
### Адаптация сохраняет последние два элемента
|
||
|
||
На узком экране компонент передаёт в presentation только ближайшего родителя и текущий элемент; на широком экране показывает полный trail. Стили layout отвечают за перенос и отступ от page content.
|
||
|
||
Это прямо реализует согласованное поведение для трёхуровневой цепочки. Горизонтальная прокрутка или отдельное меню скрытых элементов добавили бы управление без новых маршрутов и не нужны для текущей глубины.
|
||
|
||
## Risks / Trade-offs
|
||
|
||
- [Прямой переход временно показывает обобщённое имя] → отображать «Счёт» до результата существующего query и не раскрывать `accountId`.
|
||
- [Запрос списка счётов ради названия] → монтировать account-aware подкомпонент только на маршрутах счёта; React Query повторно использует его 60-секундный cache.
|
||
- [Рост route map при новых страницах] → добавлять маршрут и его expected trail в той же app-level карте и соответствующем тесте.
|
||
|
||
## Migration Plan
|
||
|
||
Изменение не требует миграции данных или API. При rollback удалить slot и app-level компонент; существующие маршруты и page content продолжат работать без крошек.
|