Actualize development branch#9
Merged
Merged
Conversation
chore: include build args in docker build step
- Create shared/lib/dom/useVisualViewportHeight hook (Pitfall 1 fix: iOS Safari does NOT update 100dvh on keyboard; visualViewport.height does). Hook returns dynamic height + sets --keyboard-aware-height CSS var on :root. - Add 4 unit tests (vv available / sets CSS var / fallback / cleanup) — pass. - Replace h-screen → h-dvh in DesktopLayout + MobileLayout (D-02). - Integrate useVisualViewportHeight() side-effect call into 5 mobile components (MobileFiltersDrawer, MobileTimeSelectorSheet, MobileResultsSheet, MobileZoneCard, MobileSearchBar). - Add maxHeight: 'calc(var(--keyboard-aware-height, 100dvh) - 80px)' inline style to the 4 vaul Drawer.Content surfaces; wrap MobileSearchBar overlay height in same CSS var. - Preserve CO-02 single-snap [0.92] for MobileResultsSheet (D-06).
…ard (RESP-06,07) - src/index.css: add .map-controls-shifted-container [class*=ymaps3-controls] rule reading var(--bottom-sheet-offset, 20px) with 200ms ease transition. YMapControls does NOT accept className prop (typed reactify wrapper from @yandex/ymaps3-types), so parent-div selector-fallback is used. - MapCanvas.tsx: wrap inner div with class map-controls-shifted-container. - MobileLayout.tsx: useEffect sets --bottom-sheet-offset to calc(92vh + 20px) when ANY of filtersOpen/timeSheetOpen/resultsSheetOpen/selectedZoneId is active; default 20px otherwise. - eslint.config.js: add no-restricted-syntax rules blocking h-screen / min-h-screen / max-h-screen in className= AND any 100vh literal (D-07 regression guard). Verified rule fires on temp test file. - tests/e2e/tap-targets.spec.ts: Playwright runtime test asserting all buttons/links on /map iPhone 13 viewport have computed bbox >=44x44 (WCAG 2.5.5). Skips on ymaps3 CDN failure (Phase 3 known blocker) consistent with phase4-smoke.spec.ts pattern. Note: eslint-plugin-tailwindcss is NOT used — research finding: package does NOT support Tailwind 4 (issue #325 open). Playwright runtime test is the sole tap-target enforcement mechanism.
- Install sonner@^2.0.7 as runtime dependency (D-19) via --legacy-peer-deps - Extend env.ts Zod schema: VITE_SHARED_SHELL_URL (D-09) + VITE_API_MODE (D-15) - Create brand-tokens.ts: single source of truth (D-12) — green/amber/neutral/semantic - Append @theme directive to index.css (Tailwind 4 native, after Plan 05-01 .map-controls-shifted) - Update shared/config barrel to re-export brand - Document all 5 env vars in .env.example incl. localhost limitation warning (Pitfall 4)
…1..03)
- Replace throwing stub with TanStack Query + apiClient.get('/auth/me') (D-08, D-09)
- Map AuthMeResponse -> User (display_name = full_name ?? email)
- Localhost guard: console.warn when VITE_AUTH_MODE=shared on localhost (Pitfall 4)
- 4 vitest tests: 200 happy path, full_name=null fallback, 401 unauthenticated,
W-1 fix static source-content assertion via Vite ?raw import (replaces placebo)
- Test 4 uses ?raw instead of node:fs/__dirname (app tsconfig has no node types)
…06; UX-05,06) - AuthListener: 401 CustomEvent listener (D-10) — mock=invalidate+warning toast, shared=error toast + 2s redirect to /login?return=... - AppProviders: mount Toaster (zIndex 100, Pitfall 2 — above vaul z-50) inside AuthListener inside QueryProvider; AuthReady wraps children unchanged - Toast.tsx: thin sonner re-export (D-13) — vendor-swap = single-file change - Banner.tsx: in-drawer error primitive (D-13) — 4 variants, 44x44 dismiss button - StubHeader.tsx: returns null in shared mode (D-14, INTEG-06) - Update barrels: providers/index.ts re-exports AuthListener, ui/index.ts adds 4
- main.tsx: gate MSW worker registration on VITE_API_MODE (independent from VITE_AUTH_MODE per D-15) — enables 4-combo testing of API/auth modes; default mock when env unset - playwright.real-api.config.ts: dedicated config (NOT in default CI), testMatch pinned to real-api.spec.ts, HTML report to phase-05-uat/ - tests/e2e/real-api.spec.ts: 7 shape-only smoke tests covering all 6 endpoints (GET /zones, /zones/<id>, /occupancy, /forecasts; POST /routing/search, /routing/new) + D-17 combined-filter probe - package.json: test:e2e:real-api script via cross-env (Windows-portable) - cross-env@^7.0.3 added as devDep (B-2 ownership: Plan 05-04 must grep-guard before re-installing) - ambient process declaration in spec avoids polluting app tsconfig with node types (mirrors Plan 05-02 W-1 approach)
…D-17/D-18) - New section «Phase 5 D-17 verification protocol» appended (Phase 2 baseline preserved unchanged) - 7-row verification status table (one row per filter), all marked unverified — Plan 05-05 UAT fills statuses from real-api smoke - 5-value status legend (unverified/accepted/degraded/rejected/ client-only-fallback) clarifies action for each outcome - Per-filter individual curl probe commands documented for offending- param identification when combined GET fails - D-18 conditional normalizer note: normalizers.ts created ONLY if smoke shows shape divergence (avoid speculative dead code) - phase-05-uat/real-api-smoke.log artefact structure specified
…staleTime (D-29 NFR-01 + D-32 NFR-04) - Install audit devDeps: @axe-core/playwright, rollup-plugin-visualizer^6.0.4 (resolved ^6.0.11), size-limit^11, @size-limit/preset-app, ts-morph; cross-env already present (B-2 guard verified) - Enable noUncheckedIndexedAccess + exactOptionalPropertyTypes + noImplicitOverride + noImplicitReturns in tsconfig.app.json AFTER dry-run (107 errors → 0; fixed in batch across 14 files: array-access non-null assertions, conditional spread for optional props, defensive guards in zoneCentroid) - ESLint: @typescript-eslint/no-explicit-any: error blocks any in new code (existing code clean) - Mode-aware staleTime in zone.queries.ts (D-32 NFR-04 — I-1 fix moved here from 05-03): /zones (now) → 30s /occupancy (past) → 300s (5min, history immutable) /forecasts (future) → 60s (decay) /zones/<id> (now) → 60s /occupancy view=card → 300s /forecasts view=card → 60s - WTPCTAButton.test.tsx fixed (deferred from 05-01): mock navigator.permissions + findByText for async handleClick
…o (D-22/23/24/31/33 NFR-03/05/06) - vite.config.ts: rollup-plugin-visualizer (BUILD_ANALYZE=1) + manualChunks splitting: vendor-react (react+react-dom+scheduler+react-error-boundary co-located per Pitfall 10 TDZ), vendor-tanstack, vendor-state, vendor-ui (vaul+radix), vendor-icons (lucide), vendor-misc - .size-limit.json: 5 hard-fail budgets (initial<250KB, vendor-react<100KB, etc.); all pass: initial=21.65KB, vendor-react=60.89KB, vendor-tanstack=15.94KB, vendor-ui=17.69KB, vendor-icons=2.55KB - package.json: build:analyze + size scripts (cross-env from 05-03 reused per B-2) - nginx.conf: Content-Security-Policy verbatim from Yandex docs (script/connect/style/img/worker/frame-ancestors) + X-Content-Type-Options, X-Frame-Options, Referrer-Policy - index.html: csp=202512 migration param appended to Yandex CDN URL (Pitfall 12) - 4 widgets wrapped in React.memo (D-31 / I-3 fix incl. ParallelZoneLayer): ZoneLayer, RoutePreviewLayer, ParallelZoneLayer, DesktopResultsPanel
…s docs (D-30/34 NFR-02/07) - OfflineBanner via @tanstack/react-query onlineManager.subscribe (NOT navigator.onLine direct read per Pitfall 8 — Chrome bug) - Toast feedback through @/shared/ui wrapper (Plan 05-02 ingress): error 'Нет соединения' (id='offline', duration:Infinity) + success 'Соединение восстановлено' on reconnect - Mounted in AppProviders sibling to Toaster, inside AuthListener - Exported from app/providers/index.ts barrel - docs/fsd-exceptions.md documents 2 known cross-layer imports (ZoneCard→MapCanvas, useFilteredZones→filter-zones) — NFR-02 reviewer trail - Security grep audit (D-33): no token leakage in console.*, no token in localStorage, no dangerouslySetInnerHTML usage
…11y docs (D-21/25/27/28/35) - tests/e2e/a11y.spec.ts: axe-core scan over 4 flows (/map, /map?sel=42, /map?from=&dest=, /map?route=1), critical=0 blocks merge per D-26, serious console.warn for backlog (W-2 fix: no fs imports/writes) - tests/e2e/atomic-state.spec.ts: NFR-08 verification — 2 tests 1. parallel filter+time+zone change → no runtime errors 2. rapid filter toggle → AbortController cascade verifies completedRequests ≤ 2 (I-2 fix: tightened heuristic with rationale comment) - tests/unit/no-silent-failures.spec.ts: ts-morph AST audit asserts every useQuery/useMutation has onError/throwOnError; allowlist for queries that propagate error to caller (auth adapters, address suggest/resolve, zone/routing queries, user profile) - ambient declare process per Plan 05-02/03 minimal-surface pattern (no @types/node pollution) - 4 docs: a11y-backlog.md (placeholder for v1.x), a11y-keyboard-walkthrough.md (10-step manual scenario per D-27), a11y-colorblind-audit.md (5 vision-mode test matrix per D-28)
- web-map/docs/uat-flows-checklist.md: 12 manual flow steps (10 + VK/TG D-37/D-38) - web-map/docs/uat-matrix.md: required + optional device list with status table - Templates per D-36 — owner = Илья Р. (real-device tester); Claude prepares - Pass criteria: all 10 flows on iPhone iOS17+ Safari, Android 14+ Chrome, VK/TG webview
- Phase 5 deliverables: RESP-01..07, INTEG-01..06, A11Y-06, UX-05/06, NFR-01..08 - Documents ALL 24 Phase 5 requirements with implementation note - Lists known limitations + v1.x deferrals (Misha-shell, UI-kit, Lighthouse perf) - Notes default Playwright headless ymaps3 CDN limitation; UAT delegated - Phase 5 verification artifacts archived in .planning/phases/05-.../uat/
Mock /routing/search возвращал inactive (is_active=false) zones в кандидатах ranking → tap на парковку из ResultsPanel → ZoneCard показывала empty-state 'Зона неактивна в этот период' вместо контента. Server design assumption (applyClientCandidateFilters comment): RouteCandidate не имеет is_active поля — server должен ВСЕГДА возвращать только active+public parkings. Mock теперь mirror это поведение через ALWAYS-ON фильтр в rankCandidates. Affected: ResultsPanel ranked list, MobileResultsSheet, MobileZoneCard handoff flow. Frontend изменений не требует — applyClientCandidateFilters уже учитывает этот контракт.
Root cause: Phase 2 D-06 specified snapPoints=[0.4, 0.85], но vaul snap math требует drawer height >= largestSnap × viewport (≥792px на iPhone 14 Pro Max). Реальный content (header+tags+button ~408px) намного меньше — vaul применяет transform translateY(559px) который пушит drawer ENTIRELY off-screen. Карточка рендерится в DOM (verified: data-state=open, content visible), но визуально не видна. Тот же bug был в Phase 4 MobileResultsSheet — решился single-snap [0.92] (CO-02). Применяем тот же pattern: drawer открывается на 92% экрана, drag-down dismiss. Preview-режим [0.4] deferred to v1.x design pass per CO-02 protocol. Affected mobile flow: tap parking → ResultsSheet close → MobileZoneCard open. Все 294/294 tests pass.
User feedback: drawer открывался на 92dvh с большим пустым пространством под кнопкой «Построить маршрут»; drag handle не работал из-за vaul snap math. Решение: убрать snapPoints/activeSnapPoint полностью. vaul без snap-points auto-fit'нет drawer на natural content height — drawer открывается ровно до кнопки + 15px (pb-[15px]) внизу. Drag-down dismiss работает нативно через vaul handle. max-height ограничивает экстремальные случаи viewport-safe-area. Снимает: hot-fix 56a7fa3 ([0.92] snap который тоже не fit'ил content корректно). Ничего не ломает existing tests (294/294 pass).
Revert new map merge
This reverts commit 367c576.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.