# Active Context — Strava Frontend ## Task State - task_id: TASK-MCP-SETUP - status: success - parent_task: — - summary: **Настроить Playwright MCP для UI-верификации через браузер. Конфиг Zoo Code обновлён (Node 22), Chromium установлен.** - next task: — ## TASK-MCP-SETUP: Playwright MCP configuration **Что сделано:** - MCP-конфиг Zoo Code (`mcp_settings.json`): server `web-browser` → `@playwright/mcp@latest`, Node 22 via nvm absolute path, `--headless` - Chromium `1234` уже установлен в `~/.cache/ms-playwright/` - `.mcp.json` создан в проекте (project-level, для совместимости) - `techContext.md` обновлён: секция "UI Verification (MCP Browser)" **Как использовать (workflow):** 1. `yarn dev` — запустить dev server (порт 5173) 2. `browser_navigate` → `http://localhost:5173/explore` — проверить публичную страницу 3. `browser_evaluate` → `() => { localStorage.setItem('token', 'test'); localStorage.setItem('user', JSON.stringify({id:1,name:'Test'})); location.reload(); }` — сымитировать auth 4. `browser_navigate` → проверить auth-страницы (`/workouts`, `/workouts/:id`) 5. `browser_snapshot` — проверить DOM-структуру 6. `browser_take_screenshot` — визуальная проверка 7. `browser_network_requests` — проверить API-запросы ### Баг (контекст) Сайдбар показывает `publicRoutes` (Лента + Маршрут) после логина до F5. Корень: [`NavigationRoutes.ts:70`](src/components/sidebar/NavigationRoutes.ts:70) — `routes` вычисляется один раз при module evaluation и кэшируется. TASK-AUTH-NAV-1 уже добавил реактивный `isAuthenticated` в `useGlobalStore` (инициализация из localStorage + `setAuthenticated` в Login/Logout). Эта задача переключает UI на computed. ### TASK-AUTH-NAV-2: реактивные маршруты (3 файла) **1. `src/components/sidebar/NavigationRoutes.ts`** - Сделать named exports: `export const authRoutes: INavigationRoute[]` и `export const publicRoutes: INavigationRoute[]` (сейчас это локальные `const`, не экспортированные). - Убрать статическое поле `routes` из default export (или оставить default без `routes`, т.к. оба потребителя перейдут на computed). `INavigationRoute` интерфейс — не трогать. - Важно: массивы `authRoutes`/`publicRoutes` остаются теми же по структуре/содержимому — только экспортируются. **2. `src/components/sidebar/AppSidebar.vue`** (Options API, `setup()`) - `import { useGlobalStore } from "../../stores/global-store";` + `import { authRoutes, publicRoutes } from "./NavigationRoutes";` (импорт `navigationRoutes` по default можно оставить/убрать — но все обращения `navigationRoutes.routes` заменить). - В `setup()`: `const globalStore = useGlobalStore();` - computed: `const routes = computed(() => globalStore.isAuthenticated ? authRoutes : publicRoutes);` - В `return` заменить `navigationRoutes` на `routes` (тепловой шаблон уже использует `navigationRoutes.routes` → поправить на `routes.value`? НЕТ — в Options API computed из setup доступно в шаблоне как `routes` без `.value`, т.е. в шаблоне `navigationRoutes.routes` → `routes`). - `setActiveExpand`: `navigationRoutes.routes.map(...)` → `routes.value.map(...)` (в setup `.value` нужен). - Шаблоны: `v-for="(route, index) in navigationRoutes.routes"` → `in routes`. **3. `src/components/app-layout-navigation/AppLayoutNavigation.vue`** (script setup) - `import { authRoutes, publicRoutes } from "../sidebar/NavigationRoutes";` + `import { useGlobalStore } from "../../stores/global-store";` - `const globalStore = useGlobalStore();` - `findRouteName` (строка ~64): `traverse(NavigationRoutes.routes)` → `traverse(globalStore.isAuthenticated ? authRoutes : publicRoutes)`. - Убедиться, что `items` computed (зависит от `route.matched` и `findRouteName`) остаётся реактивным — т.к. `findRouteName` читает `globalStore.isAuthenticated` внутри `items` computed, реactivity сохранится. ### Acceptance Criteria (TASK-AUTH-NAV-2) 1. `yarn lint` → 0 ошибок. 2. `yarn build` → 0 ошибок (vue-tsc --noEmit). 3. `NavigationRoutes.ts`: `authRoutes` и `publicRoutes` экспортируются; статического `routes` с localStorage-тернарником больше нет. 4. `AppSidebar.vue`: routes = computed от `globalStore.isAuthenticated`; `setActiveExpand` использует `routes.value`. 5. `AppLayoutNavigation.vue`: `traverse` использует выбор по `globalStore.isAuthenticated`. 6. **Ручной сценарий (ключевой)**: без F5 — выход из профиля → `/explore` → логин → сайдбар **сразу** показывает «Мои тренировки» (authRoutes). Аут → сайдбар сразу `publicRoutes`. ## ✅ CODER SUCCESS REPORT — TASK-AUTH-NAV-2 - `src/components/sidebar/NavigationRoutes.ts`: `export const authRoutes` / `export const publicRoutes`; удалён статический `routes: localStorage.getItem("token") ? ...` из default export (оставлен только `root`). - `src/components/sidebar/AppSidebar.vue`: импорт `authRoutes, publicRoutes` + `useGlobalStore`; `computed(() => globalStore.isAuthenticated ? authRoutes : publicRoutes)`; `setActiveExpand` использует `routes.value.map`; шаблон `v-for="(route, index) in routes"`. - `src/components/app-layout-navigation/AppLayoutNavigation.vue`: `const globalStore = useGlobalStore()`; `traverse(globalStore.isAuthenticated ? authRoutes : publicRoutes)` внутри `findRouteName` (вызывается в `items` computed → реactivity сохранена). - Verified: `yarn lint` exit 0, `yarn build` exit 0 (vue-tsc --noEmit 0 ошибок, vite ✓ 7.07s). ## История (закрытые задачи) - **TASK-AUTH-NAV-1**: success — `isAuthenticated` + `setAuthenticated` в `useGlobalStore`; Login `setAuthenticated(true)`, Logout `setAuthenticated(false)`. Verified lint/build 0. - TASK-SSR-DETAIL: success — SSR /public/workouts/:id под DOM WorkoutItem.vue. - TASK-404: success — HTTP 404 для неизвестных страниц. - TASK-PUBLIC-ROUTE-FIX: success — workout_public_item в top-level router. - TASK-F11/F12/F13/F14: success — SEO + фиксы карты тренировки.