# Active Context — Strava Frontend ## Task State - task_id: TASK-F1 (PARENT) - status: success (CLOSED) - parent_task: — - summary: **Галерея фото тренировки + загрузка/удаление + маркеры фото на Yandex-карте (components/WorkoutItem.vue).** npm run build exit 0 (vue-tsc + vite), npm run lint exit 0. - next task: create a NEW task_id when starting the next feature. ## TASK-F1 — TODO - [x] `src/pages/workouts/Definitions.vue`: тип `WorkoutPhoto` + `photos?: Array` в `WorkoutItem` (fetch менять не нужно — бэкенд уже присылает `workout.photos`). - [x] `src/pages/workouts/components/WorkoutItem.vue`: `photos` ref (из `workoutItem?.photos`), `photosWithCoords` computed, `` для фото с координатами (порядок `[lon, lat]` как у `clickCoordinates`, `color: 'blue'`, onClick → `window.open(photo.url, "_blank")`). - [x] `src/pages/workouts/components/WorkoutItem.vue`: секция `#workout-photos` под `#workout-container` — grid ``, «Добавить фото» (`v-if="isPrivate"`, скрытый `input[type=file] accept="image/*" multiple`, `axiosAuth.post` multipart поле `file`, `Promise.allSettled`, ответ в `photos`, VaButton `:loading`), «Удалить» (`v-if="isPrivate"`, `axiosAuth.delete` → убрать из массива), ошибки/успех — `useToast`. - [x] `src/pages/workouts/components/WorkoutItem.vue`: `isPrivate` добавлен в деструктуризацию `defineProps`; стили `.workout-photos-*` (grid auto-fill 160px, img 120px object-fit cover, кнопка удаления absolute). - [x] `WorkoutListItem.vue` НЕ тронут (по ТЗ). - [x] Верификация: `npm run build` exit 0 (vue-tsc --noEmit + vite, ~8–12s), `npm run lint` exit 0 (prettier+eslint --fix). ## ✅ CODER SUCCESS REPORT — TASK-F1 - Изменены файлы: `src/pages/workouts/Definitions.vue` (+8 строк: тип `WorkoutPhoto`, поле `photos?`), `src/pages/workouts/components/WorkoutItem.vue` (+163 строки: маркеры фото, галерея, upload/delete, стили). - `photos` — локальный `ref>` (иниц. из пропса), все мутации только по нему; `axiosAuth` — существующий `inject("axiosAuth")`. - Маркеры: `` с `coordinates: [lon, lat] as LngLat` (тот же порядок, что у `clickCoordinates`), `color: 'blue'` для отличия от серых маркеров кликов; onClick → `window.open(photo.url, "_blank")`. - Загрузка: `Promise.allSettled` по каждому файлу (multipart, поле `file`); успех → push в `photos` + toast success; частичная неудача → toast error «Не удалось загрузить часть фото.»; `:loading` на кнопке. - Удаление: `axiosAuth.delete` → filter из `photos`; ошибка → toast «Не удалось удалить фото.» - Кнопки «Добавить фото»/«Удалить» и `v-if` секции только при `isPrivate` (владелец); на публичной странице (`WorkoutPublicItem.vue`, `isPrivate=false`) фото видны только-чтение без управления. - `npm run build`: exit 0, `✓ built in 11.71s` (vue-tsc 0 ошибок; warning о chunk >500kB — предсуществующий). - `npm run lint`: exit 0 (prettier: `WorkoutItem.vue` переформатирован, eslint 0 ошибок). - Ручные проверки (сценарии для QA): фото с GPS → в галерее + синий маркер на карте; фото без GPS → только в галерее; добавление нескольких файлов сразу → все добавлены, `:loading` на кнопке во время; удаление → исчезло из галерее и с карты; публичная страница → фото видны, кнопок нет; клик по фото/маркеру → opens в новой вкладке. ## W3 acceptance criteria - `eslint` 9.x + `typescript-eslint` 8.x in yarn.lock; legacy `@typescript-eslint/eslint-plugin@6` + `@typescript-eslint/parser@6` removed (superseded by the `typescript-eslint` 8 meta-package); NO other package moved to a new major - `yarn lint` 0 errors + `yarn build` green - `eslint.config.mjs` adjustments minimal and documented (flat config already in use — migration should be trivial) - Memory Bank: status `success` + Success Report ## W3 notes for the Coder - Current state: `eslint@8.57.1` (flat config works on 8.57), `typescript-eslint@7.18.0`, legacy `@typescript-eslint/eslint-plugin@^6.11.0` + `@typescript-eslint/parser@^6.11.0` still in package.json (redundant with the meta-package but currently unused by eslint.config.mjs). - Target: `yarn add -D eslint@^9 typescript-eslint@^8`, then `yarn remove @typescript-eslint/eslint-plugin @typescript-eslint/parser` ONLY if eslint.config.mjs does not import them directly (check first). - eslint 9 removes some legacy config options — if `eslint.config.mjs` breaks, apply the minimal migration (documented). - `eslint-plugin-prettier`/`@vue/eslint-config-prettier` are NOT part of W3 — leave versions as-is. ## W2d acceptance criteria - `package.json`: no `storybook`/`@storybook/*`/`eslint-plugin-storybook` deps, no `storybook`/`build-storybook` scripts - yarn.lock: no `@storybook/vue3-vite` entry, no nested `@vitejs/plugin-vue@4` install - `yarn lint` 0 errors + `yarn build` green - `eslint.config.mjs` — no references to storybook plugin (verify; add minimal fix if present) - Memory Bank: status `success` + Success Report (removed list, install-size delta if measurable) ## W2b acceptance criteria - `vue-tsc` resolved to 2.x and `typescript` to 5.8.x in yarn.lock; NO other package moved to a new major - `yarn lint` — 0 errors; `yarn build` — green (vue-tsc 2 type-check 0 errors, bundle built) - Minimal type-only fixes in `src/` allowed only if required by the stricter checker; each documented with justification - Memory Bank: status `success` + Success Report (old/new versions, full list of src/ fixes with justification) ## Wave plan (each wave = one atomic task, verified independently) - **W0a (TASK-DEPS-UPDATE-W0a, success)**: Fix everything that hard-blocks `yarn build`: - `LineWithLineChart.ts(41)` TS2532 "Object is possibly 'undefined'" (labels can be undefined) — fix via non-null assertion or guarded length. - SFC parsing errors: `src/pages/workouts/components/WorkoutItem.vue:260` (`Unexpected token {`) and `WorkoutListItem.vue:60` (`'interface' is reserved`). Root-cause candidates: TS syntax in a plain `