# Menu links: достижимость новых страниц Sprint 31 **Проблема (от координатора).** Маршруты `/purchases/invoices`, `/purchases/invoices/:id`, `/purchases/supplies/scan` и `/inventory/mobile` объявлены в `App.tsx`, но пользователь к ним никак не доберётся: ни в sidebar (`AppLayout.tsx`), ни в `CommandPalette`, ни в `QuickActionsPalette` ссылок нет. На страницах `/purchases/supplies` и `/inventory/inventories` тоже нет кнопок, которые бы вели на новые UX-ветки. **Условия задачи.** - Админ + Кладовщик видят новые пункты; Кассир — нет. - Пункты видны в простом режиме (`isAdvancedMode === false`) тоже — это базовые приёмка/инвентаризация, а не расширенные фичи. - i18n: ru обязательно, en — потому что меню переводится. - Playwright-проход «кликами с главной» на desktop (1280×800) + mobile (375×667) под demo-keeper и demo-admin; плюс негатив-проход для demo-cashier. - Аудит сирот: диффим `` из `App.tsx` против фактических точек входа. **Границы.** Не трогаем прод, `global.json`, `deploy/*/nginx`. ## Чек-лист - [x] 1. Главное меню `AppLayout` — пункты «Накладные (по фото)» (`/purchases/invoices`) в разделе «Закупки» и «Инвентаризация с телефона» (`/inventory/mobile`) в разделе «Остатки» для ролей Admin / Storekeeper; видны в простом режиме; i18n ru + en. - [x] 2. Dropdown-кнопки входа на `/purchases/supplies` и `/inventory/inventories`: «Новая приёмка ▾» → Вручную / По фото накладной / Сканированием; «Новая инвентаризация ▾» → Вручную / С телефона. - [x] 3. CommandPalette (Cmd+K) + QuickActionsPalette (Cmd+J): добавить `invoices`, `supply-scan`, `inventory-mobile` в соответствующие списки. - [x] 4. ПРОВЕРКА ГЛАЗАМИ — Playwright `stage-ui-menu-links.spec.ts`: 3 новых страницы кликами с главной под demo-keeper и demo-admin, desktop + mobile; скриншоты в `tests/e2e/reports/`. Негатив для demo-cashier. - [x] 5. Аудит «сирот» — скрипт `tests/scripts/menu-orphans-audit.mjs`, отчёт в `docs/menu-orphans-report.md`. - [x] 6. `~/deploy-stage.sh` + ретест п.4 на свежем stage. ## Протокол выполнения ### 1. Главное меню (AppLayout) `src/food-market.web/src/components/AppLayout.tsx`: - В секцию «Остатки» (`section_inventory`) добавлен пункт `nav.inventoryMobile → /inventory/mobile` (icon `Smartphone`), виден под условием `isAdmin || isStorekeeper` — т.е. без `isCashier` — и в простом режиме, не завязан на `advanced`. - В секцию «Закупки» (`section_purchases`) — пункт `nav.invoices → /purchases/invoices` (icon `Camera`), те же роли, без advanced-гарда. - Параллельно вскрылся сирота `/admin/diagnostic` (см. п.5) — добавлен в `section_admin` под Admin'ом (icon `Stethoscope`). - i18n: обновили `locales/ru.json` + `locales/en.json` (`nav.inventoryMobile`, `nav.invoices`, `nav.diagnostic`). ### 2. Split-кнопки на list-страницах Новый компонент `src/food-market.web/src/components/SplitButtonMenu.tsx` — dropdown-кнопка «Новая …» с клавиатурной навигацией (↑↓/Enter/Esc, click-outside). Использована: - `SuppliesPage.tsx`: «Новая приёмка ▾» → **Вручную** (`/purchases/supplies/new`), **По фото накладной** (`/purchases/invoices`), **Сканированием** (`/purchases/supplies/scan`). - `InventoriesPage.tsx`: «Новая инвентаризация ▾» → **Вручную** (`/inventory/inventories/new`), **С телефона** (`/inventory/mobile`). Селекторы `data-testid=supplies-new-dropdown`, `inventories-new-dropdown`, плюс каждый пункт меню — для e2e. ### 3. CommandPalette + QuickActions `components/CommandPalette.tsx`: добавлены `page:invoices`, `page:supply-scan`, `page:inventories` (ранее отсутствовал), `page:inventory-mobile` в `STATIC_PAGES`. Иконки `Camera`, `ScanLine`, `ClipboardCheck`, `Smartphone`. `components/QuickActionsPalette.tsx`: действия `invoice-new`, `supply-scan`, `inventory-mobile` в `ACTIONS`. ### 4. Playwright-проверка глазами `tests/e2e/scenarios/stage-ui-menu-links.spec.ts` — 5 тестов: - `demo-keeper / desktop` — ✓ 10.5s - `demo-keeper / mobile` — ✓ 24.1s (drawer открывается hamburger'ом) - `demo-admin / desktop` — ✓ 10.5s - `demo-admin / mobile` — ✓ 10.3s - `demo-cashier` negative — ✓ 3.9s (нет пунктов «Накладные (по фото)», «Инвентаризация с телефона», и раздела «Приёмки») Итого **5/5 passed** за 60 секунд против свежего stage (`https://test.admin.food-market.kz`). Логин через sentinel-пароль `__QUICK_LOGIN_PWLESS__` (тот же механизм, что SPA использует при клике по карточке demo-аккаунта). Скриншоты в `tests/e2e/reports/`: `menu-links-{demo-admin|demo-keeper}-{desktop|mobile}-{invoices|supply-scan|inventory-mobile}.png` (12 позитивных) + `menu-links-demo-cashier-desktop-sidebar.png`. ### 5. Orphan-audit `tests/scripts/menu-orphans-audit.mjs` — парсит `App.tsx`, диффит все `` из tenant-ветки против всех строк, встречающихся в sidebar / CommandPalette / QuickActionsPalette / split-кнопках `SuppliesPage.tsx` + `InventoriesPage.tsx`. Классификация: 57 tenant-маршрутов → 20 служебных (`/login`, `/auth-bridge`, `/:id`-формы, `/new`-формы, супер-админ), 37 проверяемых. **После всех правок: 0 сирот.** Отчёт — `docs/menu-orphans-report.md`. Первый прогон обнаружил `/admin/diagnostic` — исправлено в п.1. ### 6. Deploy stage + retest `~/deploy-stage.sh` → `[stage] OK — https://test.admin.food-market.kz`. После деплоя тот же `stage-ui-menu-links.spec.ts` — **5/5 passed**. ## Итог Все 6 шагов выполнены. Новые экраны Sprint 31 полноценно встроены в навигацию: sidebar + Cmd+K + Cmd+J + split-кнопки на list-страницах. Автоматический orphan-audit в `tests/scripts/menu-orphans-audit.mjs` можно гонять в CI как регрессионную защиту от повторения проблемы. Прод, `global.json`, `deploy/nginx*` — не трогались.