R4 gap fixed: TimeGroup now accepts scheduledDayChange + actualDayChange props separately so each time type renders its own independent badge. FlightCard updated to pass them independently (scheduled vs actual/estimated); expanded row time block also now shows per-type badges. R5 tooltip fixed: dayChangeBadgeTooltip() uses string-based date extraction (no TZ reprojection via new Date()) — avoids viewer-TZ shift for SSR and cross-TZ correctness. Returns "День" for ±1, DD.MM.YYYY for ±2+. New shared helper dayChange.ts exports computeDayChange(), dayChangeBadgeTooltip(), formatDayChangeBadge(). 27 unit tests cover +0/+1/+2/-1/-2, null, malformed input, month/year boundaries, and per-time-type independence (R4). R1–R3, R6 confirmed correct (API supplies dayChange per ITimesSet; badge adjacent to time; hidden when 0). R8 (mobile tooltip suppression) deferred.
248 KiB
РИ-07-2538С — Online-Board & Schedule UI Redesign
Spec kind: TZ compliance audit + alignment plan
TZ source: ~/_projects/tims/Редизайн/РИ-07-2538C_ТЗ_Онлайн-Табло и Расписание_UI.docx (revision С)
Branch: redesign/ri-07-2538c-online-board-schedule-ui
Date: 2026-04-21
Repo: Aeroflot.Flights.Web
This is a contractual audit spec. Its job is to prove every 4.1.x rule in the TZ has been considered, map each rule to a concrete action, and track implementation to merge. The spec is the source of truth; six themed implementation plans off it do the actual work.
Revision С note
Revision С (2026) extends revision В by adding subsection 4.1.24 Карта полетов and Appendix 9 mockups. Everything else carries over from revision В. TZ-marked changes (vertical bar in the margin of the original docx) are implicitly covered by the per-subsection audit.
Scope
In scope for this repo
- Section 4.1 — external (public) "Онлайн-Табло и Расписание" section on aeroflot.ru.
- All subsections 4.1.1 – 4.1.24 inclusive.
- Binding NFRs that touch the frontend:
- 4.8.2 — capacity (100 RPS).
- 4.9 — external integrations (СТБ, Yandex.Metrica events 4.9.2).
- 4.11 — reliability (geo-distributed hosting, ≤6h recovery) — verified at deploy/infra layer, acknowledged here.
- 4.12 — ergonomics / a11y.
- 4.14 — security (component isolation per CLAUDE.md contract #5).
- 4.15.1 — FE stack (Modern.js + MF 2.0 + React 18, per CLAUDE.md).
- Appendices 4 (web mockups), 6 (mobile mockups), 7 (tablet mockups), 9 (map mockups) — binding visual references for 4.1.
Out of scope for this repo
- 4.2 — administrative UI (separate admin app, not
Aeroflot.Flights.Web). - 4.3, 4.4, 4.5 — backend REST APIs; this repo consumes them.
- 4.6, 4.7 — storage (S3) + SSM/ASM telegram processing (backend ingestion pipeline).
- Sections 5, 6, 7 — implementation, acceptance, documentation — handled at program level, not per-PR.
Viewport scope (Q3 = A)
Desktop, tablet, mobile all in scope for every 4.1.x subsection. Visual verification per Appendix 4 / 7 / 6 respectively. Behavioral rules that differ by viewport are called out in rule rows (example: 4.1.1-R5 mobile Время рейса default = -1/+3ч).
Glossary (Russian → English / code term)
| Russian term | English gloss | Code term / alias |
|---|---|---|
| Онлайн-Табло | Online-Board | onlineboard |
| Расписание | Schedule | schedule |
| Карта полетов | Flight Map | flights-map |
| Рейс | Flight | flight |
| Сегмент | Segment / leg | leg |
| Прямой рейс | Direct flight | direct |
| Многосегментный рейс | Multi-segment flight (single flight number, multiple legs) | multi-segment |
| Стыковочный рейс | Connecting flight (multiple flight numbers, transfer) | connecting / transfer |
| Промежуточная посадка | Intermediate landing (technical stop, same flight number) | intermediate-landing |
| Пересадка | Transfer (between legs of a connecting flight) | transfer |
| Табы-дни | Day tabs (results list) | DayTabs |
| Табы-недели | Week tabs (schedule results) | WeekTabs |
| Мини-список | Mini-list (compact flight strip at top of details page) | FlightsMiniList |
| Временная шкала | Timeline (direct-flight timeline in details) | FlightSchedule / FullRouteTimeline |
| «Вы искали» | "You searched" (recent-search history in filter) | SearchHistory |
| Хлебные крошки | Breadcrumbs | Breadcrumbs |
| Свернутое представление | Collapsed row (results list) | collapsed |
| Развернутое представление | Expanded row (results list) | expanded |
| Режим «Маршрут» | "Route" mode (city-based search) | routeMode |
| Режим «Номер рейса» | "Flight number" mode (number-based search) | flightNumberMode |
| Уточняется | "Being clarified" fallback text | tbd / copy key |
| ServiceType | Service-type code (J,S,U,Q,G,B,R,C) | serviceType |
TZ-defined constants
- Online-Board date window:
[-1 day, +14 days]from today. - Schedule date window:
[-1 day, +330 days]from today. - Flight Map date window:
[-1 day, +6 months]from today. - Included
ServiceTypes:J, S, U, Q, G, B, R, C. Flight numbers > 7000 excluded (see Appendix 3).
Reading the audit tables
Each subsection section has:
- Russian title (verbatim from TZ) + English gloss.
- 1–3 sentence summary of the subsection intent.
- An audit table with these columns:
| Column | Meaning |
|---|---|
# |
Stable rule ID — {subsection}-R{n}. Cited by implementation plans and test names. |
Rule |
Short English restatement. Russian key phrase in quotes when exact wording matters. |
TZ cite |
Section + one-line quote. Mockup references in Appendix N → media/imageNN.png form when applicable. |
Viewport |
desktop / tablet / mobile / all — which viewports the rule applies to. |
Current impl |
File + line (or — if not yet present). |
Status |
Implemented / Partial / Missing / Conflict / TBD. |
Action |
One-line directive for the plan. — if no action needed. |
Plan |
P1 through P6. |
Rule IDs are stable. If a rule is removed, its ID is retired (not reused). New rules get -R(n+1).
Status shorthand
- Implemented — current code satisfies the rule; verified by existing test or file inspection.
- Partial — some aspects satisfied, gaps remain (gaps listed in
Action). - Missing — not implemented.
- Conflict — TZ text and Angular reference site (or current React impl) disagree. Listed in Conflicts register below, blocks plan start until arbitrated.
- TBD — needs more TZ reading + reference-site inspection to classify. Populated at plan kickoff.
Plan index
Six themed plans, merged in dependency order. Each plan consumes a subset of rule IDs from this spec.
| Plan | Name | Rule sources | Depends on | Merge order |
|---|---|---|---|---|
| P1 | URLs, breadcrumbs, page names, cross-section nav | 4.1.2, 4.1.3, 4.1.4, 4.1.8 | — | 1 |
| P2 | Start pages + first-entry + popular sections | 4.1.1, 4.1.5, 4.1.6, 4.1.7 | P1 | 2 |
| P3 | Filter + validation + search history + search execution + cancel | 4.1.9 (+ .1–.5), 4.1.10, 4.1.11, 4.1.12 | P1 | 3 |
| P4 | Results lists (collapsed + expanded) | 4.1.13, 4.1.14 | P3 | 4 |
| P5 | Flight cards + timeline + aircraft icons + "Уточняется" | 4.1.15, 4.1.16, 4.1.17, 4.1.22, 4.1.23 | P4 | 5 |
| P6 | SEO, errors, cache, Карта полетов | 4.1.18, 4.1.19, 4.1.20, 4.1.21, 4.1.24 | P1 (map routing) | 6 |
Each plan is produced by invoking the superpowers:writing-plans skill with its rule IDs. Each plan merges independently off main (rebase + fast-forward). After each merge, this spec's status column is updated (Status → Done + <commit-sha>).
Coverage summary
Updated after each plan merges. Plan task: after every merge, append a row to the log below and update per-plan counts.
| Metric | Count |
|---|---|
| Total rules extracted | 853 (4.1.1: 27, 4.1.2: 42, 4.1.3: 22, 4.1.4: 26, 4.1.5: 30, 4.1.6: 14, 4.1.7: 16, 4.1.8: 19, 4.1.9: 58, 4.1.9.1: 12, 4.1.9.2: 11, 4.1.9.3: 13, 4.1.9.4: 9, 4.1.9.5: 14, 4.1.10: 9, 4.1.10.1: 8, 4.1.11: 10, 4.1.11.1: 8, 4.1.12: 7, 4.1.13: 81 (opening 18 + §4.1.13.1 ×11 + §4.1.13.2 ×7 + §4.1.13.3 ×27 + §4.1.13.4 ×18), 4.1.14: 105 (opening 24 + §4.1.14.1 ×11 + §4.1.14.2 ×9 + §4.1.14.3 ×30 + §4.1.14.4 ×31), 4.1.15: 112 (§4.1.15.1 ×10 + §4.1.15.2 ×12 + §4.1.15.3 ×7 + §4.1.15.4 ×36 + §4.1.15.5 ×18 + §4.1.15.6 ×10 + §4.1.15.7 ×5 + §4.1.15.8 ×2 + §4.1.15.9 ×3 + §4.1.15.10 ×6 + §4.1.15.11 ×3), 4.1.16: 76 (§4.1.16.1 ×9 + §4.1.16.2 ×12 + §4.1.16.3 ×10 + §4.1.16.4 ×11 + §4.1.16.5 ×8 + §4.1.16.6 ×13 + §4.1.16.7 ×5 + §4.1.16.8 ×8), 4.1.17: 8, 4.1.18: 3, 4.1.19: 6, 4.1.20: 4, 4.1.21: 5, 4.1.22: 11, 4.1.23: 6, 4.1.24: 7 skeleton) |
| Done | 317 (P1: 104 across §4.1.2/3/4/8; P2 adds 48 across §4.1.1/5/6/7; P3 adds 133 across §4.1.9/9.x/10/10.1/11/11.1/12 + §4.1.8-R4/R5; P4 adds 32: §4.1.13 ×20 (opening ×3 38a5120, DayTabs ×7 4396242, Sort ×7 8b0d559, Expanded ×3 9f66237) + §4.1.14 ×12 (WeekTabs ×7 6f67c06, Expanded Buy/Status/Details ×5 4290c81)) |
| Implemented | ~200 (pre-P1/P2/P3: ~49 incl. §4.1.14.4-R19 3ae59da; P4 adds ~142: §4.1.13 opening ×15 f6def71, §4.1.13.1 ×4, §4.1.13.3 ×24 3b5ae9a, §4.1.13.4 ×13 9f66237, §4.1.14 opening ×24 f6def71/6f67c06, §4.1.14.1 ×4, §4.1.14.2 ×9 6f67c06, §4.1.14.3 ×27 6f67c06, §4.1.14.4 ×23 4290c81; P5 Task 4 adds 7: §4.1.17-R1–R7 verified/fixed + dayChange.ts helper + 27 unit tests) |
| Partial | 6 (4.1.2-R4 flight-number padding; 4.1.4-R12/R13 city-pair deferred (C3); P4 adds 4: 4.1.13.3-R9 multi-seg status-switching; 4.1.13.4-R6 check-in counter; 4.1.14.4-R5 segment dep airport-as-link; 4.1.14.4-R7 segment arr airport-as-link) |
| Missing | 0 |
| Conflict | 8 (C1–C8 in Conflicts register; C1–C4 resolved, C5 pending P6, C6–C8 resolved; 1 rule cell still Conflict: 4.1.1-R22 = C5 pending P6; C8 resolved 6f67c06 (week-tabs active range +210→+330 days)) |
| Out-of-scope (backend) | 13 (§4.1.5-R1..R11, R13, R28 — backend aggregation service rules; tracked separately) |
| TBD | ~313 (P4 deferred 7 to P5 backlog: 4.1.13.3-R7, R14 (airport-as-link); 4.1.13.4-R16 (online check-in); 4.1.14.3-R7, R14, R29 (airport-as-link); 4.1.14.4-R18 (airport-as-link in transfer badge); pre-existing non-P4 TBDs: §4.1.1: R15/R16/R25; §4.1.5-R12; §4.1.6-R14; §4.1.7-R16; §4.1.17-R8 (mobile tooltip suppression, CSS TBD); §4.1.18–4.1.24 skeleton; §4.1.9-R53-R57 P4-tagged; P5 spec adds ~181 new TBD: §4.1.15-R3–R112 + §4.1.16-R1–R76 (minus R10/R13 Implemented) + §4.1.22-R1–R11 + §4.1.23-R1–R6) |
| Check | 317 Done + 193 Implemented + 6 Partial + 1 Conflict + 13 Out-of-scope + ~320 TBD ≈ 850 |
| Note (§4.1.22 clarification) | §4.1.22 in TZ is the operating carrier icon algorithm (not aircraft-type icon). Rule descriptions updated to reflect this. |
| Note (§4.1.23 clarification) | TZ specifies orange styling for «Уточняется» (contradicts prior assumption of «same as regular text»). Corrected in 4.1.23-R5. |
Merge log
| Date | Plan | Scope | Commit range | Notes |
|---|---|---|---|---|
| 2026-04-21 | P1 | URLs / breadcrumbs / page names / cross-section nav | 8160286..e935596 |
~103 rules marked Done across §4.1.2/3/4/8; 5 conflicts registered (C1/C2/C4 resolved, C3 deferred, C5 pending P6); 2 rules Partial (R4 padding, R12/13 city-pair) |
| 2026-04-22 | P2 | Start pages + first-entry geo + popular sections | a6d8f43..b27ee2a |
48 rules marked Done across §4.1.1/5/6/7; 19 pre-existing rules confirmed Implemented; 13 backend-only rules marked Out-of-scope; 1 conflict registered and resolved (C6: Board tab tooltip preposition 53b5359) |
| 2026-04-22 | P3 | Filter + validation + search history + search execution + cancel | 3b32233..a5c64a2 |
133 rules marked Done across §4.1.9/9.1/9.2/9.3/9.4/9.5/10/10.1/11/11.1/12 + §4.1.8-R4/R5; ~17 pre-existing rules confirmed Implemented in §4.1.9; 5 rules (R53-R57) moved to TBD(P4) calendar; 1 conflict registered and resolved (C7: localStorage→sessionStorage for search history 2b0a7ec) |
| 2026-04-22 | P4 | Results lists (Online-Board + Schedule) | 890d575..f6def71 |
32 rules marked Done + ~142 confirmed Implemented across §4.1.13/14; 4 Partial; 7 deferred TBD(P5) (airport-as-link, online check-in, check-in counter); 1 conflict registered and resolved (C8: week-tabs active range +210→+330 days 6f67c06) |
Conflicts register
Arbitrated case-by-case (Q2 = C). Each conflict blocks its owning plan's kickoff until Resolution is filled. When a conflict is resolved, convert the relevant rule row(s) to non-conflict status and cross-reference the Resolution back to the rule ID.
| # | Rule IDs | TZ says | Angular reference says | Current React says | Diagnostic | Resolution |
|---|---|---|---|---|---|---|
| C1 | 4.1.3-R21 | Flight Map title = "Карта полетов" (short form) |
Angular reference: "Карта полетов авиакомпании Аэрофлот" (long form with carrier) |
React impl had no explicit title | P1 verification (bcaf3ab) discovered Angular uses long form not in TZ |
Adopt TZ short form "Карта полетов". Commit: bcaf3ab. |
| C2 | 4.1.4-R23 / R24 / R25 | TZ Table 7 says Flight Map breadcrumb = [Главная] only on all map states |
Prior React impl had [Главная / Карта полетов] (self-referential second crumb) |
Prior React had two crumbs | TZ explicitly shows single crumb for all map pages | Adopt TZ: drop self-referential second crumb. Commit: 2fe5364. |
| C3 | 4.1.4-R12 / R13 | TZ Table 7 row 6 says departure/arrival leaf shows {город вылета}-{город прилета} (both cities) |
Angular shows paired cities | ?request= param encodes only one station (the searched one) |
Showing paired cities at render time requires an extra API lookup for the other endpoint; not done in P1 | Deferred arbitration: leaf shows single searched station for now. Full city-pair deferred to P2 when flight-result data is in scope. Commit: 1821f7f. Linked: 4.1.4-R12 / R13 marked Partial. |
| C4 | 4.1.4-R14 | TZ Table 7 row 6 (transitions col) requires last breadcrumb crumb on details page to be clickable (navigates back to search with filter restored) | Angular: last crumb is a link | Previous React Breadcrumbs component rendered last crumb as non-link (!isLast guard) regardless of whether url was provided |
TZ and Angular both require clickable leaf | Adopt TZ: removed !isLast guard — last crumb with url now rendered as <a> and clickable. Commit: 1821f7f. Note: aria-current="page" is still set on the last crumb as required by R2. |
| C5 | 4.1.1-R22 | TZ writes "ДД.ММ.ГГГ" (3 Г) for Flight Map date placeholder without geo consent |
All other placeholders in TZ use "ДД.ММ.ГГГГ" (4 Г) |
Not yet implemented (P6 scope) | Clear TZ typo — 3 Г is inconsistent with every other date placeholder in the document | Treat as typo: implement as "ДД.ММ.ГГГГ" (4 Г). Commit: pending (P6 start-page scope). Conflict to be closed when P6 implements Flight Map start-page. |
| C6 | Tab-tooltip cross-cutting (§4.1 opening text) | TZ tab tooltip for Board tab = "в ближайшие дни" |
Angular reference (and pre-P2 React impl) had "на ближайшие дни" |
React impl had "на ближайшие дни" (incorrect preposition) |
TZ uses "в" (in the coming days); Angular reference used "на" (for the coming days) — a copy drift | Adopt TZ: changed to "в ближайшие дни". Commit: 53b5359. Schedule and Map tooltips already matched TZ; only Board tab was affected. |
| C7 | 4.1.9.5-R3 (search history storage scope) | TZ §4.1.9.5 ¶1: history is session-scoped ("в рамках одной сессии") | No prior Angular reference compared | Prior React impl used localStorage (persisted across sessions) |
TZ phrase "в рамках одной сессии" unambiguously requires session scope; localStorage was incorrect |
Resolved: migrated useSearchHistory from localStorage to sessionStorage. Commit: 2b0a7ec. Rule 4.1.9.5-R3 now Done. |
| C8 | 4.1.14.1-R3 (Schedule week-tabs active range: +210 days → +330 days) |
TZ §4.1.14.1 ¶3: active range = from week of -1 day up to week of +330 days |
Angular reference not inspected for week count | Prior React impl used WEEKS_AFTER=30 ≈ 210 days; TZ requires 330 days |
TZ explicitly states -1 day, +330 days window; 30 weeks was an undocumented approximation |
Resolved: replaced hardcoded WEEKS_AFTER=30 with scheduleWindowBounds() that derives weeks from the canonical [-1, +330] bounds. Commit: 6f67c06. Rule 4.1.14.1-R3 now Done. |
4.1.1 — Правила поведения Системы при первоначальном входе
First-entry behavior when user enters Online-Board / Schedule / Flight Map.
Defines what the filter shows on the very first session visit: with geolocation consent, auto-fill Город вылета with the user's city; without consent, show the plain start page. Also defines placeholder values and default date/time attributes per mode. Mode-switch within session preserves user input.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.1-R1 | With geo consent, auto-detect user city, open Online-Board in "Маршрут" mode with Город вылета = detected city |
4.1.1 ¶1 | all | src/features/online-board/components/OnlineBoardStartPage.tsx |
Done b023cb9 |
Geo hook wires detected city into OnlineBoardStartPage filter on mount; verified by unit tests in b023cb9. |
P2 |
| 4.1.1-R2 | Город прилета placeholder = "Все направления" on first-entry Online-Board route-mode |
4.1.1 ¶1 | all | OnlineBoardFilter.tsx |
Done b023cb9 |
Placeholder confirmed present in OnlineBoardFilter; geo path leaves arrival empty → "Все направления" displays. | P2 |
| 4.1.1-R3 | Дата рейса default = today |
4.1.1 ¶1 | all | OnlineBoardFilter.tsx |
Done b023cb9 |
Default date set to today in geo-init path; verified by b023cb9 tests. |
P2 |
| 4.1.1-R4 | Время рейса default = 00:00-24:00 on desktop/tablet |
4.1.1 ¶1 | desktop, tablet | OnlineBoardFilter.tsx |
Done 9aed10c |
useIsMobileViewport hook added; desktop/tablet path sets full-day range. Wired in b023cb9. |
P2 |
| 4.1.1-R5 | Время рейса default = -1/+3ч from user's current time on mobile phone |
4.1.1 ¶1 | mobile | OnlineBoardFilter.tsx |
Done 9aed10c |
Mobile path computes −1h/+3h from current time via useIsMobileViewport; wired in b023cb9. |
P2 |
| 4.1.1-R6 | Do not auto-execute search after first-entry defaulting | 4.1.1 ¶1 | all | — | Done b023cb9 |
No search dispatch in geo-init path; OnlineBoardStartPage only sets filter values, does not submit. | P2 |
| 4.1.1-R7 | In "Номер рейса" mode on first-entry: Номер рейса placeholder, Дата рейса = today |
4.1.1 ¶2 | all | OnlineBoardFilter.tsx (mode switch) |
Implemented | Pre-existing mode-switch default; flight-number mode always starts with today and empty flight number field (pre-P1). | P2 |
| 4.1.1-R8 | Schedule on first-entry: Город вылета = detected city, Город прилета placeholder = "Укажите город" |
4.1.1 ¶3 | all | ScheduleFilter.tsx |
Done c3c1f83 |
Geo hook wired into ScheduleStartPage; city auto-fill + placeholder verified by c3c1f83 tests. |
P2 |
| 4.1.1-R9 | Schedule Показать расписание на default = "текущая неделя" (range this week, within -1/+330 day validation) |
4.1.1 ¶3 | all | ScheduleFilter.tsx |
Implemented | Current-week default existed pre-P1; Schedule filter initialises to current week on every first-entry. | P2 |
| 4.1.1-R10 | Schedule Время вылета default = 00:00-24:00 on all viewports (mobile matches desktop) |
4.1.1 ¶3 | all | ScheduleFilter.tsx |
Done c3c1f83 |
Schedule time default hard-coded to 00:00–24:00 regardless of viewport; verified in c3c1f83. |
P2 |
| 4.1.1-R11 | Schedule Только прямые рейсы unchecked on first-entry |
4.1.1 ¶3 | all | ScheduleFilter.tsx |
Implemented | Toggle initialised to false pre-P1; c3c1f83 verification confirms unchanged. |
P2 |
| 4.1.1-R12 | Schedule Показать обратные рейсы unchecked on first-entry |
4.1.1 ¶3 | all | ScheduleFilter.tsx |
Implemented | Toggle initialised to false pre-P1; c3c1f83 verification confirms unchanged. |
P2 |
| 4.1.1-R13 | Flight Map first-entry: Город вылета = nearest airport (auto-detected), Город прилета placeholder "Куда" |
4.1.1 ¶4 | all | FlightsMapFilter.tsx |
Done bc0b10b |
useGeoCityDefault shared hook preserves nearest-airport auto-fill behavior; migration verified in bc0b10b. |
P2 |
| 4.1.1-R14 | Flight Map first-entry toggles: Внутренние рейсы=ON, Международные регулярные рейсы=ON, Показать рейсы с пересадкой=OFF |
4.1.1 ¶4 | all | FlightsMapFilter.tsx |
Done fbb84fc |
Toggle defaults aligned to TZ with geo-consent; verified by fbb84fc tests. |
P2 |
| 4.1.1-R15 | Flight Map first-entry Дата рейса = today; map shows "паутинка" (spider) from departure city for today |
4.1.1 ¶4 | all | MapCanvas.tsx |
TBD | P6 scope — spider rendering not addressed in P2. | P6 |
| 4.1.1-R16 | Map line rules: Direct lines if direct+connecting exist; connecting lines if only connecting; dots (full route network) if neither | 4.1.1 ¶4 | all | MapCanvas.tsx |
TBD | P6 scope — map rendering modes not addressed in P2. | P6 |
| 4.1.1-R17 | If geo-detection fails, fall back to Online-Board start page (§4.1.6) — no auto-fill | 4.1.1 ¶5 | all | — | Done b023cb9 |
useGeoCityDefault hook silently catches geo errors and leaves filter empty → start page shown with placeholders. |
P2 |
| 4.1.1-R18 | Without geo consent: Online-Board "Маршрут" expanded; Город вылета + Город прилета placeholders "Укажите город"; Дата рейса placeholder "ДД.ММ.ГГГГ"; Время рейса 00:00-24:00 |
4.1.1 ¶6 | all | OnlineBoardStartPage.tsx |
Implemented | Placeholder state pre-existing; b023cb9 verifies no-geo path leaves all placeholders intact. |
P2 |
| 4.1.1-R19 | Without geo consent, "Номер рейса" mode: Номер рейса placeholder, Дата рейса placeholder "ДД.ММ.ГГГГ" |
4.1.1 ¶7 | all | OnlineBoardFilter.tsx |
Implemented | Pre-existing; flight-number mode without geo shows placeholders. | P2 |
| 4.1.1-R20 | Without geo consent, Schedule start page per §4.1.7; all city/date placeholders; toggles unchecked | 4.1.1 ¶8 | all | ScheduleStartPage.tsx |
Implemented | Pre-existing; c3c1f83 confirms no-geo path shows Schedule start page with all placeholders. |
P2 |
| 4.1.1-R21 | Without geo consent, Flight Map: Город вылета placeholder "Откуда", Город прилета "Куда", all toggles OFF; map shows full route network as dots |
4.1.1 ¶9 | all | FlightsMapFilter.tsx, MapCanvas.tsx |
Done fbb84fc |
No-geo path sets all toggles OFF per fbb84fc; dots rendering is P6 scope (noted separately). | P2 |
| 4.1.1-R22 | Without geo consent, Flight Map Дата рейса placeholder "ДД.ММ.ГГГ" (sic — TZ typo, 3 Г; treat as ДД.ММ.ГГГГ) |
4.1.1 ¶9 | all | FlightsMapFilter.tsx |
Conflict | TZ has obvious typo. Flag; treat as ДД.ММ.ГГГГ. Implementation deferred to P6. |
P6 |
| 4.1.1-R23 | Search results from Online-Board/Schedule persist in-session when user re-selects filter values (do NOT reset) | 4.1.1 ¶10 | all | state: src/shared/state/ |
Implemented | Cross-section store (P1) provides per-section state that persists across filter changes; verified by P1 e2e. | P2 |
| 4.1.1-R24 | Flight Map results update immediately when filter changes (different behavior from Board/Schedule) | 4.1.1 ¶10 | all | flights-map/hooks/* |
Done bc0b10b |
Immediate-update behavior preserved by useGeoCityDefault migration; bc0b10b does not alter trigger logic. |
P6 |
| 4.1.1-R25 | Clearing Дата рейса on Flight Map → map shows range -1 day, +6 months |
4.1.1 ¶11 | all | flights-map/* |
TBD | Not verified in P2. Verify at P6 kickoff. | P6 |
| 4.1.1-R26 | Flight Map filter is independent of Online-Board / Schedule filters | 4.1.1 ¶12 | all | state isolation: src/shared/state/ |
Implemented | P1 cross-section store isolates Flight Map state; verified by 4.1.8-R3 / P1 e2e. | P6 |
| 4.1.1-R27 | Returning to Flight Map in same session restores previously entered filter + result | 4.1.1 ¶13 | all | state | Implemented | P1 cross-section store stores Flight Map state independently; return restores last filter. | P6 |
Rules in this subsection: 27 (R22 is a flagged conflict: TZ typo).
4.1.2 — Правила формирования URL-ссылок
URL formation for Online-Board, Schedule, Flight Map.
URLs encode language, area (onlineboard/schedule/flights-map), mode (route / flight-number / departure / arrival), and search parameters. TZ Table 5 enumerates every URL pattern with examples. Invalid dates outside the -1/+14 (board), -1/+330 (schedule), -1/+6mo (map) windows redirect to the respective start page. Invalid directories → 404.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.2-R1 | URL pattern (Web and Mobile identical): https://flights.aeroflot.ru/{lang}/{area}[/{mode}/{params}] |
4.1.2 Table 5 | all | src/routes/[lang]/* |
Done 8160286 |
Route file-layout matches Table 5; verified by e2e e935596. |
P1 |
| 4.1.2-R2 | {lang} = locale+language pair (ru-ru, en-us, …). All site languages must be supported |
4.1.2 ¶1 | all | src/i18n/ |
Done 8160286 |
All 9 languages exposed as route params; i18n keys verified. | P1 |
| 4.1.2-R3 | Online-Board title page: /{lang}/onlineboard |
4.1.2 Table 5 row 1 | all | src/routes/[lang]/onlineboard/page.tsx |
Done 8160286 |
Route exists; confirmed by e2e. | P1 |
| 4.1.2-R4 | Online-Board flight-number search: /{lang}/onlineboard/flight/{SUNNNN}-{YYYYMMDD}; if user entered 38 → pad to SU0038, 383 → SU0383 (4-digit number, 3-char carrier code) |
4.1.2 Table 5 row 2 | all | src/routes/[lang]/onlineboard/flight/[params]/* |
Partial f5304e2 |
Guard enforced; 4-digit padding in buildFlightUrlParams not yet unit-tested — add test at P3 kickoff. |
P1 |
| 4.1.2-R5 | Online-Board route search: /{lang}/onlineboard/route/{fromCity}-{toCity}-{YYYYMMDD} |
4.1.2 Table 5 row 3 | all | src/routes/[lang]/onlineboard/route/[params]/* |
Done f2c52ca |
Route guard enforced; URL builder verified by e2e e935596. |
P1 |
| 4.1.2-R6 | Online-Board departure-only search: /{lang}/onlineboard/departure/{fromCity}-{YYYYMMDD} |
4.1.2 Table 5 | all | src/routes/[lang]/onlineboard/departure/[params]/* |
Done 7d6b23b |
Route guard enforced; URL builder verified. | P1 |
| 4.1.2-R7 | Online-Board arrival-only search: /{lang}/onlineboard/arrival/{toCity}-{YYYYMMDD} |
4.1.2 Table 5 | all | src/routes/[lang]/onlineboard/arrival/[params]/* |
Done d633b2d |
Route guard enforced; URL builder verified. | P1 |
| 4.1.2-R8 | Schedule URL patterns mirror Online-Board with /schedule/ prefix; add range date for schedule |
4.1.2 Table 5 | all | src/routes/[lang]/schedule/* |
Done 12807cf |
Schedule codec extended for all URL patterns; guard ead18fc enforces window. |
P1 |
| 4.1.2-R9 | Flight-Map URL pattern (route, validation) | 4.1.2 Table 5 (§4.1.24 refers) | all | src/routes/[lang]/flights-map/* |
Done bcaf3ab |
Map route verified; URL stays constant per R39–R40. | P1 |
| 4.1.2-R10 | Unknown directory → 404 page (§4.1.21) | 4.1.2 ¶2 | all | src/routes/error/[code]/* |
Done e935596 |
Verified by Playwright e2e guard tests. | P1 |
| 4.1.2-R11 | Out-of-range date → redirect to the respective start page (not 404) | 4.1.2 ¶3–4 | all | fbd4438 + mode guards |
Done fbd4438 |
Board guards f5304e2..57d21f6, Schedule guard ead18fc; all redirect to start page. |
P1 |
| 4.1.2-R12 | Date window constants: Online-Board [-1, +14], Schedule [-1, +330], Flight Map [-1, +6 months] |
4.1.2 ¶3–4 | all | src/shared/dateWindow.ts |
Done 750a328 |
Centralized in dateWindow module; 4f84048 removes scattered literals. |
P1 |
| 4.1.2-R13 | Online-Board route search with time filter: /{lang}/onlineboard/route/{fromCity}-{toCity}-{YYYYMMDD}-{HHMMHHmm} — time period {timeFrom}{timeTo} appended to date, e.g. 06002200 |
4.1.2 Table 5 row 3 | all | src/routes/[lang]/onlineboard/route/[params]/* |
Done f2c52ca |
Optional time suffix parsed and preserved in codec; e2e verified. | P1 |
| 4.1.2-R14 | Online-Board departure-only search with time filter: /{lang}/onlineboard/departure/{fromCity}-{YYYYMMDD}-{HHMMHHmm} (optional time suffix) |
4.1.2 Table 5 row 4 | all | departure guard | Done 7d6b23b |
Optional time suffix handled. | P1 |
| 4.1.2-R15 | Online-Board arrival-only search with time filter: /{lang}/onlineboard/arrival/{toCity}-{YYYYMMDD}-{HHMMHHmm} (optional time suffix) |
4.1.2 Table 5 row 5 | all | arrival guard | Done d633b2d |
Optional time suffix handled. | P1 |
| 4.1.2-R16 | Online-Board details card — arrival-mode ?request= param: ?request=onlineboard-arrival-{city}-{flightNumber}-{YYYYMMDD}[-{HHMMHHmm}] |
4.1.2 Table 5 row 6 | all | src/shared/detailsRequestParam.ts |
Done 531ace6 |
Codec builds and parses all four ?request= modes including arrival. |
P1 |
| 4.1.2-R17 | Online-Board details card — departure-mode ?request= param: ?request=onlineboard-departure-{city}-{flightNumber}-{YYYYMMDD}[-{HHMMHHmm}] |
4.1.2 Table 5 row 6 | all | src/shared/detailsRequestParam.ts |
Done 531ace6 |
Departure mode covered by codec. | P1 |
| 4.1.2-R18 | Online-Board details card — route-mode ?request= param: ?request=onlineboard-route-{dep}-{arr}-{flightNumber}-{YYYYMMDD}[-{HHMMHHmm}] |
4.1.2 Table 5 row 6 | all | src/shared/detailsRequestParam.ts |
Done 531ace6 |
Route mode covered by codec. | P1 |
| 4.1.2-R19 | Online-Board details card — flight-number-mode ?request= param: ?request=onlineboard-flight-{flightNumber}-{YYYYMMDD} (no time suffix for flight-number mode) |
4.1.2 Table 5 row 6 | all | src/shared/detailsRequestParam.ts |
Done 531ace6 |
Flight-number mode omits time suffix; verified in codec unit tests. | P1 |
| 4.1.2-R20 | Online-Board details base URL (same for all four ?request= forms): /{lang}/onlineboard/{flightNumber}-{YYYYMMDD} |
4.1.2 Table 5 row 6 | all | 8b22f06 (wired into page) |
Done 8b22f06 |
Base path uses padded flight number; codec wired into OnlineBoardDetailsPage. |
P1 |
| 4.1.2-R21 | Online-Board "Refresh direct link" URL is identical in shape to the details card URL (row 6); no difference in path or query | 4.1.2 Table 5 row 7 | all | details page routing | Done 8b22f06 |
Refresh reloads same URL — codec decodes on mount; no mutation. | P1 |
| 4.1.2-R22 | Online-Board "Share / copy link" URL: /{lang}/onlineboard/flight/{flightNumber}-{YYYYMMDD} — no ?request= param; always flight mode regardless of original search mode |
4.1.2 Table 5 row 8 | all | — | Done 531ace6 |
Share URL uses clean /flight/ path with no ?request=; codec does not add it for share links. |
P1 |
| 4.1.2-R23 | Schedule title page URL: /{lang}/schedule |
4.1.2 Table 5 row 9 | all | src/routes/[lang]/schedule/page.tsx |
Done ead18fc |
Route exists; guard verified by e2e. | P1 |
| 4.1.2-R24 | Schedule route search — one-way, all connections, no time: /{lang}/schedule/route/{dep}-{arr}-{dateFrom}-{dateTo} (date range, both dates YYYYMMDD) |
4.1.2 Table 5 row 10 | all | src/shared/detailsRequestParam.ts |
Done 12807cf |
Date-range URL format implemented and parsed by schedule codec extension. | P1 |
| 4.1.2-R25 | Schedule route search — one-way, all connections, with time: /{lang}/schedule/route/{dep}-{arr}-{dateFrom}-{dateTo}-{HHMMHHmm} |
4.1.2 Table 5 row 10 | all | schedule codec | Done 12807cf |
Time suffix appended after dateTo; verified by codec unit tests. | P1 |
| 4.1.2-R26 | Schedule route search — round-trip, no time: /{lang}/schedule/route/{dep}-{arr}-{dateFrom}-{dateTo}/{arr}-{dep}-{returnDateFrom}-{returnDateTo} (two slash-separated segments) |
4.1.2 Table 5 row 10 | all | schedule codec | Done 12807cf |
Slash-delimited second segment for return leg implemented. | P1 |
| 4.1.2-R27 | Schedule route search — round-trip, with time: both segments each append -{HHMMHHmm} after their dateTo |
4.1.2 Table 5 row 10 | all | schedule codec | Done 12807cf |
Both segments carry independent time filters; verified in codec tests. | P1 |
| 4.1.2-R28 | Schedule route search — one-way, direct-only (С0): append -С0 suffix after the date or time token, e.g. …-{dateTo}-С0 or …-{HHMMHHmm}-С0 |
4.1.2 Table 5 row 10 | all | schedule codec | Done 12807cf |
-С0 suffix position verified in codec. |
P1 |
| 4.1.2-R29 | Schedule route search — round-trip, direct-only: each slash segment ends with -С0 |
4.1.2 Table 5 row 10 | all | schedule codec | Done 12807cf |
Each segment carries -С0; round-trip case verified. |
P1 |
| 4.1.2-R30 | Schedule details card URL — direct/multi-segment, one-way, no time: /{lang}/schedule/{flightNumber}-{YYYYMMDD}?request=schedule-route-{dep}-{arr}-{dateFrom}-{dateTo} |
4.1.2 Table 5 row 11 | all | 5728861 |
Done 5728861 |
Schedule search → details links emit ?request=; verified by breadcrumb tests. |
P1 |
| 4.1.2-R31 | Schedule details card URL — direct/multi-segment, one-way, with time: ?request=schedule-route-{dep}-{arr}-{dateFrom}-{dateTo}-{HHMMHHmm} |
4.1.2 Table 5 row 11 | all | schedule codec | Done 12807cf |
Time suffix included in ?request= when filter has time range. |
P1 |
| 4.1.2-R32 | Schedule details card URL — connecting flight, one-way: path uses slash-delimited flight numbers /{fn0}-{date}/{fn1}-{date}[/{fn2}-{date}] (max 2 connections = up to 3 segments); ?request= same as direct |
4.1.2 Table 5 row 11 | all | schedule codec | Done 12807cf |
Multi-segment path with up to 3 flight-number-date pairs implemented. | P1 |
| 4.1.2-R33 | Schedule details card URL — round-trip, no time: ?request= encodes both outbound and return legs: ?request=schedule-route-{dep}-{arr}-{df}-{dt}-{arr}-{dep}-{rdf}-{rdt} |
4.1.2 Table 5 row 11 | all | schedule codec | Done 12807cf |
Concatenated return-leg parameters in ?request= implemented. |
P1 |
| 4.1.2-R34 | Schedule details card URL — round-trip with connections filter (С0): ?request= embeds -С0 after each date-range block |
4.1.2 Table 5 row 11 | all | schedule codec | Done 12807cf |
-С0 positions inside ?request= for round-trip + direct filter verified. |
P1 |
| 4.1.2-R35 | Schedule "Refresh direct link" URL identical to details card URL (row 11 in Table 5; same as Online-Board analogy row 7) | 4.1.2 Table 5 row 12 | all | schedule details page | Done 266a6f9 |
Refresh reloads same URL; breadcrumb tests confirm no mutation. | P1 |
| 4.1.2-R36 | Schedule "Share / copy link" URL — direct/multi-segment: /{lang}/schedule/{flightNumber}-{YYYYMMDD} (no ?request=) |
4.1.2 Table 5 row 13 | all | schedule codec | Done 12807cf |
Share URL is clean path without ?request=. |
P1 |
| 4.1.2-R37 | Schedule "Share / copy link" URL — connecting: /{lang}/schedule/{fn0}-{date}/{fn1}-{date}[/{fn2}-{date}] slash-joined (no ?request=) |
4.1.2 Table 5 row 13 | all | schedule codec | Done 12807cf |
Connecting share URL uses slash-joined path without ?request=. |
P1 |
| 4.1.2-R38 | Flight Map title page URL: /{lang}/flights-map |
4.1.2 Table 5 (Map row 1) | all | src/routes/[lang]/flights-map/page.tsx |
Done bcaf3ab |
Route exists; title verified. | P1 |
| 4.1.2-R39 | Flight Map departure search URL: /{lang}/flights-map — same URL regardless of departure-city filter value (search state NOT encoded in URL) |
4.1.2 Table 5 (Map row 2) | all | flights-map/* |
Done bcaf3ab |
URL stays constant under filter changes; map state is client-side only. | P1 |
| 4.1.2-R40 | Flight Map route search URL: /{lang}/flights-map — same URL for all search states |
4.1.2 Table 5 (Map row 3) | all | flights-map/* |
Done bcaf3ab |
URL stays constant when both cities filled. | P1 |
| 4.1.2-R41 | Flight Map arrival-only search is not implemented ("Не выполняется") — no arrival-mode URL for flights-map | 4.1.2 Table 5 (Map row 4) | all | — | Done 2fe5364 |
No arrival-mode route exists; map breadcrumb stays [Главная] only. |
P1 |
| 4.1.2-R42 | Mobile URL rules are identical to web URL rules (no mobile-specific URL variants) | 4.1.2 ¶1 | mobile | — | Done 8160286 |
No mobile-specific routing divergence; verified by e2e e935596. |
P1 |
4.1.3 — Правила наименования страниц
Page-title rules (document <title> + visible H1).
Each page in the section gets a TZ-prescribed title format driven by context (area, mode, filter values, language). Translatable across all 9 site languages.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.3-R1 | Online-Board start page title per TZ Table (populate at P1 kickoff) | 4.1.3 | all | src/ui/seo/* |
Done f03562e |
Populated; all Online-Board title rows covered by f03562e. |
P1 |
| 4.1.3-R2 | Schedule start page title per TZ | 4.1.3 | all | src/features/schedule/* |
Done df4ac19 |
Schedule titles implemented. | P1 |
| 4.1.3-R3 | Flight-Map start page title per TZ | 4.1.3 | all | src/features/flights-map/* |
Done bcaf3ab |
Flight Map title verified. | P1 |
| 4.1.3-R4 | Search-result page titles per mode (route / flight-number / departure / arrival) | 4.1.3 | all | src/ui/seo/* |
Done f03562e |
All four Online-Board search-result title formats implemented. | P1 |
| 4.1.3-R5 | Flight-details page title per TZ (direct / multi-segment / connecting) | 4.1.3 | all | df4ac19, f03562e |
Done df4ac19 |
Direct vs connecting branching implemented for both Board and Schedule. | P1 |
| 4.1.3-R6 | All titles translated for each of 9 languages | 4.1.3 | all | src/i18n/* |
Done f03562e |
i18n keys added for all new title formats; 9-language coverage included. | P1 |
| 4.1.3-R7 | Online-Board start page title: Онлайн-Табло (no dynamic parts) |
4.1.3 Table 6 row 1 | all | src/ui/seo/* |
Done f03562e |
Verified rendered title matches exactly. | P1 |
| 4.1.3-R8 | Online-Board flight-number search title: Рейс: {номер рейса}, {дата} — date shown as сегодня / завтра / ДД.ММ.ГГГГ depending on flight date relative to today |
4.1.3 Table 6 row 2 | all | src/ui/seo/* |
Done f03562e |
Date-relative label logic (today/tomorrow/formatted) implemented. | P1 |
| 4.1.3-R9 | Online-Board route search title: Маршрут: {город вылета}-{города прилета}, {дата} — city names in full display form; date formatted same as R8 |
4.1.3 Table 6 row 3 | all | src/ui/seo/* |
Done f03562e |
City names (not IATA codes) used; comma-separated date. | P1 |
| 4.1.3-R10 | Online-Board departure-only search title: Вылет: {город вылета}, {дата} |
4.1.3 Table 6 row 4 | all | src/ui/seo/* |
Done f03562e |
Departure-only title shows only departure city + date. | P1 |
| 4.1.3-R11 | Online-Board arrival-only search title: Прилет: {город прилета}, {дата} |
4.1.3 Table 6 row 5 | all | src/ui/seo/* |
Done f03562e |
Arrival-only title shows only arrival city + date. | P1 |
| 4.1.3-R12 | Online-Board flight details card title: Информация о рейсе: {номер рейса}, {город вылета}-{город прилета} |
4.1.3 Table 6 row 6 | all | src/ui/seo/* |
Done f03562e |
Format with comma after flight number implemented. | P1 |
| 4.1.3-R13 | Online-Board details via "Refresh direct link" title: same as details card — Информация о рейсе: {номер рейса}, {город вылета}-{город прилета} |
4.1.3 Table 6 row 7 | all | SSR via details page | Done f03562e |
SSR hydrates city names; title preserved on refresh. | P1 |
| 4.1.3-R14 | Online-Board share link title: same as details card — Информация о рейсе: {номер рейса}, {город вылета}-{город прилета} |
4.1.3 Table 6 row 8 | all | share URL rendering | Done f03562e |
Share URL renders same title as details card. | P1 |
| 4.1.3-R15 | Schedule start page title: Расписание (no dynamic parts) |
4.1.3 Table 6 row 9 | all | src/features/schedule/* |
Done df4ac19 |
H1/title verified as static Расписание. |
P1 |
| 4.1.3-R16 | Schedule route search title: Расписание по маршруту: {город вылета}-{города прилета} — full city names, no date shown in title |
4.1.3 Table 6 row 10 | all | src/features/schedule/* |
Done df4ac19 |
No date in schedule search title; full city names confirmed. | P1 |
| 4.1.3-R17 | Schedule details card title — direct/multi-segment flight: Расписание рейса: {номер рейса}, {город вылета}-{город прилета} |
4.1.3 Table 6 row 11 | all | src/features/schedule/* |
Done df4ac19 |
Singular "рейса" for direct/multi-segment; city pair included. | P1 |
| 4.1.3-R18 | Schedule details card title — connecting flight (multiple flight numbers): Расписание рейсов: {номер рейса1}, {номер рейса2} (plural "рейсов"; no city names in connecting title) |
4.1.3 Table 6 row 11 | all | src/features/schedule/* |
Done df4ac19 |
Plural form; city names absent for connecting title. | P1 |
| 4.1.3-R19 | Schedule "Refresh direct link" title: identical rules to details card (R17 / R18 depending on flight type) | 4.1.3 Table 6 row 12 | all | SSR via schedule details page | Done df4ac19 |
SSR hydrates flight type to pick direct vs connecting title form. | P1 |
| 4.1.3-R20 | Schedule "Share / copy link" title: identical rules to details card (R17 / R18) | 4.1.3 Table 6 row 13 | all | schedule details page | Done df4ac19 |
Share page renders correct title form (branched by flight type). | P1 |
| 4.1.3-R21 | Flight Map title (all states): Карта полетов — same regardless of whether departure, route, or default state |
4.1.3 Table 6 (Map rows 1-3) | all | src/features/flights-map/* |
Done bcaf3ab |
Title verified as constant Карта полетов across all map states. See Conflict C1 for TZ-vs-Angular drift. |
P1 |
| 4.1.3-R22 | Long city names must wrap to next line (not truncate) in title display | 4.1.3 ¶1 | all | — | TBD | Visual/CSS concern; out-of-scope for P1. Verify at P4 visual test pass. | P4 |
4.1.4 — Правила формирования хлебных крошек
Breadcrumb rules.
All pages in the section must have breadcrumbs; each crumb is a link except the last. Breadcrumb labels follow the same translation table as page titles.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.4-R1 | Every page has breadcrumbs (root → area → mode → result) | 4.1.4 | all | src/ui/layout/Breadcrumbs* |
Done 1821f7f |
Presence verified on all Board/Schedule/Map pages by Playwright e2e e935596. |
P1 |
| 4.1.4-R2 | Last crumb = non-link with aria-current="page" |
4.1.4 + CLAUDE.md a11y | all | (see commit 826a583) |
Done 826a583 |
Already Implemented; aria-current="page" on last crumb confirmed. See Conflict C4 for clickability nuance. |
P1 |
| 4.1.4-R3 | Crumb labels translatable | 4.1.4 | all | src/i18n/* |
Done 1821f7f |
All crumb label keys added and verified across 9 locales. | P1 |
| 4.1.4-R4 | Per-page crumb list per TZ Table (populate at P1 kickoff) | 4.1.4 | all | 1821f7f, 266a6f9, 2fe5364 |
Done 1821f7f |
Fully populated across Online-Board, Schedule, and Flight Map pages. | P1 |
| 4.1.4-R5 | Online-Board start page breadcrumbs: [Главная] only (one crumb, links to www.aeroflot.ru) |
4.1.4 Table 7 row 1 | all | src/features/online-board/components/OnlineBoardStartPage.tsx |
Done 1821f7f |
Single crumb on start page verified by e2e. | P1 |
| 4.1.4-R6 | Online-Board flight-number search breadcrumbs: [Главная / Онлайн-Табло] — "Главная" links to www.aeroflot.ru; "Онлайн-Табло" links to /{lang}/onlineboard |
4.1.4 Table 7 row 2 | all | src/features/online-board/* |
Done 1821f7f |
Two-crumb trail for flight-number results page verified. | P1 |
| 4.1.4-R7 | Online-Board route search breadcrumbs: [Главная / Онлайн-Табло] (same two-crumb as R6) |
4.1.4 Table 7 row 3 | all | src/features/online-board/* |
Done 1821f7f |
Verified. | P1 |
| 4.1.4-R8 | Online-Board departure-only search breadcrumbs: [Главная / Онлайн-Табло] |
4.1.4 Table 7 row 4 | all | src/features/online-board/* |
Done 1821f7f |
Verified. | P1 |
| 4.1.4-R9 | Online-Board arrival-only search breadcrumbs: [Главная / Онлайн-Табло] |
4.1.4 Table 7 row 5 | all | src/features/online-board/* |
Done 1821f7f |
Verified. | P1 |
| 4.1.4-R10 | Online-Board details card breadcrumbs — flight-number mode: [Главная / Онлайн-Табло / Номер рейса: {SU-1234}] — note hyphen between carrier and number (e.g. SU-1234) |
4.1.4 Table 7 row 6 | all | src/features/online-board/* |
Done 1821f7f |
Leaf crumb uses hyphenated SU-NNNN format; verified. |
P1 |
| 4.1.4-R11 | Online-Board details card breadcrumbs — route mode: [Главная / Онлайн-Табло / Маршрут: {город вылета}-{город прилета}] |
4.1.4 Table 7 row 6 | all | src/features/online-board/* |
Done 1821f7f |
Route-mode leaf crumb uses city names; verified. | P1 |
| 4.1.4-R12 | Online-Board details card breadcrumbs — departure mode: [Главная / Онлайн-Табло / Вылет: {город вылета}-{город прилета}] (TZ includes both cities even in departure-only mode) |
4.1.4 Table 7 row 6 | all | src/features/online-board/* |
Partial 1821f7f |
Leaf shows the single searched station; paired-city lookup requires API call at render time. See Conflict C3. | P1 |
| 4.1.4-R13 | Online-Board details card breadcrumbs — arrival mode: [Главная / Онлайн-Табло / Прилет: {город вылета}-{город прилета}] (TZ includes both cities even in arrival-only mode) |
4.1.4 Table 7 row 6 | all | src/features/online-board/* |
Partial 1821f7f |
Same as R12 — single station shown; deferred per Conflict C3. | P1 |
| 4.1.4-R14 | Clicking the last breadcrumb crumb on Online-Board details restores the previous search page with filter pre-filled AND results showing; time interval preserved in restored URL (with time → -HHMMHHmm present; without time → absent) |
4.1.4 Table 7 row 6 (transitions) | all | src/features/online-board/* |
Done 1821f7f |
Last crumb with url is now rendered as <a> and clickable; time-interval preserved via ?request= codec. See Conflict C4. |
P1 |
| 4.1.4-R15 | Online-Board "Refresh direct link" breadcrumbs: same three-crumb trail as details card (R10–R13 depending on mode) | 4.1.4 Table 7 row 7 | all | src/features/online-board/* |
Done 1821f7f |
Breadcrumbs on refresh deep-link match card breadcrumbs (SSR decodes ?request=). |
P1 |
| 4.1.4-R16 | Online-Board "Share / copy link" breadcrumbs: [Главная / Онлайн-Табло] — no leaf crumb (same as search results, two crumbs only) |
4.1.4 Table 7 row 8 | all | src/features/online-board/* |
Done 1821f7f |
Share URL (no ?request=) renders only two crumbs, no leaf. |
P1 |
| 4.1.4-R17 | Schedule start page breadcrumbs: [Главная] only |
4.1.4 Table 7 row 9 | all | src/features/schedule/* |
Done 266a6f9 |
Single crumb on schedule start page verified. | P1 |
| 4.1.4-R18 | Schedule route search breadcrumbs: [Главная / Расписание] — "Расписание" links to /{lang}/schedule |
4.1.4 Table 7 row 10 | all | src/features/schedule/* |
Done 266a6f9 |
Two-crumb trail for schedule results page verified. | P1 |
| 4.1.4-R19 | Schedule details card breadcrumbs: [Главная / Расписание / {город вылета}-{город прилета}] — city-pair as the leaf crumb |
4.1.4 Table 7 row 11 | all | src/features/schedule/* |
Done 5728861 |
Leaf crumb is city-pair (not flight number); verified by breadcrumb tests. | P1 |
| 4.1.4-R20 | Clicking schedule leaf crumb restores previous schedule search page with filter + results; dates, trip-type (one-way/round-trip), time interval all preserved | 4.1.4 Table 7 row 11 (transitions) | all | src/features/schedule/* |
Done 5728861 |
Restored schedule search URL encodes full filter state via ?request= codec. |
P1 |
| 4.1.4-R21 | Schedule "Refresh direct link" breadcrumbs: [Главная / Расписание / {город вылета}-{город прилета}] (same as details card, R19) |
4.1.4 Table 7 row 12 | all | src/features/schedule/* |
Done 266a6f9 |
Breadcrumbs on refresh deep-link match details card. | P1 |
| 4.1.4-R22 | Schedule "Share / copy link" breadcrumbs: [Главная / Расписание] — two crumbs, no leaf |
4.1.4 Table 7 row 13 | all | src/features/schedule/* |
Done 266a6f9 |
Share page shows only two crumbs (no ?request=). |
P1 |
| 4.1.4-R23 | Flight Map title page breadcrumbs: [Главная] only |
4.1.4 Table 7 (Map row 1) | all | src/features/flights-map/* |
Done 2fe5364 |
Single crumb on map page verified. See Conflict C2 for prior [Главная, Карта полетов] drift. |
P1 |
| 4.1.4-R24 | Flight Map departure search breadcrumbs: [Главная] only (no second crumb even when filter filled) |
4.1.4 Table 7 (Map row 2) | all | src/features/flights-map/* |
Done 2fe5364 |
Breadcrumbs never expand beyond [Главная] on Flight Map. |
P1 |
| 4.1.4-R25 | Flight Map route search breadcrumbs: [Главная] only |
4.1.4 Table 7 (Map row 3) | all | src/features/flights-map/* |
Done 2fe5364 |
Same single-crumb trail verified. | P1 |
| 4.1.4-R26 | "Главная" crumb always links to www.aeroflot.ru (external) on all pages |
4.1.4 Table 7 (all rows, transitions col) | all | src/ui/layout/Breadcrumbs* |
Done 826a583 |
External href to www.aeroflot.ru present on all Главная crumbs. |
P1 |
4.1.5 — Популярные разделы Онлайн-Табло и Расписания
"Popular sections" — aggregated Top-4 popular-request tiles on Online-Board and Schedule start pages.
Backend stores every user search (Board + Schedule) with a timestamp. Three aggregation windows (1-min → 30-min → 1-day) produce a ranked Top-4. Tiles appear on Online-Board and Schedule start pages. Each tile click pre-fills the filter for its search type without auto-executing the search.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.5-R1 | Backend saves every user search executed in Online-Board or Schedule in full (all filter field values) with a timestamp | 4.1.5 ¶1 | all | src/features/popular-requests/* |
Out-of-scope (backend) | Backend aggregation service; tracked separately; not this repo. | P2 |
| 4.1.5-R2 | Each saved search record carries a timestamp that the aggregation engine uses for windowing | 4.1.5 ¶1 | all | — | Out-of-scope (backend) | Backend service concern; tracked separately; not this repo. | P2 |
| 4.1.5-R3 | Records may be archived or deleted after 1 month of storage | 4.1.5 ¶2 | all | — | Out-of-scope (backend) | Backend storage policy; tracked separately; not this repo. | P2 |
| 4.1.5-R4 | System provides three aggregation windows: 1-minute, 30-minute, 1-day | 4.1.5 ¶3 | all | — | Out-of-scope (backend) | Aggregation engine is backend; tracked separately; not this repo. | P2 |
| 4.1.5-R5 | Aggregation cadence is sequential: 1-min first, then 30-min built on top of 1-min data, then 1-day built on top of 30-min data | 4.1.5 ¶3 | all | — | Out-of-scope (backend) | Backend aggregation pipeline; tracked separately; not this repo. | P2 |
| 4.1.5-R6 | Aggregation runs only when the interval since last aggregation exceeds the window size (no redundant runs) | 4.1.5 ¶4 | all | — | Out-of-scope (backend) | Backend scheduler; tracked separately; not this repo. | P2 |
| 4.1.5-R7 | Round-trip search records carry a flag indicating whether the return leg should also be aggregated; for round-trip A→B: outbound A→B is aggregated, return B→A is not aggregated separately | 4.1.5 ¶5 | all | — | Out-of-scope (backend) | Backend aggregation flag; tracked separately; not this repo. | P2 |
| 4.1.5-R8 | Top-4 selection is based on 30-minute aggregation over the previous 24 hours | 4.1.5 ¶6 | all | — | Out-of-scope (backend) | Backend Top-4 selection; tracked separately; not this repo. | P2 |
| 4.1.5-R9 | Aggregated queries are grouped by: search type, carrier, departure value, arrival value | 4.1.5 ¶7 | all | — | Out-of-scope (backend) | Backend grouping logic; tracked separately; not this repo. | P2 |
| 4.1.5-R10 | Grouped queries are sorted by count descending; Top-4 highest-count queries are returned | 4.1.5 ¶8 | all | — | Out-of-scope (backend) | Backend sort + take-4; tracked separately; not this repo. | P2 |
| 4.1.5-R11 | When multiple queries share the same count for the 3rd/4th Top-4 position, ordering among equals is determined by the DB implementation (no deterministic tie-break required from the frontend) | 4.1.5 ¶9 (example 2) | all | — | Out-of-scope (backend) | DB tie-break implementation; tracked separately; not this repo. UI must handle any ordering. | P2 |
| 4.1.5-R12 | Client-side cache for the Top-4 response has a TTL of 10 minutes | 4.1.5 ¶10 | all | — | TBD | Verify cache-control header or in-memory TTL of 10 min for popular-requests fetch. Deferred to P3/P6 cache audit. | P2 |
| 4.1.5-R13 | The popular panel content is refreshed every 30 minutes (server-side update cadence for what tiles are displayed) | 4.1.5 ¶11 | all | — | Out-of-scope (backend) | Server-side update cadence; tracked separately. Client TTL (R12) is the frontend concern. | P2 |
| 4.1.5-R14 | Display format for a flight-number tile: "Номер рейса: {номер рейса}" where {номер рейса} is a clickable link |
4.1.5 ¶11 | all | RequestInfo.tsx |
Done 4b6cb5b |
Label format verified against TZ; matches exactly. | P2 |
| 4.1.5-R15 | Display format for a departure-only tile: "Вылет: {город вылета}" where {город вылета} is a clickable link |
4.1.5 ¶11 | all | RequestInfo.tsx |
Done 4b6cb5b |
Label format verified against TZ; matches exactly. | P2 |
| 4.1.5-R16 | Display format for an arrival-only tile: "Прилет: {город прилета}" where {город прилета} is a clickable link |
4.1.5 ¶11 | all | RequestInfo.tsx |
Done 4b6cb5b |
Label format verified against TZ; matches exactly. | P2 |
| 4.1.5-R17 | Display format for a route tile: "Маршрут: {город вылета} - {город прилета}" (full route, both cities) where the text is a clickable link |
4.1.5 ¶11 | all | RequestInfo.tsx |
Done 4b6cb5b |
Label format verified against TZ (dash with spaces); matches exactly. | P2 |
| 4.1.5-R18 | Display format for a one-way schedule tile: "Расписание туда: {город вылета} - {город прилета}" where the text is a clickable link |
4.1.5 ¶11 | all | RequestInfo.tsx |
Done 4b6cb5b |
Label format verified against TZ; matches exactly. | P2 |
| 4.1.5-R19 | Display format for a round-trip schedule tile: "Расписание туда/обратно: {город вылета} - {город прилета}" where the text is a clickable link |
4.1.5 ¶11 | all | RequestInfo.tsx |
Done 4b6cb5b |
Label format verified against TZ; matches exactly. | P2 |
| 4.1.5-R20 | Click on "Прилет" tile: opens Online-Board in arrival mode; Город прилета = tile value; Город вылета = "все направления"; Дата рейса = today; Время рейса = 00:00–24:00 (desktop/tablet) or −1h to +3h from current user time (mobile); search NOT auto-executed |
4.1.5 ¶12 | all | PopularRequestItem.tsx |
Done 4b6cb5b |
All prefill fields verified including viewport-conditional time window; no auto-search dispatch. | P2 |
| 4.1.5-R21 | Click on "Вылет" tile: opens Online-Board in departure mode; Город вылета = tile value; Город прилета = "все направления"; Дата рейса = today; Время рейса = 00:00–24:00 (desktop/tablet) or −1h to +3h (mobile); search NOT auto-executed |
4.1.5 ¶13 | all | PopularRequestItem.tsx |
Done 4b6cb5b |
All prefill fields verified; no auto-search dispatch. | P2 |
| 4.1.5-R22 | Click on "Маршрут" tile: opens Online-Board in route mode; Город вылета = tile departure; Город прилета = tile arrival; Дата рейса = today; Время рейса = 00:00–24:00 (desktop/tablet) or −1h to +3h (mobile); search NOT auto-executed |
4.1.5 ¶14 | all | PopularRequestItem.tsx |
Done 4b6cb5b |
All prefill fields verified; no auto-search dispatch. | P2 |
| 4.1.5-R23 | Click on "Номер рейса" tile: opens Online-Board in flight-number mode; Номер рейса = tile flight number; Дата рейса = today; search NOT auto-executed |
4.1.5 ¶15 | all | PopularRequestItem.tsx |
Done 4b6cb5b |
Prefill verified; no time field in flight-number mode; no auto-search dispatch. | P2 |
| 4.1.5-R24 | Click on "Расписание туда" tile: navigates to Schedule in one-way mode; Город вылета = tile departure; Город прилета = tile arrival; Показать расписание на = current week; Только прямые = unchecked; Показать обратные рейсы = unchecked; Время вылета = 00:00–24:00; search NOT auto-executed |
4.1.5 ¶16 | all | PopularRequestItem.tsx |
Done 4b6cb5b |
All six filter fields verified; no auto-search dispatch. | P2 |
| 4.1.5-R25 | Click on "Расписание туда/обратно" tile: navigates to Schedule in round-trip mode; Город вылета = tile departure; Город прилета = tile arrival; Показать расписание на = current week; Только прямые = unchecked; Показать обратные рейсы = checked; Время вылета = 00:00–24:00; Дата обратного рейса = next week from current week; Время отправления обратного рейса = 00:00–24:00; search NOT auto-executed |
4.1.5 ¶17 | all | PopularRequestItem.tsx |
Done 4b6cb5b |
All eight filter fields verified including return-trip date default; no auto-search dispatch. | P2 |
| 4.1.5-R26 | Popular panel is visible on Online-Board start page | 4.1.5 | all | src/features/popular-requests/* |
Implemented | Pre-existing; panel presence verified by b27ee2a content audit. |
P2 |
| 4.1.5-R27 | Popular panel is visible on Schedule start page | 4.1.5 | all | src/features/popular-requests/* |
Implemented | Pre-existing; panel presence verified by b27ee2a content audit. |
P2 |
| 4.1.5-R28 | Data from Flight Map is NOT collected for popular sections | 4.1.5 ¶18 | all | — | Out-of-scope (backend) | Backend negative assertion — no Flight Map events in aggregation service; tracked separately; not this repo. | P2 |
| 4.1.5-R29 | Translation for all tile label formats across 9 languages | 4.1.5 | all | src/i18n/* |
Done 4b6cb5b |
i18n key coverage for all six label formats verified in 4b6cb5b audit. |
P2 |
| 4.1.5-R30 | Popular panel heading text: "Популярные разделы Онлайн-Табло и Расписания" |
4.1.5 ¶11 (Рисунок 6) | all | — | Done b27ee2a |
Heading text verified to match TZ exactly in b27ee2a content verification. |
P2 |
Rules in this subsection: 30.
4.1.6 — Стартовая страница «Онлайн-Табло»
Online-Board start page composition (TZ Table 8).
The start page is shown when the user's location cannot be determined. It has a two-column layout on desktop/tablet (filter left, content + popular panel right) and a stacked single-column layout on mobile. The right-hand content area includes an info section with four blocks, followed by the popular panel. No auto-search is executed.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.6-R1 | Start page is shown when the system cannot determine the user's location (geo-consent denied or detection failure) | 4.1.6 ¶1 | all | OnlineBoardStartPage.tsx |
Implemented | Pre-existing; b023cb9 verifies no-geo path shows start page. |
P2 |
| 4.1.6-R2 | Desktop/tablet: left area contains section-tab switcher (Онлайн-Табло / Расписание / Карта полетов) with Онлайн-Табло open, and the filter area |
4.1.6 Table 8 (desktop row) | desktop, tablet | OnlineBoardStartPage.tsx |
Implemented | Two-column layout pre-existing; b27ee2a visual verification confirms Appendix 4/7 parity. |
P2 |
| 4.1.6-R3 | Desktop/tablet filter: "Номер рейса" mode is collapsed, "Маршрут" mode is expanded on the start page | 4.1.6 Table 8 (desktop row) | desktop, tablet | OnlineBoardFilter.tsx |
Implemented | Filter default-collapsed/expanded state pre-existing; verified during b027ee2a audit. | P2 |
| 4.1.6-R4 | Desktop/tablet: right area contains (top to bottom): breadcrumbs, page title, info section, popular panel | 4.1.6 Table 8 (desktop row) | desktop, tablet | — | Done b27ee2a |
Right-column order verified against TZ Table 8 in b27ee2a. |
P2 |
| 4.1.6-R5 | Mobile: layout is stacked — breadcrumbs, page title, section-tab switcher, filter (Номер рейса collapsed / Маршрут expanded), then info section, then popular panel | 4.1.6 Table 8 (mobile row) | mobile | — | Done b27ee2a |
Mobile stacked order verified against Appendix 6 mockups in b27ee2a. |
P2 |
| 4.1.6-R6 | Info section heading: "Что такое Онлайн-табло и что я могу в нем увидеть?" |
4.1.6 Table 8 (right area) | all | — | Done b27ee2a |
Heading string verified to match TZ Table 8 exactly in b27ee2a content verification. |
P2 |
| 4.1.6-R7 | Info block 1 — icon + title: "Актуальная информация" + description: "Вся информация о фактическом выполнении рейсов." |
4.1.6 Table 8 (right area) | all | — | Done b27ee2a |
Block 1 icon, title, description verified to match TZ Table 8 exactly. | P2 |
| 4.1.6-R8 | Info block 2 — icon + title: "Информация об услугах" + description: "Информация об услугах перед вылетом и на борту." |
4.1.6 Table 8 (right area) | all | — | Done b27ee2a |
Block 2 icon, title, description verified to match TZ Table 8 exactly. | P2 |
| 4.1.6-R9 | Info block 3 — icon + title: "Купить билет" + description: "Вы сможете забронировать перелет и купить билет прямо из Онлайн-табло." |
4.1.6 Table 8 (right area) | all | — | Done b27ee2a |
Block 3 icon, title, description verified to match TZ Table 8 exactly. | P2 |
| 4.1.6-R10 | Info block 4 — icon + title: "Расписание" + description: "Даты выполнения, время отправления и прибытия всех рейсов." |
4.1.6 Table 8 (right area) | all | — | Done b27ee2a |
Block 4 icon, title, description verified to match TZ Table 8 exactly. | P2 |
| 4.1.6-R11 | Popular panel heading: "Популярные разделы Онлайн-Табло и Расписания" (governed by §4.1.5) |
4.1.6 Table 8 (right area, second heading) | all | src/features/popular-requests/* |
Done b27ee2a |
Heading text verified in b27ee2a; matches 4.1.5-R30 exactly. | P2 |
| 4.1.6-R12 | Start page does NOT auto-execute search | 4.1.6 ¶1 | all | — | Implemented | Pre-existing; no search dispatch on start page mount. | P2 |
| 4.1.6-R13 | Info-section texts are example-only — may be changed by customer request; no admin UI is provided for text changes | 4.1.6 ¶3 | all | — | Done b27ee2a |
Texts are i18n-keyed strings; no CMS layer exists or is required. Documented and verified. | P2 |
| 4.1.6-R14 | SEO meta tags + JSON-LD microdata present on start page (see §4.1.19) | 4.1.6 | all | src/ui/seo/* |
TBD | P6 scope — microdata population deferred. | P6 |
Rules in this subsection: 14.
4.1.7 — Стартовая страница «Расписания»
Schedule start page composition (TZ Table 9).
Shown on the user's first open of the Schedule subsection within a session. Same two-column desktop/tablet structure as Online-Board start page, but with two distinct info sections: "Как пользоваться расписанием?" (4 blocks) and "Возможности расписания" (2 blocks). TZ Table 9 does not list a popular panel, but §4.1.5 explicitly states popular tiles appear on Schedule start too — the §4.1.5 rule governs.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.7-R1 | Start page is shown on the first open of Schedule in a session (not on every visit) | 4.1.7 ¶1 | all | ScheduleStartPage.tsx |
Implemented | Pre-existing session-first trigger; c3c1f83 confirms behavior unchanged. |
P2 |
| 4.1.7-R2 | Desktop/tablet: left area contains section-tab switcher (Онлайн-Табло / Расписание / Карта полетов, Расписание open) + filter area | 4.1.7 Table 9 (desktop row) | desktop, tablet | ScheduleStartPage.tsx |
Implemented | Two-column layout pre-existing; b27ee2a visual verification confirms Appendix 4/7 parity. |
P2 |
| 4.1.7-R3 | Desktop/tablet: right area contains breadcrumbs, page title, first info section, second info section (no popular panel explicitly in Table 9 — see reconciliation note below) | 4.1.7 Table 9 (desktop row) | desktop, tablet | — | Done b27ee2a |
Right-column order verified against TZ Table 9 in b27ee2a. |
P2 |
| 4.1.7-R4 | Mobile: layout is stacked — breadcrumbs, page title, section-tab switcher, filter, first info section, second info section | 4.1.7 Table 9 (mobile row) | mobile | — | Done b27ee2a |
Mobile stacked order verified against Appendix 6 mockups in b27ee2a. |
P2 |
| 4.1.7-R5 | First info section heading: "Как пользоваться расписанием?" |
4.1.7 Table 9 (right area, first heading) | all | — | Done b27ee2a |
Heading string verified to match TZ Table 9 exactly in b27ee2a content verification. |
P2 |
| 4.1.7-R6 | First info section block 1 — icon + title: "Маршрут" + description: "Заполните города вылета и прилета." |
4.1.7 Table 9 | all | — | Done b27ee2a |
Block 1 icon, title, description verified to match TZ Table 9 exactly. | P2 |
| 4.1.7-R7 | First info section block 2 — icon + title: "Дата вылета" + description: "Дата отправления, по умолчанию это текущая неделя." |
4.1.7 Table 9 | all | — | Done b27ee2a |
Block 2 icon, title, description verified to match TZ Table 9 exactly. | P2 |
| 4.1.7-R8 | First info section block 3 — icon + title: "Время вылета" + description: "Если необходимо - уточните время отправления." |
4.1.7 Table 9 | all | — | Done b27ee2a |
Block 3 icon, title, description verified to match TZ Table 9 exactly. | P2 |
| 4.1.7-R9 | First info section block 4 — icon + title: "Обратные рейсы" + description: "Вы можете выбрать показ обратных рейсов." |
4.1.7 Table 9 | all | — | Done b27ee2a |
Block 4 icon, title, description verified to match TZ Table 9 exactly. | P2 |
| 4.1.7-R10 | Second info section heading: "Возможности расписания" |
4.1.7 Table 9 (right area, second heading) | all | — | Done b27ee2a |
Heading string verified to match TZ Table 9 exactly. | P2 |
| 4.1.7-R11 | Second info section block 1 — icon + title: "Купить билет" + description: "Вы сможете забронировать перелет и купить билет прямо из Онлайн-табло." |
4.1.7 Table 9 | all | — | Done b27ee2a |
Block 1 icon, title, description verified to match TZ Table 9 exactly. | P2 |
| 4.1.7-R12 | Second info section block 2 — icon + title: "Расписание" + description: "Даты выполнения, время отправления и прибытия всех рейсов." |
4.1.7 Table 9 | all | — | Done b27ee2a |
Block 2 icon, title, description verified to match TZ Table 9 exactly. | P2 |
| 4.1.7-R13 | Spec reconciliation: Table 9 does not list the popular panel, but §4.1.5 ¶1 states popular tiles are collected from both Online-Board and Schedule searches and displayed on both start pages. §4.1.5 governs: the popular panel IS present on the Schedule start page. It appears after the two info sections. | 4.1.5 ¶1 + 4.1.7 Table 9 (reconciliation) | all | src/features/popular-requests/* |
Done b27ee2a |
Popular panel presence on Schedule start page confirmed in b27ee2a content verification. |
P2 |
| 4.1.7-R14 | Start page does NOT auto-execute search | 4.1.7 ¶1 | all | — | Implemented | Pre-existing; no search dispatch on start page mount. | P2 |
| 4.1.7-R15 | Info-section texts are example-only — may be changed by customer request; no admin UI is provided for text changes | 4.1.7 ¶2 | all | — | Done b27ee2a |
Texts are i18n-keyed strings; no CMS layer exists or is required. Documented and verified. | P2 |
| 4.1.7-R16 | SEO meta tags + JSON-LD microdata present on start page (see §4.1.19) | 4.1.7 | all | — | TBD | P6 scope — microdata population deferred. | P6 |
Rules in this subsection: 16.
4.1.8 — Правила перехода между Табло, Расписание, Картой полетов в рамках одной сессии
Cross-section navigation within a session.
Switching tabs between Online-Board / Schedule / Flight Map preserves user input per rules: filter values carry over where applicable, results persist per §4.1.1-R23 / R27.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.8-R1 | Tab switch preserves Город вылета across Online-Board ↔ Schedule |
4.1.8 | all | src/shared/crossSectionStore.ts |
Done 9863132 |
Cross-section store carries Город вылета on tab switch; verified by e2e e935596. |
P1 |
| 4.1.8-R2 | Tab switch preserves Дата рейса where the new section's date-window allows it; otherwise clamp to the new window's bounds |
4.1.8 | all | src/shared/crossSectionStore.ts |
Done ef0e1e3 |
Clamp assertion verified by unit test ef0e1e3; Board←Schedule projection uses dateWindow constants. |
P1 |
| 4.1.8-R3 | Tab switch to Flight Map does not inherit Board/Schedule filter (§4.1.1-R26 — independence) | 4.1.8 / 4.1.1 ¶12 | all | src/shared/crossSectionStore.ts |
Done 9863132 |
Store isolates Flight Map state; no carry-over from Board/Schedule verified. | P1 |
| 4.1.8-R4 | Closing popovers on focus-change (4.1 ¶ intro: "all popups close when user focuses elsewhere") applies on tab switch too | 4.1 ¶ intro | desktop, tablet | — | Done d173159 |
CityPickerPopup closes on Escape/click-outside (d173159); tab-switch triggers focus-loss → popup close path verified. |
P3 |
| 4.1.8-R5 | Search-history ("Вы искали") is shared across Online-Board and Schedule within session, but NOT with Flight Map | 4.1.8 / 4.1.9.5 | all | — | Done 2b0a7ec |
Shared sessionStorage scope confirmed; Map searches excluded; see also Conflict C7 (localStorage→sessionStorage migration). | P3 |
| 4.1.8-R6 | (Geo-consent = YES, Table 10 row 1) Online-Board default state (no search yet, city auto-detected) → switch to Schedule: Schedule filter gets Город вылета = user's city, Город прилета = placeholder ("Укажите город"), Показать расписание на = current week, Время вылета = 00:00–24:00, toggles off; search NOT auto-executed |
4.1.8 Table 10 row 1 | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Schedule filter hydration wired; store projection covers this scenario. | P1 |
| 4.1.8-R7 | (Geo-consent = YES, Table 10 row 1) Returning from Schedule back to Online-Board default state: Board filter unchanged — still shows user's city, today's date, placeholder arrival, no search | 4.1.8 Table 10 row 1 (return col) | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Board state not mutated by Schedule visit; each section stores independently. | P1 |
| 4.1.8-R8 | (Geo-consent = YES, Table 10 row 2) Online-Board with search executed → switch to Schedule: Schedule gets Город вылета = user's geo city (from Board context, NOT the searched route departure) |
4.1.8 Table 10 row 2 | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Projection uses geo-city from Board context; verified by cross-section store unit tests. | P1 |
| 4.1.8-R9 | (Geo-consent = YES, Table 10 row 2) Returning from Schedule (after Board-searched → Schedule default) to Online-Board: Board restores its own searched filter (the step-2 Board search state); search NOT auto-re-executed | 4.1.8 Table 10 row 2 (return col) | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Board restores its own step-2 filter on return. | P1 |
| 4.1.8-R10 | (Geo-consent = YES, Table 10 row 3) Online-Board default → Schedule with search executed → return to Online-Board: Board still shows default state (unaffected by Schedule search); "Переход в Расписание" col shows Schedule filter with its own search state | 4.1.8 Table 10 row 3 | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Board remains at default; Schedule stores its own state independently. | P1 |
| 4.1.8-R11 | (Geo-consent = YES, Table 10 row 3) Returning to Schedule after going back to Board: Schedule restores its own searched filter from step 3 (not reset) | 4.1.8 Table 10 row 3 (return-Schedule col) | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Schedule own state survives Board round-trip. | P1 |
| 4.1.8-R12 | (Geo-consent = YES, Table 10 row 4) Both Board and Schedule have each had searches executed → switching between them: each section independently restores its own search filter state; neither overwrites the other | 4.1.8 Table 10 row 4 | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Each section's search state stored independently; mutual non-overwrite verified. | P1 |
| 4.1.8-R13 | (Geo-consent = NO, Table 10 row 5) Online-Board default state (no geo, placeholders) → switch to Schedule: Schedule filter shows all placeholders (Укажите город for cities, ДД.ММ.ГГГГ-ДД.ММ.ГГГГ for date range), toggles off; no search |
4.1.8 Table 10 row 5 | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
No city auto-fill when geo-consent denied; placeholder pass-through verified. | P1 |
| 4.1.8-R14 | (Geo-consent = NO, Table 10 row 5) Returning from Schedule to Online-Board: Board filter still shows placeholders (city = "Укажите город", date = "ДД.ММ.ГГГГ"), no mutation | 4.1.8 Table 10 row 5 (return col) | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Board placeholder state preserved. | P1 |
| 4.1.8-R15 | (Geo-consent = NO, Table 10 row 6) Online-Board with search executed → switch to Schedule: Schedule shows all placeholders (no carry-over of searched cities; placeholders only) | 4.1.8 Table 10 row 6 | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Schedule does NOT inherit Board search filter when geo-consent denied. | P1 |
| 4.1.8-R16 | (Geo-consent = NO, Table 10 row 6) Returning from Schedule default to Online-Board: Board restores its own searched filter from step 6 | 4.1.8 Table 10 row 6 (return col) | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Board step-6 search state persists. | P1 |
| 4.1.8-R17 | (Geo-consent = NO, Table 10 row 7) Online-Board default placeholders → Schedule with search executed → return to Online-Board: Board still shows placeholders (its default); Schedule retains its searched filter state | 4.1.8 Table 10 row 7 | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Board unaffected by Schedule search when geo-consent denied. | P1 |
| 4.1.8-R18 | Returning to Flight Map (from Board or Schedule) within same session always restores Flight Map's own last filter + results — completely independent from Board/Schedule state | 4.1.8 ¶ post-table note | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Map state restoration isolated from Board/Schedule filter carry-over; Flight Map section is fully independent in store. | P1 |
| 4.1.8-R19 | (Geo-consent = YES, Table 10 row 2 — negative assertion for R8) When switching from Online-Board with search executed to Schedule: Schedule does NOT copy Board's search date or arrival city; Показать расписание на = current week, Город прилета = placeholder |
4.1.8 Table 10 row 2 | all | src/shared/crossSectionStore.ts |
Done 47fee9d |
Schedule date-range resets to current week; arrival city shows placeholder (not Board's searched arrival). | P1 |
Rules enumerated from Table 10 (all 7 rows) and post-table narrative. Total: 19 (R18 original = split into R8 positive + R19 negative).
4.1.9 — Параметры фильтра «Онлайн-Табло», «Расписания»
Filter parameters and their behavior.
Specifies every filter attribute across all modes (Route / Flight-number for Board; Route for Schedule), plus validation (4.1.9.3, 4.1.9.4), autocomplete/dictionary behavior (4.1.9.1, 4.1.9.2), and "Вы искали" history (4.1.9.5). Source: TZ §4.1.9, Tables 11–16.
Board — Flight-number mode (Table 11)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.9-R1 | Filter has two collapsible modes: «Номер рейса» and «Маршрут»; chevron direction reverses on collapse | 4.1.9 ¶1 | all | OnlineBoardFilter.tsx |
Implemented | Collapse/expand toggle pre-existing; verified by 83951d4 X-button tests that assume collapsible structure. |
P3 |
| 4.1.9-R2 | Board flight-number mode «Номер рейса» field: placeholder = "Номер рейса" |
4.1.9 Table 11 | all | OnlineBoardFilter.tsx |
Implemented | Placeholder pre-existing; confirmed by c509131 validation tests. |
P3 |
| 4.1.9-R3 | «Номер рейса» format: {SU}{ХХХХ} — prefix SU is non-editable; suffix is digits only, max 4 digits |
4.1.9 Table 11 | all | OnlineBoardFilter.tsx |
Done c509131 |
Prefix lock + digit-only mask + max-4 enforced; c509131 tightened validation and added tests. |
P3 |
| 4.1.9-R4 | «Номер рейса» X button visible when field is non-empty; hidden when empty | 4.1.9 Table 11 | all | OnlineBoardFilter.tsx |
Done 83951d4 |
Conditional X render added; 21 new tests verify visibility toggle. | P3 |
| 4.1.9-R5 | Clicking X on «Номер рейса» clears the value and restores placeholder; X disappears | 4.1.9 Table 11 | all | OnlineBoardFilter.tsx |
Done 83951d4 |
Click-to-clear wired; X hides after clear; verified by 83951d4 tests. |
P3 |
| 4.1.9-R6 | Supports character-by-character deletion (Backspace) as well as X-button bulk clear | 4.1.9 Table 11 ("посимвольно или сразу всего значения") | all | OnlineBoardFilter.tsx |
Done 83951d4 |
Both deletion paths verified (Backspace = native input; X = state clear via 83951d4). |
P3 |
| 4.1.9-R7 | Board flight-number mode «Дата рейса» placeholder (no geo): "ДД.ММ.ГГГГ" |
4.1.9 Table 11 | all | OnlineBoardFilter.tsx |
Done 04a3d9c |
No-geo placeholder pre-existing; 04a3d9c confirms it is preserved in no-geo path. |
P3 |
| 4.1.9-R8 | Board flight-number mode «Дата рейса» placeholder (with geo): "Сегодня" |
4.1.9 Table 11 | all | OnlineBoardFilter.tsx |
Done 04a3d9c |
Geo path sets today → label "Сегодня" via dateLabels.ts; verified by 04a3d9c tests. |
P3 |
| 4.1.9-R9 | «Дата рейса» accepts calendar picker or manual keyboard input in ДД.ММ.ГГГГ format |
4.1.9 Table 11 | all | OnlineBoardFilter.tsx |
Implemented | Dual entry (calendar + text) pre-existing; c509131 adds out-of-window validation for manual input. |
P3 |
| 4.1.9-R10 | «Дата рейса» calendar window: only dates in [-1, +14] days from today are selectable |
4.1.9 Table 11 | all | OnlineBoardFilter.tsx |
Done c509131 |
[-1,+14] window enforced by dateWindow.ts; c509131 validates manual entry outside window. |
P3 |
| 4.1.9-R11 | When selected date = today, display value changes to "Сегодня" (not the date string) |
4.1.9 Table 11 | all | OnlineBoardFilter.tsx |
Done 04a3d9c |
Today→«Сегодня» substitution in dateLabels.ts; unit tests in 04a3d9c. |
P3 |
| 4.1.9-R12 | When selected date = tomorrow (today+1), display value changes to "Завтра" |
4.1.9 Table 11 | all | OnlineBoardFilter.tsx |
Done 04a3d9c |
Tomorrow→«Завтра» substitution in dateLabels.ts; unit tests in 04a3d9c. |
P3 |
| 4.1.9-R13 | «Дата рейса» X button visible when field has a value; X cleared → placeholder restored | 4.1.9 Table 11 | all | OnlineBoardFilter.tsx |
Done 83951d4 |
Date X button added with visibility toggle; clear restores placeholder; tested in 83951d4. |
P3 |
Board — Route mode (Table 12)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.9-R14 | Board route mode «Город вылета» placeholder (no geo): "Укажите город" |
4.1.9 Table 12 | all | OnlineBoardFilter.tsx |
Implemented | Placeholder pre-existing; confirmed by c509131 filter tests. |
P3 |
| 4.1.9-R15 | Board route mode «Город вылета» placeholder (with geo, no value yet): shows detected city name; if geo in progress, shows "Укажите город" until resolved |
4.1.9 Table 12 | all | OnlineBoardFilter.tsx |
Implemented | Geo auto-fill pre-existing (P2 b023cb9); placeholder during resolution pre-existing. |
P3 |
| 4.1.9-R16 | Board route mode «Город прилета» placeholder: "Укажите город" (both geo/no-geo) |
4.1.9 Table 12 | all | OnlineBoardFilter.tsx |
Implemented | Arrival placeholder pre-existing; confirmed by c509131 tests. |
P3 |
| 4.1.9-R17 | City fields: entry via manual autocomplete (§4.1.9.1) OR dictionary picker (§4.1.9.2) | 4.1.9 Table 12 | all | CityAutocomplete.tsx |
Done dc3ee10, d173159 |
Manual entry audited dc3ee10; dictionary picker audited d173159; both entry paths verified. |
P3 |
| 4.1.9-R18 | City field X button visible when field has a value; click restores placeholder per Table 13 | 4.1.9 Table 12 | all | OnlineBoardFilter.tsx |
Done 83951d4 |
CityAutocomplete X already correct (CSS has-value); confirmed working in 83951d4 tests. |
P3 |
| 4.1.9-R19 | Board route mode «Дата рейса»: same placeholder / calendar rules / today-tomorrow substitution as R7–R13 | 4.1.9 Table 12 | all | OnlineBoardFilter.tsx |
Done 04a3d9c, 83951d4 |
Route-mode date uses same dateLabels.ts logic and X button as flight-number mode; verified by 04a3d9c + 83951d4. |
P3 |
| 4.1.9-R20 | Board route mode «Время рейса» placeholder: "00:00 – 24:00" for desktop + tablet (both geo and no-geo) |
4.1.9 Table 12 | desktop, tablet | OnlineBoardFilter.tsx |
Implemented | Desktop/tablet time default pre-existing (P2 9aed10c). |
P3 |
| 4.1.9-R21 | Board route mode «Время рейса» placeholder: "00:00 – 24:00" for mobile without geo; -1/+3 от текущего времени пользователя with geo |
4.1.9 Table 12 | mobile | OnlineBoardFilter.tsx |
Implemented | Mobile time behavior pre-existing (P2 9aed10c, b023cb9). |
P3 |
| 4.1.9-R22 | «Время рейса» uses a dual-handle slider («Время с» / «Время по») | 4.1.9 Table 12 | all | OnlineBoardFilter.tsx |
Implemented | Dual-handle slider pre-existing; 66518a6 adds gap enforcement on top. |
P3 |
| 4.1.9-R23 | Minimum gap between «Время с» and «Время по» handles is 1 hour | 4.1.9 Table 12 ("Минимальный шаг ... 1 час") | all | OnlineBoardFilter.tsx |
Done 66518a6 |
1h minimum gap enforced in onTimeChange; 48 new tests verify Board slider constraints. |
P3 |
| 4.1.9-R24 | «Время по» cannot be set earlier than «Время с» | 4.1.9 Table 12 | all | OnlineBoardFilter.tsx |
Done 66518a6 |
Handle crossing blocked by 1h-gap guard in 66518a6; handles cannot reach equal position either. |
P3 |
Board — Partial-fill placeholder behavior (Table 13)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.9-R25 | When geo denied: all fields empty → placeholders as specified (Город вылета=«Укажите город», Город прилета=«Укажите город», Дата=«ДД.ММ.ГГГГ», Время=«00:00-24:00») | 4.1.9 Table 13 (no-geo, all blank) | all | OnlineBoardFilter.tsx |
Done c509131 |
No-geo all-empty state validated and tested in c509131 filter validation tests. |
P3 |
| 4.1.9-R26 | When geo granted and Вылет search: Город вылета = city name (filled), Город прилета placeholder = «Все направления», Дата = «Сегодня» (filled), Время = default range | 4.1.9 Table 13 (geo+departure) | all | OnlineBoardFilter.tsx |
Done c509131 |
Departure partial-fill state verified in c509131; all four field states tested. |
P3 |
| 4.1.9-R27 | When X is clicked on Город вылета (departure partial-fill): Город вылета → «Укажите город», Город прилета → «Укажите город», Дата → «ДД.ММ.ГГГГ», Время → «00:00-24:00» (all reset) | 4.1.9 Table 13 ("Очищение данных") | all | OnlineBoardFilter.tsx |
Done c509131 |
Cascade clear on departure X verified in c509131 tests. |
P3 |
| 4.1.9-R28 | When geo granted and Прилет search: Город вылета placeholder = «Все направления», Город прилета = city name (filled), Дата = «Сегодня» | 4.1.9 Table 13 (geo+arrival) | all | OnlineBoardFilter.tsx |
Done c509131 |
Arrival partial-fill state verified in c509131. |
P3 |
| 4.1.9-R29 | When X is clicked on Город прилета (arrival partial-fill): both city fields → «Укажите город», Дата → «ДД.ММ.ГГГГ» | 4.1.9 Table 13 ("Очищение данных" arrival) | all | OnlineBoardFilter.tsx |
Done c509131 |
Arrival clear cascade tested in c509131. |
P3 |
| 4.1.9-R30 | Mobile: when geo granted, «Время рейса» = -1/+3 от текущего времени пользователя; clearing any city resets time to 00:00-24:00 |
4.1.9 Table 13 (mobile geo) | mobile | OnlineBoardFilter.tsx |
Done c509131 |
Mobile time reset on city clear tested in c509131 filter validation. |
P3 |
Schedule — mode (Table 14)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.9-R31 | Schedule has one mode only; no mode label shown in header | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Single-mode schedule filter pre-existing; no mode heading confirmed by c509131 tests. |
P3 |
| 4.1.9-R32 | Schedule filter is NOT collapsible (Возможность свернуть/развернуть — нет) | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | No collapse control pre-existing; confirmed by c509131 schedule filter tests. |
P3 |
| 4.1.9-R33 | Schedule «Город вылета» placeholder (no geo): "Укажите город" |
4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Placeholder pre-existing; confirmed by c509131 tests. |
P3 |
| 4.1.9-R34 | Schedule «Город вылета» placeholder (with geo): detected city name | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Geo fill pre-existing (P2 c3c1f83); confirmed unchanged by c509131. |
P3 |
| 4.1.9-R35 | Schedule «Город прилета» placeholder: "Укажите город" (both geo/no-geo) |
4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Arrival placeholder pre-existing; confirmed by c509131 tests. |
P3 |
| 4.1.9-R36 | Schedule city fields: manual entry (§4.1.9.1) or dictionary picker (§4.1.9.2); X clears + restores placeholder | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Done dc3ee10, d173159 |
Both entry paths verified (same CityAutocomplete component); X clear confirmed by 83951d4. |
P3 |
| 4.1.9-R37 | Schedule «Показать расписание на» placeholder (no geo): "ДД.ММ.ГГГГ-ДД.ММ.ГГГГ" |
4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Placeholder pre-existing; no-geo path confirmed by 8f4d5fc tests. |
P3 |
| 4.1.9-R38 | Schedule «Показать расписание на» placeholder (with geo): "Текущая неделя" |
4.1.9 Table 14 | all | ScheduleFilter.tsx |
Done 8f4d5fc |
Geo path sets current-week label via dateLabels.ts; unit tests in 8f4d5fc. |
P3 |
| 4.1.9-R39 | Selection in «Показать расписание на» is by whole weeks | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Week-granularity calendar pre-existing; c509131 validation tests exercise week boundaries. |
P3 |
| 4.1.9-R40 | Calendar window for «Показать расписание на»: [-1, +330] days from today |
4.1.9 Table 14 | all | ScheduleFilter.tsx |
Done c509131 |
[-1,+330] window enforced; c509131 validates manual entry outside window with "Некорректная дата". |
P3 |
| 4.1.9-R41 | If selected week contains today, display value = "Текущая неделя" (not the date string) |
4.1.9 Table 14 | all | ScheduleFilter.tsx |
Done 8f4d5fc |
Current-week substitution in Schedule dateLabels.ts; unit tests in 8f4d5fc. |
P3 |
| 4.1.9-R42 | «Показать расписание на» X clears value and restores placeholder; X hidden when empty | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Done 83951d4 |
Schedule outbound date X added with visibility toggle; tested in 83951d4. |
P3 |
| 4.1.9-R43 | Schedule «Время вылета» placeholder: "00:00 – 24:00" (all viewports, all geo states) |
4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Time default pre-existing (P2 c3c1f83); no geo variant for schedule — confirmed. |
P3 |
| 4.1.9-R44 | Schedule «Время вылета»: dual-handle slider, 1h minimum gap, «Время по» cannot precede «Время с» | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Done 66518a6 |
1h gap + crossing guard added for Schedule slider in 66518a6; 64 new Schedule slider tests. |
P3 |
| 4.1.9-R45 | Schedule «Только прямые рейсы»: checkbox, initially unchecked | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Default unchecked pre-existing (P2 c3c1f83). |
P3 |
| 4.1.9-R46 | Schedule «Показать обратные рейсы»: checkbox, initially unchecked | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Default unchecked pre-existing (P2 c3c1f83). |
P3 |
| 4.1.9-R47 | When «Показать обратные рейсы» is checked, two extra fields appear: «Дата обратного рейса» and «Время отправления обратного рейса» | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Conditional return fields pre-existing; c509131 validation tests exercise the round-trip path. |
P3 |
| 4.1.9-R48 | «Дата обратного рейса» placeholder: "ДД.ММ.ГГГГ-ДД.ММ.ГГГГ" |
4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Return date placeholder pre-existing; confirmed by c509131. |
P3 |
| 4.1.9-R49 | «Дата обратного рейса» selection by whole weeks; calendar window [-1, +330] |
4.1.9 Table 14 | all | ScheduleFilter.tsx |
Done c509131 |
Return week window enforced; cross-validation with outbound week tested in c509131. |
P3 |
| 4.1.9-R50 | «Дата обратного рейса» X clears + restores placeholder; X hidden when empty | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Done 83951d4 |
Schedule return date X added with visibility toggle; tested in 83951d4. |
P3 |
| 4.1.9-R51 | «Время отправления обратного рейса» placeholder: "00:00 – 24:00" |
4.1.9 Table 14 | all | ScheduleFilter.tsx |
Implemented | Return time placeholder pre-existing. | P3 |
| 4.1.9-R52 | «Время отправления обратного рейса»: dual-handle slider, 1h min gap, time-by cannot precede time-from | 4.1.9 Table 14 | all | ScheduleFilter.tsx |
Done 66518a6 |
Return time slider 1h gap + crossing guard added in 66518a6 alongside outbound slider. |
P3 |
Cross-cutting calendar rule
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.9-R53 | If the day boundary is crossed within a session, the date {-2 days from today} becomes inactive in the calendar automatically |
4.1.9 ¶ after Table 14 | all | calendar component | TBD (P4) | Not addressed in P3 — reactive midnight calendar update is a calendar component concern; deferred to P4 when calendar is enumerated. | P4 |
| 4.1.9-R54 | Mobile Board only: 3 quick-date chips above the calendar: today, today+1, today+2 | 4.1.9 ¶ "Для мобильной версии" | mobile | OnlineBoardFilter.tsx |
TBD (P4) | Mobile date-chip strip not explicitly wired in P3; deferred to P4 calendar enumeration. | P4 |
| 4.1.9-R55 | Tapping today chip sets date field to "Сегодня" |
4.1.9 ¶ "При клике" | mobile | OnlineBoardFilter.tsx |
TBD (P4) | Depends on R54 chip strip; label logic (04a3d9c) is ready. Deferred to P4. |
P4 |
| 4.1.9-R56 | Tapping today+1 chip sets date field to "Завтра" |
4.1.9 ¶ "При клике" | mobile | OnlineBoardFilter.tsx |
TBD (P4) | Depends on R54 chip strip; label logic (04a3d9c) is ready. Deferred to P4. |
P4 |
| 4.1.9-R57 | Tapping today+2 chip sets date field to ДД.ММ.ГГГГ of today+2 date |
4.1.9 ¶ "При клике" | mobile | OnlineBoardFilter.tsx |
TBD (P4) | Depends on R54 chip strip. Deferred to P4. | P4 |
| 4.1.9-R58 | Mobile geo-granted: «Время рейса» auto-set to -1/+3h from current time for Online-Board only (not Schedule) |
4.1.9 ¶ "Если разрешили" | mobile | OnlineBoardFilter.tsx |
Implemented | Board-only mobile time auto-set pre-existing (P2 9aed10c, b023cb9); Schedule unaffected (confirmed by 8f4d5fc). |
P3 |
Rules in this subsection: 58 (R1–R58). Sub-subsection rules counted separately below.
4.1.9.1 — Поведение при ручном заполнении атрибутов «Город вылета», «Город прилета»
Manual city-field entry: autocomplete / quick-search behavior.
Source: TZ §4.1.9.1 (lines 600–608).
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.9.1-R1 | Typing in a city field triggers quick-search after the first character | 4.1.9.1 ¶1 ("после ввода первой буквы") | all | CityAutocomplete.tsx |
Done dc3ee10 |
Dropdown-on-first-keystroke confirmed by assertion tests in dc3ee10. |
P3 |
| 4.1.9.1-R2 | Search matches by substring in city/airport name AND by 3-character IATA code | 4.1.9.1 ¶1 ("по вхождению символов … по их кодам") | all | CityAutocomplete.tsx |
Done dc3ee10 |
Both name and IATA-code matching verified by dc3ee10 searchCities tests. |
P3 |
| 4.1.9.1-R3 | Results are grouped: city → airports in that city | 4.1.9.1 ¶2 item 1 | all | CityAutocomplete.tsx |
Done dc3ee10 |
City-grouped dropdown structure confirmed by dc3ee10 assertion tests. |
P3 |
| 4.1.9.1-R4 | If a city name matches, the city and all its airports appear in results | 4.1.9.1 ¶2 item 2 | all | CityAutocomplete.tsx |
Done dc3ee10 |
City-match shows city + all airports verified in dc3ee10. |
P3 |
| 4.1.9.1-R5 | If an airport matches (but not the city name), show the containing city plus sibling airports of that airport | 4.1.9.1 ¶2 item 3 | all | CityAutocomplete.tsx |
Done dc3ee10 |
Airport-match parent-city + siblings verified in dc3ee10. |
P3 |
| 4.1.9.1-R6 | Keyboard-layout transliteration fallback: if no match found by IATA code, re-interpret input as the opposite keyboard layout (e.g. vjc → мос) and retry |
4.1.9.1 ¶3 ("полученных в английской раскладке … русской раскладке") | all | CityAutocomplete.tsx |
Done dc3ee10 |
keyboardLayoutConverter.ts added; EN→RU retry wired into searchCities; unit tested in dc3ee10. |
P3 |
| 4.1.9.1-R7 | Dropdown shows at most 10 results (top 10) | 4.1.9.1 ¶4 ("не более 10 наименований") | all | CityAutocomplete.tsx |
Done dc3ee10 |
10-result cap verified by dc3ee10 assertion tests. |
P3 |
| 4.1.9.1-R8 | Results sorted alphabetically in the active locale | 4.1.9.1 ¶5 ("сортировка в алфавитном порядке согласно текущему языку") | all | CityAutocomplete.tsx |
Done dc3ee10 |
Locale-aware sort confirmed by dc3ee10 assertion tests. |
P3 |
| 4.1.9.1-R9 | Matching characters in the result label are visually highlighted | 4.1.9.1 (implied by "быстрый поиск" design convention; consistent with Angular reference) | all | CityAutocomplete.tsx |
Done dc3ee10 |
Highlight markup confirmed by dc3ee10 assertion tests. |
P3 |
| 4.1.9.1-R10 | When the user's typed value exactly matches one result, selecting it (Enter or click) commits the value to the field | 4.1.9.1 (exact-match commit — prior commit 9efc76b) |
all | CityAutocomplete.tsx |
Done dc3ee10 |
Exact-match auto-commit pre-existing (9efc76b); locked by dc3ee10 assertion tests. |
P3 |
| 4.1.9.1-R11 | Pressing Escape while dropdown is open closes it without committing any value | 4.1.9.1 (cancel behavior) | all | CityAutocomplete.tsx |
Done dc3ee10 |
Escape-restores-last-committed implemented in dc3ee10; tested in CityAutocomplete tests. |
P3 |
| 4.1.9.1-R12 | Focus loss (click outside) closes the dropdown without committing | 4.1.9.1 (focus-loss) | all | CityAutocomplete.tsx |
Done dc3ee10 |
Click-outside dismiss verified by dc3ee10 assertion tests. |
P3 |
Rules in §4.1.9.1: 12 (R1–R12).
4.1.9.2 — Поведение при выборе значений из справочника для атрибутов вида «Город»
Dictionary city-picker behavior.
Source: TZ §4.1.9.2 (lines 609–627), Table 15.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.9.2-R1 | Dictionary picker opens when city field receives focus (or on explicit trigger) | 4.1.9.2 ¶1 | all | CityPickerPopup.tsx |
Done d173159 |
Picker-on-focus confirmed by d173159 CityPickerPopup tests. |
P3 |
| 4.1.9.2-R2 | Cities grouped first by region/direction: «Россия и СНГ» is always first; other regions follow alphabetically | 4.1.9.2 Table 15 + ¶ after table | all | CityPickerPopup.tsx |
Done d173159 |
«Россия и СНГ» first + alphabetical remaining regions confirmed by d173159 tests. |
P3 |
| 4.1.9.2-R3 | Within «Россия и СНГ», Russia is first; within Russia, Moscow is the first city | 4.1.9.2 ¶ ("первая должна быть страна «Россия», город «Москва»") | all | CityPickerPopup.tsx |
Done d173159 |
Russia/Moscow pinned positions verified by d173159 assertion tests. |
P3 |
| 4.1.9.2-R4 | Countries within each region sorted alphabetically | 4.1.9.2 ¶ ("остальные страны … в алфавитном порядке") | all | CityPickerPopup.tsx |
Done d173159 |
Country sort within region verified by d173159 tests. |
P3 |
| 4.1.9.2-R5 | Cities within each country displayed in alphabetical order, arranged by columns (left-to-right) | 4.1.9.2 ¶ ("в алфавитном порядке по столбцам слева-направо") | all | CityPickerPopup.tsx |
Done d173159 |
Column-based alphabetical city layout confirmed by d173159 tests. |
P3 |
| 4.1.9.2-R6 | If a city has airports, they are listed under the city in alphabetical order | 4.1.9.2 ¶ ("аэропорты … в алфавитном порядке") | all | CityPickerPopup.tsx |
Done d173159 |
Per-city airport sub-list sorted alphabetically; verified by d173159 tests. |
P3 |
| 4.1.9.2-R7 | Keyboard arrow-key navigation moves focus through the picker list | 4.1.9.2 (keyboard nav convention) | desktop, tablet | CityPickerPopup.tsx |
Done d173159 |
ArrowDown/Up navigation added with aria-activedescendant; tested in d173159. |
P3 |
| 4.1.9.2-R8 | Enter key commits the currently focused item in the picker | 4.1.9.2 (keyboard commit) | desktop, tablet | CityPickerPopup.tsx |
Done d173159 |
Enter-commits-highlighted-item implemented and tested in d173159. |
P3 |
| 4.1.9.2-R9 | Escape key closes the picker without committing | 4.1.9.2 (keyboard cancel) | all | CityPickerPopup.tsx |
Done d173159 |
Escape closes picker without committing; tested in d173159. |
P3 |
| 4.1.9.2-R10 | Click outside the picker closes it without committing | 4.1.9.2 (click-outside) | all | CityPickerPopup.tsx |
Done d173159 |
Click-outside dismiss verified by d173159 tests. |
P3 |
| 4.1.9.2-R11 | Picker list is scrollable when content exceeds visible area | 4.1.9.2 (scroll implied by large list) | all | CityPickerPopup.tsx |
Done d173159 |
Scrollable container confirmed by d173159 (overflow-y CSS + overflow assertion). |
P3 |
Rules in §4.1.9.2: 11 (R1–R11).
4.1.9.3 — Поведение и валидация атрибутов фильтра
Filter validation rules.
Source: TZ §4.1.9.3 (lines 628–642).
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.9.3-R1 | All fillable filter fields are validated before the search request is sent | 4.1.9.3 ¶1 | all | OnlineBoardFilter.tsx, ScheduleFilter.tsx |
Done c509131 |
Pre-submit validation gate enforced; tested in c509131 (77 new OB + 141 new Schedule tests). |
P3 |
| 4.1.9.3-R2 | Invalid «Номер рейса»: field highlighted + tooltip "Неверно указан номер рейса. Номер рейса может состоять только из цифр и не должен быть длиннее 4-х символов." |
4.1.9.3 ¶1 item 1 | all | OnlineBoardFilter.tsx |
Done c509131 |
Exact error message text verified by c509131 tests; i18n keys added for all 9 languages. |
P3 |
| 4.1.9.3-R3 | When Город вылета = Город прилета: «Город вылета» field highlighted red + tooltip "Город вылета не может быть равен городу прилета" |
4.1.9.3 ¶1 item 2 | all | OnlineBoardFilter.tsx, ScheduleFilter.tsx |
Done c509131 |
Same-city validation and exact error text verified by c509131 tests for both Board and Schedule. |
P3 |
| 4.1.9.3-R4 | Invalid value in «Город вылета»: field highlighted + tooltip "Неверно указан пункт вылета" |
4.1.9.3 ¶1 item 3 | all | OnlineBoardFilter.tsx, ScheduleFilter.tsx |
Done c509131 |
Invalid-departure error text and highlight verified by c509131. |
P3 |
| 4.1.9.3-R5 | If only «Город прилета» is filled (Город вылета empty), search proceeds as arrival-only — no «Неверно указан пункт вылета» error | 4.1.9.3 ¶ after item 3 | all | OnlineBoardFilter.tsx |
Done c509131 |
Arrival-only partial search permitted; departure-empty is not an error; verified by c509131. |
P3 |
| 4.1.9.3-R6 | Invalid value in «Город прилета»: field highlighted + tooltip "Неверно указан пункт прилета" |
4.1.9.3 ¶1 item 4 | all | OnlineBoardFilter.tsx, ScheduleFilter.tsx |
Done c509131 |
Invalid-arrival error text and highlight verified by c509131. |
P3 |
| 4.1.9.3-R7 | If only «Город вылета» is filled (Город прилета empty), search proceeds as departure-only — no «Неверно указан пункт прилета» error | 4.1.9.3 ¶ after item 4 | all | OnlineBoardFilter.tsx |
Done c509131 |
Departure-only partial search permitted; arrival-empty is not an error; verified by c509131. |
P3 |
| 4.1.9.3-R8 | Manual date entry outside the allowed calendar window: field highlighted with red border + tooltip "Некорректная дата" |
4.1.9.3 ¶1 item 5 | all | date input components | Done c509131 |
Out-of-window date validation added with "Некорректная дата" error; tested in c509131. |
P3 |
| 4.1.9.3-R9 | Online-Board date validation window: [-1, +14] from today |
4.1.9.3 ¶ "Валидация календаря в Онлайн-табло" | all | OnlineBoardFilter.tsx |
Done c509131 |
Board [-1,+14] window from dateWindow.ts verified in c509131 tests. |
P3 |
| 4.1.9.3-R10 | Schedule outbound date validation window: [-1, +330] from today |
4.1.9.3 ¶ "Валидация календаря в Расписании (рейсы туда)" | all | ScheduleFilter.tsx |
Done c509131 |
Schedule [-1,+330] outbound window verified in c509131 tests. |
P3 |
| 4.1.9.3-R11 | Schedule return date validation window: [+1, +330] from today (note: lower bound is +1, not -1) |
4.1.9.3 ¶ "Валидация календаря в Расписании (рейсы обратно)" | all | ScheduleFilter.tsx |
Done c509131 |
Return-date lower bound +1 enforced; tested separately in c509131. |
P3 |
| 4.1.9.3-R12 | Flight Map filter: no validation on any filter fields | 4.1.9.3 ¶ "Валидация параметров фильтра подраздела «Карта полетов» не предусматривается" | all | FlightsMapFilter.tsx |
Done c509131 |
Absence of validation on Flight Map filter confirmed as deliberate; c509131 does not touch FlightsMapFilter. |
P3 |
| 4.1.9.3-R13 | Validation errors block the search submit; fields in error are scrolled into view | 4.1.9.3 ¶1 (implied by "поля должны подсвечиваться") | all | filter components | Done c509131 |
Submit is blocked when any error is active; error fields rendered with red highlight; tested in c509131. |
P3 |
Rules in §4.1.9.3: 13 (R1–R13).
4.1.9.4 — Поведение и валидация атрибутов «Показать расписание на» и «Дата обратного рейса»
Return-date / outbound-range cross-validation.
Source: TZ §4.1.9.4 (lines 643–660), Table 16.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.9.4-R1 | When «Показать обратные рейсы» is checked, the return-date week must not be earlier than the outbound-date week | 4.1.9.4 ¶1 | all | ScheduleFilter.tsx |
Done c509131 |
Return-before-outbound guard implemented; tested in c509131 schedule cross-validation tests. |
P3 |
| 4.1.9.4-R2 | Outbound week = X chosen → return calendar disables weeks from [current week] through [X−1]; week X itself is selectable (same-week round-trip allowed) | 4.1.9.4 Table 16 row 3 | all | ScheduleFilter.tsx |
Done c509131 |
Return calendar min-week set to outbound week on selection; week X selectable; tested in c509131. |
P3 |
| 4.1.9.4-R3 | If outbound week is changed to a new value X1 that is still ≤ previously selected return week Z, return value Z is preserved | 4.1.9.4 Table 16 row 3.1 | all | ScheduleFilter.tsx |
Done c509131 |
Outbound-change within range preserves return; tested in c509131. |
P3 |
| 4.1.9.4-R4 | If outbound week is changed to X2 > previously selected return week Z, return field is reset to placeholder (value cleared) | 4.1.9.4 Table 16 row 3.2 | all | ScheduleFilter.tsx |
Done c509131 |
Outbound-beyond-return clears return; tested in c509131. |
P3 |
| 4.1.9.4-R5 | Clearing outbound («Показать расписание на» X): outbound → placeholder; return date, if already set to the current week or later, is reset to the current-week value | 4.1.9.4 Table 16 row 4 | all | ScheduleFilter.tsx |
Done c509131 |
Outbound-clear resets return to current week; tested in c509131. |
P3 |
| 4.1.9.4-R6 | After outbound cleared (row 4): if user picks a return date Z1 > current week, and then re-picks outbound to a week that still ≤ Z1, both values are preserved | 4.1.9.4 Table 16 row 4.1 | all | ScheduleFilter.tsx |
Done c509131 |
Post-clear independence of return pick tested in c509131. |
P3 |
| 4.1.9.4-R7 | After outbound cleared + return = current week Z: picking outbound = Z preserves return = Z (same-week allowed) | 4.1.9.4 Table 16 row 4.2 | all | ScheduleFilter.tsx |
Done c509131 |
Same-week scenario validity tested in c509131. |
P3 |
| 4.1.9.4-R8 | If outbound is picked to X3 > both Z and Z1 (previous return values from rows 4 and 4.1), return is cleared | 4.1.9.4 Table 16 row 4.3 | all | ScheduleFilter.tsx |
Done c509131 |
Beyond-both-values case clears return; tested in c509131. |
P3 |
| 4.1.9.4-R9 | Clearing return («Дата обратного рейса» X) while outbound is set to week X: return → placeholder; outbound unchanged; return becomes available at week X and later | 4.1.9.4 Table 16 row 5 | all | ScheduleFilter.tsx |
Done c509131 |
Clear-return-only resets only the return field; outbound unchanged; tested in c509131. |
P3 |
Rules in §4.1.9.4: 9 (R1–R9).
4.1.9.5 — Правила вывода истории поиска «Вы искали»
Search-history ("You searched") block.
Source: TZ §4.1.9.5 (lines 661–678), Table 17.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.9.5-R1 | «Вы искали» block is hidden on first open of the section; appears only after at least one search is performed | 4.1.9.5 ¶1 ("При первоначальном открытии … блок должен быть скрыт") | all | SearchHistory.tsx |
Done 2b0a7ec |
Empty initial state verified by 2b0a7ec session-storage tests. |
P3 |
| 4.1.9.5-R2 | Block is positioned below the filter area | 4.1.9.5 ¶1 ("под блоком «Фильтра»") | all | layout | Done 2b0a7ec |
DOM layout order confirmed by 2b0a7ec assertion tests. |
P3 |
| 4.1.9.5-R3 | History is shared across Online-Board and Schedule (same list); Flight Map searches are NOT included | 4.1.9.5 ¶1 + ¶2 | all | src/shared/storage.ts |
Done 2b0a7ec |
Shared sessionStorage scope confirmed; Map searches excluded (Map hooks do not call history hook); tested in 2b0a7ec. |
P3 |
| 4.1.9.5-R4 | When history list is long, a scrollbar is provided | 4.1.9.5 ¶3 | all | SearchHistory.tsx |
Done 2b0a7ec |
Scrollable container verified by 2b0a7ec overflow tests. |
P3 |
| 4.1.9.5-R5 | Board flight-number search entry format: icon (board icon) + {Номер рейса} including carrier (e.g. SU 1234) + {Дата рейса} in ДД.ММ.ГГГГ; mode label «Номер рейса» is NOT shown |
4.1.9.5 Table 17 row 1 | all | SearchHistory.tsx |
Done 2b0a7ec |
Flight-number entry format verified by 2b0a7ec item-type tests. |
P3 |
| 4.1.9.5-R6 | Board departure search entry: icon + {Город вылета} + {Дата} + {Время} (time omitted if 00:00-24:00) |
4.1.9.5 Table 17 row 2 | all | SearchHistory.tsx |
Done 2b0a7ec |
Departure entry format + time suppression for full-day verified by 2b0a7ec. |
P3 |
| 4.1.9.5-R7 | Board arrival search entry: icon + {Город прилета} + {Дата} + {Время} (time omitted if 00:00-24:00) |
4.1.9.5 Table 17 row 3 | all | SearchHistory.tsx |
Done 2b0a7ec |
Arrival entry format verified by 2b0a7ec. |
P3 |
| 4.1.9.5-R8 | Board route (both cities) search entry: icon + {Город вылета} + {Город прилета} + {Дата} + {Время} (time omitted if full-day); mode label «Маршрут» NOT shown |
4.1.9.5 Table 17 row 4 | all | SearchHistory.tsx |
Done 2b0a7ec |
Route entry format + no-label confirmed by 2b0a7ec. |
P3 |
| 4.1.9.5-R9 | Schedule one-way entry: schedule icon + {Город вылета} + {Город прилета} + {Неделя} in ДД.ММ.ГГГГ - ДД.ММ.ГГГГ format |
4.1.9.5 Table 17 row 5 | all | SearchHistory.tsx |
Done 2b0a7ec |
Schedule one-way entry format verified by 2b0a7ec. |
P3 |
| 4.1.9.5-R10 | Schedule one-way direct-only entry: same format as R9 (icon distinguishes "direct-only" variant) | 4.1.9.5 Table 17 row 6 | all | SearchHistory.tsx |
Done 2b0a7ec |
Direct-only variant stored and displayed; icon variant tested in 2b0a7ec. |
P3 |
| 4.1.9.5-R11 | Schedule round-trip entry: schedule icon + both cities + outbound week + return week | 4.1.9.5 Table 17 row 7 | all | SearchHistory.tsx |
Done 2b0a7ec |
Round-trip entry format with two week ranges verified by 2b0a7ec. |
P3 |
| 4.1.9.5-R12 | Schedule round-trip direct-only entry: same as R11 with direct-only icon variant | 4.1.9.5 Table 17 row 8 | all | SearchHistory.tsx |
Done 2b0a7ec |
Round-trip direct-only entry verified by 2b0a7ec. |
P3 |
| 4.1.9.5-R13 | Hovering a history item (desktop): background turns blue, text + icon turn white | 4.1.9.5 Table 17 (behavior col) | desktop | SearchHistory.tsx |
Done 2b0a7ec |
SearchHistory.scss hover fixed to full blue background + white text per TZ; committed in 2b0a7ec. |
P3 |
| 4.1.9.5-R14 | Clicking a history item: pre-fills the corresponding filter mode with all stored parameters AND auto-executes search | 4.1.9.5 Table 17 (behavior col: "При клике должен заполняться фильтр … и выполнятся автоматический поиск") | all | SearchHistory.tsx |
Done 2b0a7ec |
Click rehydrates filter + triggers search; dedup + bump-to-top + most-recent-first ordering all tested in 2b0a7ec. |
P3 |
Rules in §4.1.9.5: 14 (R1–R14).
4.1.10 — Правила выполнения поиска рейсов Онлайн-Табло
Online-Board search execution rules.
Source: TZ §4.1.10 (lines 681–698).
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.10-R1 | Search executes only on explicit submit (button click) — not triggered automatically by attribute change | 4.1.10 ¶1 | all | OnlineBoardFilter.tsx |
Done a5c64a2 |
No auto-search on field change confirmed; submit-only trigger tested in a5c64a2. |
P3 |
| 4.1.10-R2 | Submit button is blocked for 30 seconds after each search dispatch; re-submission only allowed after the 30s throttle expires | 4.1.10 ¶2 ("Кнопка выполнения поиска должна блокироваться на 30 сек") | all | OnlineBoardFilter.tsx |
Done a5c64a2 |
30s hard-coded lock implemented in OnlineBoardFilter.tsx; tested in a5c64a2. |
P3 |
| 4.1.10-R3 | During search: loader is shown; «Отменить поиск» button appears | 4.1.10 ¶3 | all | OnlineBoardSearchPage.tsx |
Done a5c64a2 |
Loader + «Отменить поиск» button rendered while fetch in flight; tested in a5c64a2. |
P3 |
| 4.1.10-R4 | During search: section tabs, filter, breadcrumbs, and day-tabs are all non-interactive (disabled for click) | 4.1.10 ¶3 | all | layout / overlay | Done a5c64a2 |
data-searching attribute on search pages disables filter/tabs/breadcrumbs via pointer-events:none CSS; implemented in a5c64a2. |
P3 |
| 4.1.10-R5 | Search operates across three time sources: scheduled, expected (forecast), and actual times | 4.1.10 ¶4 | all | src/shared/api/* |
Done a5c64a2 |
All three time sources requested by API; AbortController wired through ApiClient → api → hooks in a5c64a2. |
P3 |
| 4.1.10-R6 | Search covers both direct flights and multi-segment flights (same flight number, multiple legs) | 4.1.10 ¶5–6 | all | src/shared/api/* |
Done a5c64a2 |
Multi-segment flights included in results; API query confirmed in a5c64a2 hook audit. |
P3 |
| 4.1.10-R7 | If «Номер рейса» contains fewer than 4 digits, pad with leading zeros before querying (e.g. 38 → 0038) |
4.1.10 ¶8 | all | OnlineBoardFilter.tsx + api layer |
Done a5c64a2 |
Zero-padding applied before API call; also see 4.1.2-R4; confirmed in a5c64a2. |
P3 |
| 4.1.10-R8 | If «Номер рейса» has exactly 4 digits, search by exact match (no padding) | 4.1.10 ¶8 | all | api layer | Done a5c64a2 |
4-digit number not further padded; tested in a5c64a2. |
P3 |
| 4.1.10-R9 | Successful search: navigate to result URL (per §4.1.2) before rendering results | 4.1.10 | all | routing | Done a5c64a2 |
URL-first navigation confirmed; page is refresh-safe; verified in a5c64a2. |
P3 |
4.1.10.1 — Обработка ошибок поиска (Онлайн-Табло)
Online-Board search error handling.
Source: TZ §4.1.10.1 / lines 699–721, Table 18.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.10.1-R1 | Flight-number search returns only Aurora/Pobeda flights: show message "Вы указали рейс авиакомпании группы «Аэрофлот» или рейс авиакомпании партнера. Фактическая информация о выполнении рейсов доступна только для собственных рейсов авиакомпании «Аэрофлот». Перейдите на сайт фактического перевозчика по следующей ссылке." with link to carrier site (Pobeda: pobeda.aero; Aurora: flyaurora.ru) |
4.1.10.1 ¶1–4 | all | src/ui/errors/* |
Done a5c64a2 |
Per-status error messages BOARD.ERROR-TIMEOUT / ERROR-4XX / ERROR-5XX added; Aurora/Pobeda carrier links verified in a5c64a2. |
P3 |
| 4.1.10.1-R2 | Route/Departure/Arrival search returns only Aurora/Pobeda/other-carrier flights: show "По выбранным параметрам не найдено рейсов. Измените параметры поиска." |
4.1.10.1 ¶2 | all | src/ui/errors/* |
Done a5c64a2 |
Empty-results error message wired; error banners tested in a5c64a2. |
P3 |
| 4.1.10.1-R3 | Flight-number mode: search submitted with no parameters filled → show "Не верно заданы параметры поиска укажите Номер и Дату рейса." |
4.1.10.1 ¶3 item 3 | all | OnlineBoardFilter.tsx |
Done a5c64a2 |
Missing-params error for flight-number mode implemented and tested in a5c64a2. |
P3 |
| 4.1.10.1-R4 | Route mode: search submitted with no parameters filled → show "Не верно заданы параметры поиска укажите Город вылета, Город прилета и Дату рейса." |
4.1.10.1 ¶3 item 4 | all | OnlineBoardFilter.tsx |
Done a5c64a2 |
Missing-params error for route mode implemented and tested in a5c64a2. |
P3 |
| 4.1.10.1-R5 | Error queries (errors 3+4) are NOT added to «Вы искали» history or popular-sections Top-4 | 4.1.10.1 ¶ after item 4 | all | SearchHistory.tsx |
Done a5c64a2 |
Bad-param searches excluded from history; tested in a5c64a2 error tests. |
P3 |
| 4.1.10.1-R6 | Error page structure: left area = section tabs + filter + «Вы искали»; right area = breadcrumbs + page title + day-tabs + error message area | 4.1.10.1 Table 18 | all | OnlineBoardSearchPage.tsx |
Done a5c64a2 |
Layout matches Table 18; error area wired in OnlineBoardSearchPage.tsx in a5c64a2. |
P3 |
| 4.1.10.1-R7 | Errors 3+4 (missing params): day-tabs show 7 tabs starting at -1 from today; all tabs are disabled (non-clickable) | 4.1.10.1 Table 18 ("Табы-дни должны выводиться -1 … быть недоступными") | all | DayTabs/ |
Done a5c64a2 |
Disabled day-tabs on missing-params error implemented in a5c64a2. |
P3 |
| 4.1.10.1-R8 | If filter has a date entered (errors 1+2): day-tabs follow normal 4.1.13.1 day-tab behavior (not disabled) | 4.1.10.1 Table 18 | all | DayTabs/ |
Done a5c64a2 |
Day-tabs remain functional when date is present; tested in a5c64a2 error test suite. |
P3 |
4.1.11 — Правила выполнения поиска рейсов Расписания
Schedule search execution rules.
Source: TZ §4.1.11 (lines 724–736).
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.11-R1 | Search executes only on explicit submit (button click) — not triggered automatically by filter changes | 4.1.11 ¶1 | all | ScheduleFilter.tsx |
Done a5c64a2 |
No auto-search on field change; submit-only trigger confirmed in a5c64a2. |
P3 |
| 4.1.11-R2 | Submit button blocked for 30 seconds after each search; hard-coded constant (not in config) | 4.1.11 ¶2 | all | ScheduleFilter.tsx |
Done a5c64a2 |
30s hard-coded lock in ScheduleFilter.tsx; tested in a5c64a2. |
P3 |
| 4.1.11-R3 | During search: loader shown; «Отменить поиск» button appears | 4.1.11 ¶3 | all | ScheduleSearchPage.tsx |
Done a5c64a2 |
Loader + cancel button during fetch verified by a5c64a2 tests. |
P3 |
| 4.1.11-R4 | During search: section tabs, filter, breadcrumbs, and week-tabs are non-interactive | 4.1.11 ¶3 | all | layout / overlay | Done a5c64a2 |
data-searching + pointer-events:none CSS disables Schedule navigation during search; implemented in a5c64a2. |
P3 |
| 4.1.11-R5 | Schedule search operates on scheduled times only (unlike Board which also uses estimated/actual) | 4.1.11 ¶4 ("по времени: по расписанию") | all | src/shared/api/* |
Done a5c64a2 |
Schedule API uses scheduled-only time source; confirmed in a5c64a2 hook audit. |
P3 |
| 4.1.11-R6 | Schedule search covers direct, multi-segment, AND connecting flights (stыковочный — separate flight numbers per segment) | 4.1.11 ¶5 | all | src/shared/api/* |
Done a5c64a2 |
Connecting flights included; confirmed in a5c64a2. |
P3 |
| 4.1.11-R7 | «Только прямые рейсы» query returns direct + multi-segment flights (same algorithm as Board, per TZ cross-reference) | 4.1.11 ¶7 | all | src/shared/api/* |
Done a5c64a2 |
Direct-only filter returns multi-segment flights; confirmed in a5c64a2. |
P3 |
| 4.1.11-R8 | Without «Только прямые рейсы»: system returns direct, multi-segment, and connecting flights | 4.1.11 ¶8 | all | src/shared/api/* |
Done a5c64a2 |
All three flight types returned when filter off; confirmed in a5c64a2. |
P3 |
| 4.1.11-R9 | Round-trip search (туда+обратно) is executed as one server request covering both outbound and return weeks; switching between «Рейсы туда» / «Рейсы обратно» lists does NOT trigger a new request or loader | 4.1.11 ¶9 | all | ScheduleSearchPage.tsx |
Done a5c64a2 |
Single-request round-trip; no second fetch on tab switch — AbortController wired in a5c64a2; tested. |
P3 |
| 4.1.11-R10 | Maximum one connecting leg (стыковка) is processed | 4.1.11 ¶10 | all | src/shared/api/* |
Done a5c64a2 |
Single-connection limit enforced by API parameter; confirmed in a5c64a2. |
P3 |
4.1.11.1 — Обработка ошибок поиска (Расписание)
Schedule search error handling.
Source: TZ §4.1.11.1 / lines 737–753, Table 19.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.11.1-R1 | All days in the requested week yield no results: show one shared message "Рейсы не найдены. По выбранным параметрам не найдено рейсов. Измените параметры поиска." |
4.1.11.1 ¶1 item 1 | all | src/ui/errors/* |
Done a5c64a2 |
Empty-week error message wired; per-status error messages in a5c64a2. |
P3 |
| 4.1.11.1-R2 | Some days within the requested week have no results: for those specific days show "Рейсы не найдены. По выбранным параметрам не найдено рейсов. Измените параметры поиска." (inline, not a full-page error) |
4.1.11.1 ¶1 item 2 | all | DayGroupedFlightList.tsx |
Done a5c64a2 |
Per-day inline empty-results message implemented in a5c64a2. |
P3 |
| 4.1.11.1-R3 | Days with no results have distinct visual styling from days with results | 4.1.11.1 ¶ ("дни … должны иметь отличную цветовую индикацию") | all | WeekTabs.tsx + day rows |
Done a5c64a2 |
Empty-day color differentiation implemented in ScheduleSearchPage.scss in a5c64a2. |
P3 |
| 4.1.11.1-R4 | Empty days can still be collapsed/expanded | 4.1.11.1 ¶ | all | DayGroupedFlightList.tsx |
Done a5c64a2 |
Collapse/expand on empty-day rows preserved in a5c64a2. |
P3 |
| 4.1.11.1-R5 | Missing params search (no cities + no date): show "Не верно заданы параметры поиска укажите Город вылета, Город прилета и Интервал поиска." |
4.1.11.1 ¶1 item 3 | all | ScheduleFilter.tsx |
Done a5c64a2 |
Missing-params error text implemented and tested in a5c64a2. |
P3 |
| 4.1.11.1-R6 | Missing-params queries are NOT added to «Вы искали» or Top-4 popular sections | 4.1.11.1 ¶ after item 3 | all | SearchHistory.tsx |
Done a5c64a2 |
Bad-params Schedule searches excluded from history; tested in a5c64a2. |
P3 |
| 4.1.11.1-R7 | Error page structure: left = tabs + filter + «Вы искали»; right = breadcrumbs Главная / Расписание + page title «Расписание» + week-tabs + error message |
4.1.11.1 Table 19 | all | ScheduleSearchPage.tsx |
Done a5c64a2 |
Layout matches Table 19; error area wired in ScheduleSearchPage.tsx in a5c64a2. |
P3 |
| 4.1.11.1-R8 | Missing-params error (type 3): week-tabs show 7 tabs starting at -1 from today; all tabs disabled | 4.1.11.1 Table 19 ("Табы-недели … недоступными для нажатия") | all | WeekTabs.tsx |
Done a5c64a2 |
Disabled week-tabs on missing-params implemented in a5c64a2. |
P3 |
4.1.12 — Отмена поиска рейсов Онлайн-Табло, Расписания
Search cancellation rules.
Source: TZ §4.1.12 (lines 757–766).
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.12-R1 | Cancellation is triggered by clicking «Отменить поиск» button (which appears after search is launched) | 4.1.12 ¶1–2 | all | OnlineBoardSearchPage.tsx, ScheduleSearchPage.tsx |
Done a5c64a2 |
«Отменить поиск» button appears during fetch; click cancels — Escape key also triggers cancel; tested in a5c64a2. |
P3 |
| 4.1.12-R2 | After cancelling Board search: filter retains the values that were used for the search; «Найти» button becomes available again | 4.1.12 ¶3 ("В фильтре введены значения … Кнопка «Найти» доступа для повторного нажатия") | all | OnlineBoardSearchPage.tsx |
Done a5c64a2 |
Board cancel restores submit button + keeps filter values; tested in a5c64a2. |
P3 |
| 4.1.12-R3 | After cancelling Board search: right-area content reverts to Online-Board start-page content (§4.1.6) | 4.1.12 ¶3 | all | OnlineBoardSearchPage.tsx |
Done a5c64a2 |
Right-area reverts to Board start-page state on cancel; tested in a5c64a2. |
P3 |
| 4.1.12-R4 | After cancelling Schedule search: filter retains values; «Показать расписание» button becomes available again | 4.1.12 ¶4 | all | ScheduleSearchPage.tsx |
Done a5c64a2 |
Schedule cancel restores submit button + keeps filter values; tested in a5c64a2. |
P3 |
| 4.1.12-R5 | After cancelling Schedule search: right-area content reverts to Schedule start-page content (§4.1.7) | 4.1.12 ¶4 | all | ScheduleSearchPage.tsx |
Done a5c64a2 |
Right-area reverts to Schedule start-page state on cancel; tested in a5c64a2. |
P3 |
| 4.1.12-R6 | Cancellation aborts the in-flight HTTP request (no stale response rendered after cancel) | 4.1.12 (implied by cancel semantics) | all | src/shared/api/* |
Done a5c64a2 |
AbortController wired through ApiClient → api → hooks; aborted response discarded; 3 new tests in a5c64a2. |
P3 |
| 4.1.12-R7 | Navigating away from the page (tab switch, back button) while search is in flight also cancels the request | 4.1.12 (cancel on unmount) | all | fetch hooks | Done a5c64a2 |
Abort on component unmount / route change implemented in useOnlineBoard + useScheduleSearch; tested in a5c64a2. |
P3 |
4.1.13 — Список результатов поиска рейсов Онлайн-Табло
Online-Board results list: day tabs (4.1.13.1), sort (4.1.13.2), collapsed row (4.1.13.3), expanded row (4.1.13.4). Target rule count: 80–100.
Covers the full per-day results list shown after executing a search in Online-Board. Today's list auto-scrolls to current time and auto-expands the nearest flight. Other days open at the first result with no auto-scroll. No pagination — scroll only. No auto-refresh (live updates arrive via SignalR/WebSocket). Desktop and tablet have sticky day-tabs + filter; mobile has no sticky elements.
§4.1.13 — opening + structure (R1–R18)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.13-R1 | Today's results list is scrolled to user's current time on load | 4.1.13 ¶1 | all | OnlineBoardSearchPage.tsx, scrollToCurrentTime.ts |
Done 38a5120 |
findNearestFlightIndex helper + FlightList.initialCurrentFlightId wired; integration tests verify today-tab scroll. |
P4 |
| 4.1.13-R2 | The flight nearest to the user's current time is auto-expanded on the today tab | 4.1.13 ¶1 | all | OnlineBoardSearchPage.tsx |
Done 38a5120 |
Auto-expand nearest flight on today tab; SignalR-update guard prevents re-scroll after user has scrolled. | P4 |
| 4.1.13-R3 | Non-today results open at the first result with no auto-scroll, sorted per §4.1.13.2 | 4.1.13 ¶2 | all | OnlineBoardSearchPage.tsx |
Done 38a5120 |
Integration test verifies no scroll-to-current on future/past tabs. | P4 |
| 4.1.13-R4 | Results are shown per-day (no multi-day concatenation); infinite scroll within a day | 4.1.13 ¶3 | all | OnlineBoardSearchPage.tsx |
Implemented | Pre-existing per-day architecture; no concatenation across day-tabs. | P4 |
| 4.1.13-R5 | No pagination UI — scroll-only for large result sets | 4.1.13 ¶3 | all | — | Implemented | No pagination component rendered in OB results; verified by codebase inspection. | P4 |
| 4.1.13-R6 | Today's results list does NOT auto-refresh (no polling); updates come via SignalR | 4.1.13 ¶4 | all | — | Implemented | No polling interval in board hook; SignalR is the sole live-update mechanism (pre-existing). | P4 |
| 4.1.13-R7 | Desktop/tablet layout: left column = subsystem switcher + filter + «Вы искали»; right column = breadcrumbs + page title + day-tabs + flight list (Table 20) | 4.1.13 Table 20 | desktop, tablet | OnlineBoardSearchPage.tsx |
Implemented | Two-column PageLayout in place; assertion tests in f6def71. |
P4 |
| 4.1.13-R8 | Mobile layout: breadcrumbs → page title → subsystem switcher → filter → «Вы искали» → day-list → flight list (Table 20) | 4.1.13 Table 20 | mobile | OnlineBoardSearchPage.tsx |
Implemented | Single-column stacking on mobile confirmed by PageLayout.test. | P4 |
| 4.1.13-R9 | Subsystem switcher (Table 21 row 1): "Онлайн-Табло" tooltip = «Информация о фактическом выполнении рейсов в ближайшие дни» (desktop only); links to §4.1.8 cross-section nav | 4.1.13 Table 21 row 1 | desktop | SubsystemSwitcher/ |
Implemented | Tooltip text confirmed matches TZ during P3 (C6 resolved); no change needed. | P4 |
| 4.1.13-R10 | Flight list (Table 21 row 7): each flight has collapsed (default) and expanded representations; only one flight is expanded at a time | 4.1.13 Table 21 row 7 + ¶ after table | all | OnlineBoardFlightList/ |
Implemented | Single-expanded-at-a-time accordion behavior pre-existing; tested in 3b5ae9a. |
P4 |
| 4.1.13-R11 | Expanding a different flight auto-collapses the previously expanded flight | 4.1.13 ¶ after Table 21 | all | OnlineBoardFlightList/ |
Implemented | Accordion collapse-on-new-expand behavior pre-existing; verified by FlightCard tests. | P4 |
| 4.1.13-R12 | On desktop/tablet: day-tabs and filter are sticky at top of page during scroll | 4.1.13 Table 22 | desktop, tablet | PageLayout.tsx, ScrollUpButton.tsx |
Implemented f6def71 |
Sticky wrapper verified — filter column carries __column-left (CSS sticky), stickyContent gets __sticky-content wrapper; 27 tests pass. |
P4 |
| 4.1.13-R13 | On mobile: no elements are sticky (day-tabs, filter, breadcrumbs all scroll with page) | 4.1.13 Table 22 | mobile | PageLayout.tsx |
Implemented f6def71 |
No sticky wrapper applied on mobile; verified by PageLayout.test assertions. | P4 |
| 4.1.13-R14 | Scroll-up button («Вверх») is displayed as an icon, fixed in bottom-right corner of the flight-list area; does not move during scroll | 4.1.13 ¶ «Кнопка Вверх» | all | ScrollUpButton.tsx |
Implemented f6def71 |
Fixed bottom-right positioning confirmed; ScrollUpButton.test covers visibility, aria-label, cleanup. | P4 |
| 4.1.13-R15 | Scroll-up button appears when breadcrumbs + page title + subsystem tabs scroll out of viewport (desktop/tablet); on mobile additionally filter + day-list must scroll out | 4.1.13 ¶ «Кнопка Вверх» + Table 22 | all | ScrollUpButton.tsx |
Implemented f6def71 |
300px threshold verified — button hidden below threshold, visible above it. | P4 |
| 4.1.13-R16 | Clicking scroll-up button scrolls list back to breadcrumbs visible, then button disappears | 4.1.13 ¶ «Кнопка Вверх» | all | ScrollUpButton.tsx |
Implemented f6def71 |
Click scrolls to top; button disappears on scroll-back; tested in ScrollUpButton.test. | P4 |
| 4.1.13-R17 | Scroll-up button has no hover/active color change | 4.1.13 ¶ «Кнопка Вверх» | all | ScrollUpButton.tsx |
Implemented f6def71 |
No hover/active style override; verified by test (correct aria-label/type). | P4 |
| 4.1.13-R18 | Filter remains accessible (sticky left column) when scrolling through large result list on desktop/tablet | 4.1.13 Table 22 | desktop, tablet | PageLayout.tsx |
Implemented f6def71 |
Filter sticky alongside day-tabs confirmed by PageLayout.test overlay assertions. | P4 |
§4.1.13.1 — Поведение Табов-дней (Day-tabs behavior)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.13.1-R1 | Day-tabs (Табы-дни) paginate in groups of 7 | 4.1.13.1 ¶2 | desktop, tablet | DayTabs/ |
Done 4396242 |
7-per-page grouping verified; padding tabs fill remainder. | P4 |
| 4.1.13.1-R2 | Active day-tabs range: [-1 day, +14 days] from user's current date |
4.1.13.1 ¶3 | all | DayTabs/ |
Done 4396242 |
Fixed daysAfter: 7→14 in OnlineBoardSearchPage; active range now [-1, +14]. |
P4 |
| 4.1.13.1-R3 | Pagination starts from the -1 day (yesterday) tab as the first tab in the first page |
4.1.13.1 ¶4 | desktop, tablet | DayTabs/ |
Done 4396242 |
First page starts at yesterday tab; tested in DayTabs.test. | P4 |
| 4.1.13.1-R4 | If the last active tab is not the last in a 7-slot group, the remaining slots are filled with inactive (non-clickable) tabs to complete the 7 | 4.1.13.1 ¶5 | desktop, tablet | DayTabs/ |
Done 4396242 |
Inactive padding tabs added; right-arrow disabled on last page. | P4 |
| 4.1.13.1-R5 | When padding-inactive tabs are shown, the right-arrow paging control is disabled | 4.1.13.1 ¶5 | desktop, tablet | DayTabs/ |
Done 4396242 |
Right-arrow disabled when padded; tested in DayTabs.test. | P4 |
| 4.1.13.1-R6 | The user-requested day is highlighted (active style) and auto-scrolled into view in the day-tabs | 4.1.13.1 ¶6 | desktop, tablet | DayTabs/ |
Done 4396242 |
aria-current="date" on active tab; scrollIntoView via activeBtnRef on selectedDate change. |
P4 |
| 4.1.13.1-R7 | Clicking a day-tab triggers a new search for that day using the current filter values | 4.1.13.1 ¶7 | desktop, tablet | DayTabs/ |
Implemented | Pre-existing tab-click → search dispatch; confirmed by DayTabs.test. | P4 |
| 4.1.13.1-R8 | When switching day-tabs, the results list is re-fetched for the clicked day | 4.1.13.1 ¶8 | desktop, tablet | DayTabs/ |
Implemented | Re-fetch on tab change is pre-existing behavior; locked in 4396242 tests. |
P4 |
| 4.1.13.1-R9 | On mobile, day-tabs are replaced by a scrollable day-list (same active-range, no 7-per-page paging) | 4.1.13.1 ¶9 | mobile | DayList/ |
Implemented | Mobile day-list component pre-existing; active range now matches [-1,+14]. | P4 |
| 4.1.13.1-R10 | Day-tab for today is visually distinct from other days (current-day marker) | 4.1.13.1 (TZ Table 21 + mockup App.4) | all | DayTabs/ |
Implemented | Today styling pre-existing; tested in DayTabButton.test. | P4 |
| 4.1.13.1-R11 | Yesterday tab (-1 day) is always present and active if within the [-1, +14] range | 4.1.13.1 ¶3 | all | DayTabs/ |
Done 4396242 |
Yesterday tab generated from range start; verified clickable and active in DayTabs.test. | P4 |
§4.1.13.2 — Сортировка (Default sort order)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.13.2-R1 | No user-triggered re-sort — only default sort is applied | 4.1.13.2 ¶1 | all | sortFlights.ts |
Done 8b0d559 |
No sort controls rendered; default sort only; 18 unit tests. | P4 |
| 4.1.13.2-R2 | Default sort for "Номер рейса" mode: ascending by departure date | 4.1.13.2 ¶2 | all | sortFlights.ts |
Done 8b0d559 |
Flight-number mode sorts by scheduled departure time ascending. | P4 |
| 4.1.13.2-R3 | Default sort for "Маршрут" mode: by segment departure time, ordering yesterday < today < tomorrow | 4.1.13.2 ¶3 | all | sortFlights.ts |
Done 8b0d559 |
Day ordering emerges naturally from absolute ISO timestamps; no bespoke bucketing. | P4 |
| 4.1.13.2-R4 | For "Маршрут" mode multi-segment: sort by the departure time of the segment that matched the search | 4.1.13.2 ¶3 | all | sortFlights.ts |
Done 8b0d559 |
Matched-segment departure used as sort key for multi-leg. | P4 |
| 4.1.13.2-R5 | Default sort for "Вылет" mode: same as "Маршрут" (by segment departure time, yesterday < today < tomorrow, matched-segment for multi-segment) | 4.1.13.2 ¶4 | all | sortFlights.ts |
Done 8b0d559 |
Departure-only mode sort verified by 18 unit tests. | P4 |
| 4.1.13.2-R6 | Default sort for "Прилет" mode: by segment arrival time, ordering yesterday < today < tomorrow (matched-segment for multi-segment) | 4.1.13.2 ¶5 | all | sortFlights.ts |
Done 8b0d559 |
Arrival mode sorts by last-leg arrival time; tested in sortFlights.test. | P4 |
| 4.1.13.2-R7 | Sort takes into account all three time variants: scheduled, estimated, actual — uses whichever is currently relevant | 4.1.13.2 ¶1 | all | sortFlights.ts |
Done 8b0d559 |
Sort uses actual/estimated when available; falls back to scheduled; missing timestamp pushed to end. | P4 |
§4.1.13.3 — Свернутое представление (Collapsed row)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.13.3-R1 | Flight number displayed as SU XXXX (4-digit format) |
4.1.13.3 Table 23 row 1 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Flight-number format locked in FlightCard.test Table 23 row 1 assertion. | P4 |
| 4.1.13.3-R2 | Carrier icon: full (non-mini, non-round) airline logo for direct flight (Table 23) | 4.1.13.3 Table 23 row 2 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Full logo (non-round) for direct flight verified in FlightCard.test. | P4 |
| 4.1.13.3-R3 | Departure time: show the most current of scheduled / estimated / actual | 4.1.13.3 Table 23 row 3 | all | FlightCard.tsx, TimeGroup.tsx |
Implemented 3b5ae9a |
Time priority (actual > estimated > scheduled) verified by FlightCard.test Table 23 row 3. | P4 |
| 4.1.13.3-R4 | When departure time was changed: show the current (actual/estimated) time normally, and the superseded time (scheduled or estimated) struck-through in small font below | 4.1.13.3 Table 23 row 3 | all | TimeGroup.tsx |
Implemented 3b5ae9a |
Strikethrough of superseded time verified in FlightCard.test. | P4 |
| 4.1.13.3-R5 | Departure day-change badge ±X shown if flight crosses midnight; tooltip on hover shows «день» for ±1, else DD.MM.YYYY of the relevant date; no tooltip on mobile |
4.1.13.3 Table 23 row 4 | all | DayChangeBadge/ |
Implemented 3b5ae9a |
Badge + tooltip content locked in FlightCard.test; consistent with §4.1.17. | P4 |
| 4.1.13.3-R6 | Departure city name shown | 4.1.13.3 Table 23 row 5 | all | FlightCard.tsx |
Implemented 3b5ae9a |
City field rendered; verified by FlightCard.test. | P4 |
| 4.1.13.3-R7 | Departure airport name shown if available; Шереметьево / Внуково rendered as clickable link opening in new browser tab | 4.1.13.3 Table 23 row 6 | all | FlightCard.tsx |
TBD (P5) | Airport-as-link for SVO/VKO deferred; airport name display verified but link not implemented. | P4 |
| 4.1.13.3-R8 | Departure terminal code shown if available | 4.1.13.3 Table 23 row 7 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Terminal conditional display verified in FlightCard.test. | P4 |
| 4.1.13.3-R9 | Flight status chip shown with icon + text; for multi-segment flight shows current executing segment status, switching at end of prior segment deboarding time (Appendix 2 rules) | 4.1.13.3 Table 23 row 8 | all | FlightCard.tsx |
Partial 3b5ae9a |
Status chip icon+text verified. Multi-segment status-switching logic (Appendix 2 deboarding-time threshold) not yet implemented; deferred to P5. | P4 |
| 4.1.13.3-R10 | Arrival time: show the most current of scheduled / estimated / actual | 4.1.13.3 Table 23 row 9 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Arrival time priority verified in FlightCard.test. | P4 |
| 4.1.13.3-R11 | When arrival time was changed: show actual/estimated time normally, superseded time struck-through in small font | 4.1.13.3 Table 23 row 9 | all | FlightCard.tsx, TimeGroup.tsx |
Implemented 3b5ae9a |
Strikethrough on changed arrival time verified. | P4 |
| 4.1.13.3-R12 | Arrival day-change badge ±X with same tooltip rules as departure |
4.1.13.3 Table 23 row 10 | all | DayChangeBadge/ |
Implemented 3b5ae9a |
Arrival day-change badge locked in FlightCard.test. | P4 |
| 4.1.13.3-R13 | Arrival city name shown | 4.1.13.3 Table 23 row 11 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Arrival city field verified. | P4 |
| 4.1.13.3-R14 | Arrival airport name shown if available; Шереметьево / Внуково as link opening new tab | 4.1.13.3 Table 23 row 12 | all | FlightCard.tsx |
TBD (P5) | Airport-as-link deferred; airport name displayed but SVO/VKO link not implemented. | P4 |
| 4.1.13.3-R15 | Arrival terminal code shown if available | 4.1.13.3 Table 23 row 13 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Arrival terminal conditional display verified. | P4 |
| 4.1.13.3-R16 | Expand/collapse toggle element (arrow icon) shown on every row | 4.1.13.3 Table 23 row 14 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Toggle arrow present; verified in FlightCard.test. | P4 |
| 4.1.13.3-R17 | Multi-segment / connecting flight: full airline logo (non-mini) shown in collapsed row (Table 24) | 4.1.13.3 Table 24 row 2 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Full logo for multi-seg collapsed verified in FlightCard.test Table 24 assertions. | P4 |
| 4.1.13.3-R18 | Multi-segment collapsed: from = city/airport/terminal of first segment departure; to = city/airport/terminal of last executing segment arrival | 4.1.13.3 Table 24 rows 5–13 | all | FlightCard.tsx |
Implemented 3b5ae9a |
First-dep/last-arr for multi-seg collapsed verified in FlightCard.test. | P4 |
| 4.1.13.3-R19 | Route-change icon shown if flight route was altered (icon «Измен маршрут») | 4.1.13.3 Table 24 row 15 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Route-change icon conditional render verified. | P4 |
| 4.1.13.3-R20 | Return-to-origin icon shown if flight returned to departure airport; route-change icon also shown in this case | 4.1.13.3 Table 24 row 16 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Return-to-origin icon + co-shown route-change verified in FlightCard.test. | P4 |
| 4.1.13.3-R21 | Intermediate-landing badge shown between segments; if single landing: city + airport + terminal + icon; if 2+ landings: count + icon + «Смена терминала»/«Смена аэропорта» flags | 4.1.13.3 Table 24 row 17 + §4.1.13.3.2 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Single vs multi-stop badge content verified in FlightCard.test. | P4 |
| 4.1.13.3-R22 | Intermediate-landing badge variant type 1 (no stop badge): same city + same airport + same terminal (or one terminal missing) | 4.1.13.3.2 rules | all | FlightCard.tsx |
Implemented 3b5ae9a |
Badge type 1 conditions verified. | P4 |
| 4.1.13.3-R23 | Intermediate-landing badge variant type 2 (city-change): city of prev segment arrival ≠ city of next segment departure | 4.1.13.3.2 rules | all | FlightCard.tsx |
Implemented 3b5ae9a |
Badge type 2 (city change) verified. | P4 |
| 4.1.13.3-R24 | Intermediate-landing badge variant type 3 (terminal change): same city + same airport + different terminals | 4.1.13.3.2 rules | all | FlightCard.tsx |
Implemented 3b5ae9a |
Badge type 3 (terminal change) verified. | P4 |
| 4.1.13.3-R25 | Intermediate-landing badge variant type 4 (airport change): same city + different airport | 4.1.13.3.2 rules | all | FlightCard.tsx |
Implemented 3b5ae9a |
Badge type 4 (airport change) verified. | P4 |
| 4.1.13.3-R26 | When comparing airports for badge selection, use current available data for prev-segment arrival and next-segment departure (scheduled and actual both considered) | 4.1.13.3.2 rules | all | FlightCard.tsx |
Implemented 3b5ae9a |
Airport comparison uses both scheduled and actual data; verified in FlightCard.test. | P4 |
| 4.1.13.3-R27 | If a planned multi-segment flight changes to a direct (cancelled segment), cancelled segment is hidden, row renders as direct flight with route-change icon | 4.1.13.3 ¶ after Table 24 | all | FlightCard.tsx |
Implemented 3b5ae9a |
Multi→direct change rendering verified; route-change icon shown. | P4 |
§4.1.13.4 — Развернутое представление (Expanded row)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.13.4-R1 | Expanded row structure for direct flight (Table 26): flight-number header + departure block + status block + arrival block + operation-blocks (registration/boarding/deboarding) + action-buttons area | 4.1.13.4 Table 26 | all | FlightCard.tsx |
Implemented 9f66237 |
Expanded layout structure verified in FlightCard.test (16 assertion tests). | P4 |
| 4.1.13.4-R2 | Per Table 26 row 18: operation blocks (Регистрация / Посадка / Высадка) shown in order Регистрация → Посадка → Высадка | 4.1.13.4 §4.1.13.4.3 | all | FlightCard.tsx |
Implemented 9f66237 |
Block ordering Рег → Посадка → Высадка verified. | P4 |
| 4.1.13.4-R3 | Flight time display (Table 27): block-departure time and block-arrival time are each shown as scheduled / estimated / actual depending on flight status; superseded times struck-through in small font | 4.1.13.4 Table 27 | all | FlightCard.tsx |
Implemented 9f66237 |
Time-block algorithm per Table 27 verified; strikethrough tested. | P4 |
| 4.1.13.4-R4 | Each time block includes UTC offset label HH:MM UTC±HH:MM and day-change badge ±X; day-change badge has hover tooltip showing «День» for ±1, else DD.MM.YYYY; no tooltip on mobile |
4.1.13.4 ¶ after Table 27 | all | FlightCard.tsx |
Implemented 9f66237 |
UTC offset + day-change tooltip in expanded verified. | P4 |
| 4.1.13.4-R5 | «Регистрация» block shown when registration has started and not yet closed; for SVO uses actual data with statuses Ожидается/Идет/Закончена; for other airports uses calculated statuses with «Уточняется» | 4.1.13.4 §4.1.13.4.3 Table 28 | all | FlightCard.tsx |
Implemented 9f66237 |
Registration block show/hide and status logic verified in FlightCard.test. | P4 |
| 4.1.13.4-R6 | «Регистрация» block timing: show when Y - X ≤ 24h and Y - X > min-check-in-time; block disappears when Y - X ≤ min-check-in-time |
4.1.13.4 Table 28 | all | FlightCard.tsx |
Partial 9f66237 |
Timing window implemented; check-in counter number deferred — API type has checkingStatus string but no counter-number field; needs backend extension (backlog). |
P4 |
| 4.1.13.4-R7 | For delayed flights, registration block shows «Уточняется / Идет» when delay > 15 min; end-time uses expected departure minus min-check-in + delay offset |
4.1.13.4 Table 28 delayed rows | all | FlightCard.tsx |
Implemented 9f66237 |
Delayed-flight reg block behavior verified. | P4 |
| 4.1.13.4-R8 | «Посадка» block: starts ~40 min before departure, boarding "ongoing" for 20 min window, "finished" until departure; SVO uses actual data, others use «Уточняется» when expected data not received | 4.1.13.4 Table 29 | all | FlightCard.tsx |
Done 9f66237 |
Gate number (departure.gate) + boarding-type (departure.dispatch) added; boarding block timing tested. |
P4 |
| 4.1.13.4-R9 | «Высадка» block: shown when flight has landed and deboarding is active; closed after 1h past actual arrival for SVO; uses «Уточняется» status for 30 min when only «Прибыл» status received without actual data | 4.1.13.4 Table 30 | all | FlightCard.tsx |
Done 9f66237 |
Baggage belt (arrival.bagBelt) added as conditional field; deboarding block logic tested. |
P4 |
| 4.1.13.4-R10 | Registration block shows: start time (HH:MM) + end time (HH:MM); boarding block shows: start time + end time + gate number (if received) + boarding-type (ramp/bus, if received) | 4.1.13.4 Table 28-29 attr cols | all | FlightCard.tsx |
Done 9f66237 |
Gate, ramp/bus (dispatch), start, end all added and tested. | P4 |
| 4.1.13.4-R11 | Action area: «Поделиться» (share) icon shown; share opens VK/other social networks + copy-link; China locale also shows Weibo | 4.1.13.4 §4.1.13.4.5 | all | SharePanel/ |
Implemented 9f66237 |
Share button + panel verified in FlightCard.test. | P4 |
| 4.1.13.4-R12 | Action area: «Купить» button available when departure is > 2h away (by UTC) and flight is not cancelled | 4.1.13.4 §4.1.13.4.6 | all | FlightCard.tsx |
Implemented 9f66237 |
Buy button visibility rule verified (>2h UTC, not cancelled). | P4 |
| 4.1.13.4-R13 | «Купить» for multi-segment: single button for whole flight; availability calculated from first segment departure | 4.1.13.4 §4.1.13.4.6 | all | FlightCard.tsx |
Implemented 9f66237 |
Single Buy button for multi-seg uses first-seg departure time. | P4 |
| 4.1.13.4-R14 | «Купить» not shown for cancelled flights | 4.1.13.4 §4.1.13.4.6 | all | FlightCard.tsx |
Implemented 9f66237 |
Buy hidden for cancelled verified in FlightCard.test. | P4 |
| 4.1.13.4-R15 | «Купить» click opens SB search page in new browser tab with route params (route, cabin=economy, adults=1, autosearch=Y) |
4.1.13.4 §4.1.13.4.6 Table 31 | all | FlightCard.tsx |
Implemented 9f66237 |
SB URL params (Table 31 format) verified. | P4 |
| 4.1.13.4-R16 | «Онлайн-Регистрация» button shown when departure > min-check-in time away and flight not cancelled; for Россия airline links to Россия check-in page | 4.1.13.4 §4.1.13.4.7 | all | OnlineCheckInButton/ |
TBD (P5) | Online check-in button deferred; aircraft tail number display (aircraft.registration) also deferred to details-page parity task. | P4 |
| 4.1.13.4-R17 | For multi-segment expanded: per-segment breakdown rendered; intermediate-landing badge between segments (same badge logic as collapsed §4.1.13.3.2) | 4.1.13.4 Table 26 multi-seg variant | all | FlightCard.tsx |
Implemented 9f66237 |
Per-segment layout in expanded multi-seg verified; codeshare chips per-segment deferred (currently merged into header via _childFlightIds). | P4 |
| 4.1.13.4-R18 | «Детали рейса» button in expanded row opens flight details page (§4.1.15) | 4.1.13.4 §4.1.13.4.8 | all | FlightCard.tsx |
Implemented 9f66237 |
Details link navigates to §4.1.15 page; tested in FlightCard.test. | P4 |
4.1.14 — Список результатов поиска рейсов Расписания
Schedule results list: week tabs (4.1.14.1), sort (4.1.14.2), collapsed (4.1.14.3), expanded (4.1.14.4). Largest subsection by page count (~100 pages in TZ). Target rule count: 150–200.
Covers the full weekly results list shown after executing a Schedule search. Results are shown per week, grouped by day within the week. Active date range: [-1 day, +330 days] from today. No pagination — scroll within expanded day groups. Desktop/tablet have sticky week-tabs + search-direction header + column header; mobile has no sticky elements.
§4.1.14 — opening + structure (R1–R24)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.14-R1 | Results displayed per week; week is split into days; only days within [-1, +330] window are shown |
4.1.14 ¶1 | all | ScheduleSearchPage.tsx, DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Per-week grouping with day-level expansion pre-existing; locked in DayGroupedFlightList.test. | P4 |
| 4.1.14-R2 | No pagination — scroll within expanded day groups; infinite vertical scroll | 4.1.14 ¶2 | all | — | Implemented | No pagination component in Schedule results; verified by codebase inspection. | P4 |
| 4.1.14-R3 | Desktop/tablet layout (Table 33): left = subsystem switcher + filter + «Вы искали»; right = breadcrumbs + page title + week-tabs + search-direction + column-header + flight list | 4.1.14 Table 33 | desktop, tablet | ScheduleSearchPage.tsx |
Implemented | Two-column layout pre-existing; consistent with §4.1.13-R7 PageLayout pattern. | P4 |
| 4.1.14-R4 | Mobile layout (Table 33): stacked — breadcrumbs → page title → subsystem switcher → filter → «Вы искали» → week-list → search-direction → flight list | 4.1.14 Table 33 | mobile | ScheduleSearchPage.tsx |
Implemented | Single-column stacking pre-existing; matches PageLayout mobile pattern. | P4 |
| 4.1.14-R5 | «Направление поиска» (search-direction toggle) shown only when «Показать обратные рейсы» was checked; toggles between «Рейсы туда» and «Рейсы обратно» result lists | 4.1.14 Table 34 row 6 | all | SearchDirectionToggle/ |
Implemented | Direction toggle visibility + switching pre-existing; locked in 6f67c06 tests. |
P4 |
| 4.1.14-R6 | Column header (Шапочка списка рейсов, Table 34 row 7): shows columns «Рейс», «Авиакомпания, борт», «Вылет», «Время в пути», «Прилет»; «Вылет» and «Прилет» columns have asterisk footnote | 4.1.14 Table 34 row 7 | desktop, tablet | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Column header with footnote asterisks verified in DayGroupedFlightList.test. | P4 |
| 4.1.14-R7 | Footnote at bottom of list: «* Время в Системе - МЕСТНОЕ» | 4.1.14 Table 34 row 7 | all | ScheduleSearchPage.tsx |
Implemented 6f67c06 |
Footnote text rendered below list; verified in DayGroupedFlightList.test. | P4 |
| 4.1.14-R8 | Each day in the results list can be collapsed/expanded independently | 4.1.14 ¶ after Table 34 | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Day-group accordion independently collapsible; tested. | P4 |
| 4.1.14-R9 | Each flight within a day can be collapsed/expanded; only one flight per day is expanded at a time; expanding new flight auto-collapses the previously expanded one | 4.1.14 ¶ after Table 34 | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Single-expanded-at-a-time per day verified in DayGroupedFlightList.test. | P4 |
| 4.1.14-R10 | On load, only active days within [-1, +330] are shown (inactive days hidden) |
4.1.14 ¶ results behavior | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Inactive day filtering verified; active window uses scheduleWindowBounds(). | P4 |
| 4.1.14-R11 | If search was on the current week, the current day of week is expanded on load | 4.1.14 ¶ results behavior | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Today's day-group auto-expanded on current-week search; tested. | P4 |
| 4.1.14-R12 | If only one active day remains in the search week (e.g. Sunday), that day is auto-expanded | 4.1.14 ¶ results behavior | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Last-day-of-week auto-expand verified. | P4 |
| 4.1.14-R13 | If search was on a future week, the first day of that week is auto-expanded | 4.1.14 ¶ results behavior | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
First-day auto-expand for future week verified in DayGroupedFlightList.test. | P4 |
| 4.1.14-R14 | On desktop/tablet: week-tabs, search-direction header, and column header are sticky at top during scroll | 4.1.14 Table 35 | desktop, tablet | PageLayout.tsx |
Implemented f6def71 |
Sticky for week-tabs + direction + column header verified; PageLayout.test covers sticky wrappers. | P4 |
| 4.1.14-R15 | On mobile: no elements are sticky (all scroll with page) | 4.1.14 Table 35 | mobile | PageLayout.tsx |
Implemented f6def71 |
No sticky on mobile schedule results; confirmed by PageLayout.test. | P4 |
| 4.1.14-R16 | Scroll-up button (icon) fixed in bottom-right; appears when breadcrumbs + page title + subsystem tabs scroll out of viewport (desktop/tablet); on mobile also filter + week-list must scroll out | 4.1.14 ¶ «Кнопка Вверх» + Table 35 | all | ScrollUpButton.tsx |
Implemented f6def71 |
Scroll-up button trigger verified (same component as OB); 300px threshold tested. | P4 |
| 4.1.14-R17 | Clicking scroll-up button scrolls page back to breadcrumbs visible, button then disappears | 4.1.14 ¶ «Кнопка Вверх» | all | ScrollUpButton.tsx |
Implemented f6def71 |
Scroll-up click behavior verified in ScrollUpButton.test. | P4 |
| 4.1.14-R18 | Scroll-up button has no hover/active color change | 4.1.14 ¶ «Кнопка Вверх» | all | ScrollUpButton.tsx |
Implemented f6def71 |
No hover style on scroll-up confirmed. | P4 |
| 4.1.14-R19 | When «Показать обратные рейсы» is active, both outbound and return results share the same week-tab set; week-tab validation applies calendar rules from §4.1.9.4 | 4.1.14.1 ¶ (round-trip) | all | WeekTabs/ |
Implemented 6f67c06 |
Round-trip week-tab validation cross-check pre-existing; verified in WeekTabs.test. | P4 |
| 4.1.14-R20 | Round-trip week-tabs apply the same validation to each direction independently (Figures 19-24) | 4.1.14.1 ¶ Figures 19-24 | all | WeekTabs/ |
Implemented 6f67c06 |
Per-direction tab blocking per mockup Figs 19-24 verified. | P4 |
| 4.1.14-R21 | Filter is sticky (left column) during scroll on desktop/tablet | 4.1.14 Table 35 | desktop, tablet | PageLayout.tsx |
Implemented f6def71 |
Filter sticky alongside week-tabs confirmed; PageLayout.test overlay assertions. | P4 |
| 4.1.14-R22 | Subsystem switcher tooltips: «Онлайн-Табло» button = «Информация о фактическом выполнении рейсов в ближайшие дни»; desktop only | 4.1.14 Table 34 row 1 | desktop | SubsystemSwitcher/ |
Implemented | Tooltip text matches TZ (confirmed by C6 resolution 53b5359); shared component. |
P4 |
| 4.1.14-R23 | «Расписание» button tooltip: «Информация о планируемом выполнении рейсов на ближайший год»; desktop only | 4.1.14 Table 34 row 1 | desktop | SubsystemSwitcher/ |
Implemented | Schedule button tooltip text confirmed matches TZ pre-P4. | P4 |
| 4.1.14-R24 | «Карта полетов» button tooltip: «Информация о карте полетов»; desktop only | 4.1.14 Table 34 row 1 | desktop | SubsystemSwitcher/ |
Implemented | Map button tooltip confirmed matches TZ pre-P4. | P4 |
§4.1.14.1 — Поведение Табов-недель (Week-tabs behavior)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.14.1-R1 | Week-tabs paginate in groups of 7 weeks | 4.1.14.1 ¶1 | desktop, tablet | WeekTabs/ |
Done 6f67c06 |
7-per-page week grouping verified in WeekTabs.test. | P4 |
| 4.1.14.1-R2 | One week tab = 7 calendar days (Mon–Sun); inactive days (outside [-1, +330]) within a week are hidden but the week tab itself remains active if it contains at least one active day |
4.1.14.1 ¶2 | all | WeekTabs/ |
Done 6f67c06 |
Partial-week handling verified; tab active but out-of-range days hidden. | P4 |
| 4.1.14.1-R3 | Active week-tabs: from the week containing -1 day up to the week containing +330 days from today |
4.1.14.1 ¶3 | all | WeekTabs/ |
Done 6f67c06 |
Fixed active range from hardcoded WEEKS_AFTER=30 (≈210 days) to scheduleWindowBounds() [-1,+330 days]; WeekTabs.test verifies. |
P4 |
| 4.1.14.1-R4 | Pagination starts from the week containing -1 day (same as current week start) |
4.1.14.1 ¶4 | desktop, tablet | WeekTabs/ |
Done 6f67c06 |
First page starts at week of -1 day; verified in WeekTabs.test. | P4 |
| 4.1.14.1-R5 | If the last active week-tab is not the last in a 7-slot page, remaining slots are filled with inactive (non-clickable) week-tabs to complete the 7; right-arrow paging then disabled | 4.1.14.1 ¶5 | desktop, tablet | WeekTabs/ |
Done 6f67c06 |
Inactive padding + disabled right-arrow added; WeekTabs.test verifies. | P4 |
| 4.1.14.1-R6 | The user-requested week tab is highlighted (active style) and auto-scrolled into view | 4.1.14.1 ¶6 | all | WeekTabs/ |
Done 6f67c06 |
Auto-scroll via useEffect on selectedMonday prop change; requested-week highlight tested. |
P4 |
| 4.1.14.1-R7 | Clicking a week-tab triggers search for that week using current filter values | 4.1.14.1 ¶7 | all | WeekTabs/ |
Implemented | Search re-executes on week-tab click pre-existing; locked in WeekTabs.test. | P4 |
| 4.1.14.1-R8 | When switching week-tabs, results list is re-fetched for the selected week | 4.1.14.1 ¶8 | all | WeekTabs/ |
Implemented | API call on week change pre-existing; verified by WeekTabs.test. | P4 |
| 4.1.14.1-R9 | On mobile, week-tabs are replaced by a scrollable week-list with equivalent behavior | 4.1.14.1 ¶9 | mobile | WeekList/ |
Implemented | Week-list on mobile pre-existing; active range now matches [-1,+330]. | P4 |
| 4.1.14.1-R10 | If the last active week is only a partial week (e.g. only Sunday at day +330), that week-tab is still active but only that one valid day is shown within it | 4.1.14.1 ¶2 | all | WeekTabs/ |
Done 6f67c06 |
Partial last-week handling verified in WeekTabs.test. | P4 |
| 4.1.14.1-R11 | When new week-tab is clicked, sort resets to default (departure time ascending, 00:00–23:59) | 4.1.14.2 ¶ last | all | ScheduleSearchPage.tsx |
Implemented 6f67c06 |
Sort reset on week-tab switch verified in DayGroupedFlightList.test. | P4 |
§4.1.14.2 — Сортировка (Sort)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.14.2-R1 | Default sort: by departure time ascending (00:00 → 23:59) | 4.1.14.2 ¶1 | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Default departure-ascending sort pre-existing; locked in DayGroupedFlightList.test. | P4 |
| 4.1.14.2-R2 | For multi-segment flights: sort by the searched segment's departure time | 4.1.14.2 ¶2 | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Multi-seg uses matched-segment departure for sort; verified. | P4 |
| 4.1.14.2-R3 | For connecting flights (стыковочные): sort by the first segment's departure time | 4.1.14.2 ¶3 | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Connecting sort by first-segment departure verified. | P4 |
| 4.1.14.2-R4 | User can re-sort by: «Вылет» (departure time), «Время в пути» (duration), «Прилет» (arrival time) | 4.1.14.2 ¶4 | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Three sort columns clickable; verified in DayGroupedFlightList.test. | P4 |
| 4.1.14.2-R5 | «Вылет» user-sort: ascending/descending departure time, with ordering yesterday < today < tomorrow | 4.1.14.2 ¶5 | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Departure user-sort direction toggle + day ordering verified. | P4 |
| 4.1.14.2-R6 | «Прилет» user-sort: ascending/descending arrival time, with ordering yesterday < today < tomorrow | 4.1.14.2 ¶6 | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Arrival user-sort direction toggle + day ordering verified. | P4 |
| 4.1.14.2-R7 | «Время в пути» user-sort: ascending/descending total flight duration | 4.1.14.2 ¶7 | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Duration sort direction toggle verified. | P4 |
| 4.1.14.2-R8 | Sort is applied per expanded day-group; when next day-group is expanded it inherits the sort that was applied previously | 4.1.14.2 ¶8 | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Sort persistence across day-groups within same week verified. | P4 |
| 4.1.14.2-R9 | Sort (user re-sort) applies to the start and end point of the searched route (direct/connecting) or segment (multi-segment) | 4.1.14.2 ¶4 | all | DayGroupedFlightList.tsx |
Implemented 6f67c06 |
Sort applies to correct route endpoints; verified. | P4 |
§4.1.14.3 — Свернутое представление (Collapsed row)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.14.3-R1 | Collapsed rows for outbound and return directions have identical element structure | 4.1.14.3 ¶1 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Same component used for both directions; verified in DayGroupedFlightList.test. | P4 |
| 4.1.14.3-R2 | Direct flight collapsed (Table 36): flight number SU XXXX (4-digit) |
4.1.14.3 Table 36 row 1 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Schedule flight number format locked in DayGroupedFlightList.test Table 36 row 1. | P4 |
| 4.1.14.3-R3 | Direct flight: mini (round) airline icon; if no icon available, show empty space (not placeholder) | 4.1.14.3 Table 36 row 2 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Mini-round logo verified; empty space when missing tested. | P4 |
| 4.1.14.3-R4 | Direct flight: departure time = scheduled time (schedule only; no estimated/actual override in collapsed) | 4.1.14.3 Table 36 row 3 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Departure shows scheduled only in schedule collapsed; verified. | P4 |
| 4.1.14.3-R5 | Departure day-change badge ±X with hover tooltip (hover = «день» for ±1, else DD.MM.YYYY; no tooltip on mobile) |
4.1.14.3 Table 36 row 4 | all | DayChangeBadge/ |
Implemented 6f67c06 |
Day-change badge on schedule departure verified in DayGroupedFlightList.test. | P4 |
| 4.1.14.3-R6 | Departure city name shown | 4.1.14.3 Table 36 row 5 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Departure city rendered; verified. | P4 |
| 4.1.14.3-R7 | Departure airport shown if data received; Шереметьево/Внуково as clickable link opening new tab | 4.1.14.3 Table 36 row 6 | all | ScheduleFlightRow/ |
TBD (P5) | Airport-as-link for SVO/VKO deferred; airport name display verified but link not implemented. | P4 |
| 4.1.14.3-R8 | Departure terminal shown if data received; hidden if not | 4.1.14.3 Table 36 row 7 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Terminal conditional display verified. | P4 |
| 4.1.14.3-R9 | Duration shown as icon + formatted time: {MM}мин. / {HH}ч. {MM}мин. / {D}д. {MM}мин. / {D}д. {HH}ч. {MM}мин. |
4.1.14.3 Table 36 row 8 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Duration format verified in DayGroupedFlightList.test. | P4 |
| 4.1.14.3-R10 | Duration = sum of all segment durations + all transfer/layover durations | 4.1.14.3 Table 36 row 8 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Duration calculation includes transfer time; verified. | P4 |
| 4.1.14.3-R11 | Arrival time = scheduled | 4.1.14.3 Table 36 row 9 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Arrival shows scheduled only; verified. | P4 |
| 4.1.14.3-R12 | Arrival day-change badge ±X with same hover tooltip rules |
4.1.14.3 Table 36 row 10 | all | DayChangeBadge/ |
Implemented 6f67c06 |
Arrival day-change badge locked in DayGroupedFlightList.test. | P4 |
| 4.1.14.3-R13 | Arrival city name shown | 4.1.14.3 Table 36 row 11 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Arrival city verified. | P4 |
| 4.1.14.3-R14 | Arrival airport shown if data received; Шереметьево/Внуково as link | 4.1.14.3 Table 36 row 12 | all | ScheduleFlightRow/ |
TBD (P5) | Airport-as-link deferred (same as R7); airport name verified. | P4 |
| 4.1.14.3-R15 | Arrival terminal shown if data received; hidden if not | 4.1.14.3 Table 36 row 13 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Arrival terminal conditional verified. | P4 |
| 4.1.14.3-R16 | Expand/collapse toggle arrow shown on every row | 4.1.14.3 Table 36 row 14 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Toggle arrow rendered; verified in DayGroupedFlightList.test. | P4 |
| 4.1.14.3-R17 | Multi-segment collapsed (Table 37): single flight number for whole flight, single mini-icon (same carrier throughout); departure = first segment, arrival = last segment | 4.1.14.3 Table 37 rows 1–14 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Multi-seg single number + single round icon (3ae59da) + first/last endpoints verified. |
P4 |
| 4.1.14.3-R18 | Multi-segment collapsed: intermediate-landing badge between segments (same badge type logic as §4.1.13.3.2 / §4.1.14.3.2) | 4.1.14.3 Table 37 row 15 | all | IntermediateLandingBadge/ |
Implemented 6f67c06 |
Intermediate-landing badge in schedule collapsed verified. | P4 |
| 4.1.14.3-R19 | Connecting flight (direct+direct, Table 38): two flight numbers displayed separated (e.g. SU XXXX - SU XXXX); two mini-icons, one per segment; if same airline, two identical icons |
4.1.14.3 Table 38 rows 1–2 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Connecting flight numbers + dual mini-icons verified in DayGroupedFlightList.test Table 38. | P4 |
| 4.1.14.3-R20 | Connecting flight: if a segment has no mini-icon, show empty space (no placeholder) | 4.1.14.3 Table 38 row 2 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Empty space when mini-icon missing verified. | P4 |
| 4.1.14.3-R21 | Connecting flight collapsed (Table 38): departure from first segment, arrival at last segment; transfer badge between segments | 4.1.14.3 Table 38 rows 3–15 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Connecting flight endpoints + transfer badge verified. | P4 |
| 4.1.14.3-R22 | Connecting+multi-segment hybrid (Table 39): flight numbers of all participating legs; mini-icons per leg; departure = first segment, arrival = last | 4.1.14.3 Table 39 | all | ScheduleFlightRow/ |
Implemented 6f67c06 |
Mixed multi-seg+connecting layout verified in DayGroupedFlightList.test Table 39. | P4 |
| 4.1.14.3-R23 | Transfer/intermediate-landing badge (§4.1.14.3.2): for connecting flights badge type = «Пересадка»; for multi-segment = «Промежуточная посадка»; badge shows city + airport + terminal + type icon | 4.1.14.3.2 | all | TransferBadge/, IntermediateLandingBadge/ |
Implemented 6f67c06 |
Correct badge type per flight type verified. | P4 |
| 4.1.14.3-R24 | For 2+ stops: badge shows stop count + icon + change-of-city/airport/terminal flags; flags shown for any stop that had the change | 4.1.14.3.2 ¶ (2+ stops) | all | TransferBadge/ |
Implemented 6f67c06 |
Multi-stop badge with count + flags verified. | P4 |
| 4.1.14.3-R25 | Badge type 1 (no-change): prev-arr city = next-dep city AND prev-arr airport = next-dep airport AND terminals same (or one terminal missing) | 4.1.14.3.2 rules | all | TransferBadge/ |
Implemented 6f67c06 |
Badge type 1 condition verified. | P4 |
| 4.1.14.3-R26 | Badge type 2 (city-change): prev-arr city ≠ next-dep city → show city-change variant | 4.1.14.3.2 rules | all | TransferBadge/ |
Implemented 6f67c06 |
Badge type 2 condition verified. | P4 |
| 4.1.14.3-R27 | Badge type 3 (terminal-change): same city + same airport + different terminals | 4.1.14.3.2 rules | all | TransferBadge/ |
Implemented 6f67c06 |
Badge type 3 condition verified. | P4 |
| 4.1.14.3-R28 | Badge type 4 (airport-change): same city + different airports | 4.1.14.3.2 rules | all | TransferBadge/ |
Implemented 6f67c06 |
Badge type 4 condition verified. | P4 |
| 4.1.14.3-R29 | Шереметьево/Внуково names in badge rendered as links opening new tab | 4.1.14.3.2 | all | TransferBadge/ |
TBD (P5) | Airport links in transfer badge deferred (same as R7/R14 airport-as-link backlog). | P4 |
| 4.1.14.3-R30 | For 2+ mixed stops (промежуточные посадки + пересадки): badge shows type «Пересадки»; flags priority order: «Смена города» > «Смена аэропорта» > «Смена терминала»; shown in occurrence order | 4.1.14.3.2 (2+ mixed) | all | TransferBadge/ |
Implemented 6f67c06 |
Mixed-stop badge flag ordering verified in DayGroupedFlightList.test. | P4 |
§4.1.14.4 — Развернутое представление (Expanded row)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.14.4-R1 | Expanded row has background color distinct from collapsed rows, plus a left-edge colored bar spanning the full expanded height | 4.1.14.4 ¶1 | all | ScheduleFlightBody.tsx, ScheduleFlightBody.scss |
Implemented 4290c81 |
Expanded row background + left bar verified in ScheduleFlightBody.test. | P4 |
| 4.1.14.4-R2 | Outbound and return direction expanded rows have identical element structure | 4.1.14.4 ¶2 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Same component/structure for both directions verified. | P4 |
| 4.1.14.4-R3 | Direct flight expanded (Table 41): header = flight number + mini-icon + departure block + duration + arrival block + toggle; action area = «Поделиться» + «Купить» + «Статус рейса» + «Детали рейса» | 4.1.14.4 Table 41 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Direct flight expanded structure verified in ScheduleFlightBody.test. | P4 |
| 4.1.14.4-R4 | Per-segment info block (in expanded direct, Table 41): segment number + full airline logo + aircraft type (if data received, shown under logo, else hidden) | 4.1.14.4 Table 41 / Table 42 per-seg rows | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Full logo + aircraft type per segment verified. | P4 |
| 4.1.14.4-R5 | Segment departure time (HH:MM) + day-change badge (with hover tooltip); departure city + airport (SVO/VKO as link) + terminal | 4.1.14.4 Table 42 per-seg rows 4–8 | all | ScheduleFlightBody.tsx |
Partial 4290c81 |
Segment departure block (time, badge, city, terminal) verified; SVO/VKO airport-as-link deferred to P5. | P4 |
| 4.1.14.4-R6 | Segment duration = arr_scheduled - dep_scheduled (schedule times used for schedule expanded) |
4.1.14.4 Table 42 per-seg row 9 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Segment duration uses scheduled times; verified. | P4 |
| 4.1.14.4-R7 | Segment arrival time (HH:MM) + day-change badge; arrival city + airport (SVO/VKO as link) + terminal | 4.1.14.4 Table 42 per-seg rows 10–14 | all | ScheduleFlightBody.tsx |
Partial 4290c81 |
Segment arrival block (time, badge, city, terminal) verified; SVO/VKO airport-as-link deferred to P5. | P4 |
| 4.1.14.4-R8 | Codeshare numbers (дополнительные номера рейса) shown if received; hidden if no data | 4.1.14.4 Table 41 row 16 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Codeshare field conditional display verified. | P4 |
| 4.1.14.4-R9 | Multi-segment expanded (Table 42): header shows single flight number + single mini-icon; then «Маршрут» (route strip) section (desktop/tablet only) + per-segment blocks | 4.1.14.4 Table 42 | desktop, tablet | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Multi-seg expanded header + route strip verified in ScheduleFlightBody.test. | P4 |
| 4.1.14.4-R10 | «Маршрут» (route strip) NOT shown on mobile | 4.1.14.4 Table 42 ¶ Маршрут | mobile | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Route strip hidden on mobile verified. | P4 |
| 4.1.14.4-R11 | Route strip content (multi-seg, Table 42 Маршрут): segment sequence: dep-time + city → [seg-num + seg-duration + day-change] → [stop-duration + city + airport + terminal] → ... → arr-time | 4.1.14.4 Table 42 Маршрут rows | desktop, tablet | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Route strip sequence elements verified. | P4 |
| 4.1.14.4-R12 | Route strip scroll: left/right scroll arrows shown when content exceeds area width (more than one intermediate stop); arrows hidden if content fits | 4.1.14.4 Table 42 Маршрут rows 1, 16 | desktop, tablet | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Route strip overflow scroll arrows verified. | P4 |
| 4.1.14.4-R13 | Intermediate-stop duration in route strip = next_dep_scheduled - prev_arr_scheduled |
4.1.14.4 Table 42 Маршрут row 11 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Stop duration calculation verified. | P4 |
| 4.1.14.4-R14 | If prev-arr city = next-dep city: show one city name; if different cities: show both cities with their airports/terminals | 4.1.14.4 Table 42 Маршрут row 12 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
City-change display in route strip verified. | P4 |
| 4.1.14.4-R15 | If prev-arr airport = next-dep airport: show one airport name; if different: show both airports (with their terminals) | 4.1.14.4 Table 42 Маршрут row 13 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Airport-change display in route strip verified. | P4 |
| 4.1.14.4-R16 | Inter-segment transfer/landing badge in expanded (§4.1.14.4.2): shows icon + type + duration + city + airport + terminal; duration = next_dep_scheduled - prev_arr_scheduled |
4.1.14.4 §4.1.14.4.2 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Transfer bar content (type, duration, city, airport, terminal) verified in ScheduleFlightBody.test. | P4 |
| 4.1.14.4-R17 | Expanded transfer badge type logic (§4.1.14.4.2) same as collapsed (type 1–4 by city/airport/terminal equality) | 4.1.14.4 §4.1.14.4.2 rules | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Expanded badge type matches collapsed type conditions; verified. | P4 |
| 4.1.14.4-R18 | Шереметьево/Внуково in expanded transfer badge rendered as link opening new tab | 4.1.14.4 §4.1.14.4.2 | all | ScheduleFlightBody.tsx |
TBD (P5) | Airport link in expanded transfer badge deferred (airport-as-link backlog). | P4 |
| 4.1.14.4-R19 | Multi-leg operator-logo is compact (round mini-icon) in multi-seg expanded header (commit 3ae59da parity) |
4.1.14.4 Table 42 row 2 | all | src/features/schedule/* |
Implemented 3ae59da |
Verified by commit 3ae59da. |
P4 |
| 4.1.14.4-R20 | Action area: «Поделиться» (share) — same social network list as §4.1.13.4.5; VK + copy-link; China locale adds Weibo | 4.1.14.4 §4.1.14.4.3 | all | SharePanel/ |
Implemented 4290c81 |
Share in schedule expanded row verified in ScheduleFlightBody.test. | P4 |
| 4.1.14.4-R21 | «Купить» button: shown when scheduled_departure_UTC > now + 2h AND scheduled_departure_UTC < now + 330 days AND flight not cancelled |
4.1.14.4 §4.1.14.4.4 | all | ScheduleFlightBody.tsx |
Done 4290c81 |
Buy gate fixed: >2h lower bound AND <330 days upper bound AND not cancelled; 25 tests cover all cases. | P4 |
| 4.1.14.4-R22 | «Купить» for multi-segment/connecting: single button; availability uses first segment departure | 4.1.14.4 §4.1.14.4.4 | all | ScheduleFlightBody.tsx |
Done 4290c81 |
Single Buy for multi-seg uses first-leg departure; tested. | P4 |
| 4.1.14.4-R23 | «Купить» not shown for cancelled flights; rule applies to Online-Board and the same flight in Schedule | 4.1.14.4 §4.1.14.4.4 | all | ScheduleFlightBody.tsx |
Done 4290c81 |
Buy hidden for cancelled; cross-subsystem consistency tested. | P4 |
| 4.1.14.4-R24 | «Статус рейса» button shown only when the departure day equals today; for multi-seg/connecting: single button, based on first-segment departure | 4.1.14.4 §4.1.14.4.5 | all | ScheduleFlightBody.tsx |
Done 4290c81 |
Status gate fixed: same-day departure UTC only; first-leg governs; tested in ScheduleFlightBody.test. | P4 |
| 4.1.14.4-R25 | «Статус рейса» click: opens Online-Board flight card in new browser tab; mini-list in that card shows only the one clicked flight | 4.1.14.4 §4.1.14.4.5 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Status click opens OB card in new tab; verified. | P4 |
| 4.1.14.4-R26 | «Статус рейса» for multi-segment: opens a separate OB card for each segment in new browser tabs (requires browser popup permission) | 4.1.14.4 §4.1.14.4.5 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Multi-seg opens multiple tabs verified. | P4 |
| 4.1.14.4-R27 | «Статус рейса» for Аврора segment: navigates to https://www.flyaurora.ru/; for Победа: https://www.pobeda.aero |
4.1.14.4 §4.1.14.4.5 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Аврора/Победа external URL navigation verified. | P4 |
| 4.1.14.4-R28 | «Статус рейса» not shown if all segments are operated by airlines other than Аэрофлот/Россия/Аврора/Победа | 4.1.14.4 §4.1.14.4.5 | all | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Status hidden for non-group carriers verified. | P4 |
| 4.1.14.4-R29 | «Статус рейса» hover tooltip: «Подробнее о фактическом выполнении рейса» (desktop only; no tooltip on mobile) | 4.1.14.4 §4.1.14.4.5 | desktop | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Status button desktop-only tooltip verified. | P4 |
| 4.1.14.4-R30 | «Детали рейса» button: opens flight details card (§4.1.16) with date-tab set to the first-segment scheduled departure date | 4.1.14.4 §4.1.14.4.6 | all | ScheduleFlightBody.tsx |
Done 4290c81 |
Details button added (§4.1.14.4.6); always visible when onStatus handler provided; opens §4.1.16 with correct date-tab. |
P4 |
| 4.1.14.4-R31 | «Мобильная версия» для кнопки «Статус рейса» в сегментах — кнопка не выводится (рис. 26) | 4.1.14.4 §4.1.14.4.5 Fig 26 | mobile | ScheduleFlightBody.tsx |
Implemented 4290c81 |
Status button suppressed in mobile per-segment view verified. | P4 |
4.1.15 — Карточка рейса, открытого из Онлайн-Табло
Flight details page entered from Online-Board.
Covers: form structure (4.1.15.1), mini-list (4.1.15.2), day tabs (4.1.15.3), direct-flight info (4.1.15.4), multi-segment info (4.1.15.5), intermediate landing (4.1.15.6), timeline-time algorithm (4.1.15.7), status rules (4.1.15.8), previous-flight algorithm (4.1.15.9), onboard meals (4.1.15.10), onboard services (4.1.15.11). TZ source lines 1927–2308.
§4.1.15.1 — Структура экранной формы (Screen form structure)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.15-R1 | Page entered via «Детали рейса» button from Online-Board expanded row | 4.1.15.1 TZ line 3 | all | OnlineBoardDetailsPage.tsx |
TBD | Verify navigation entry point. | P5 |
| 4.1.15-R2 | Flight card of current day must NOT auto-refresh; only browser refresh triggers update | 4.1.15.1 TZ line 4 | all | — | TBD | Verify no polling/auto-update on details page. | P5 |
| 4.1.15-R3 | Desktop/tablet layout: left column = «Вернуться к Онлайн-Табло» + mini-list; right column = breadcrumbs, page title, day-tabs, flight header, flight info | 4.1.15.1 Table 47 | desktop, tablet | OnlineBoardDetailsPage.tsx |
TBD | Verify two-column layout. | P5 |
| 4.1.15-R4 | Mobile layout: breadcrumbs → page title → «Вернуться к Онлайн-Табло» → day list → flight header → flight info (single column, no mini-list) | 4.1.15.1 Table 47 | mobile | OnlineBoardDetailsPage.tsx |
TBD | Verify mobile layout order. | P5 |
| 4.1.15-R5 | «Вернуться к Онлайн-Табло» navigates back to the search results with search state preserved; if search was for today, list is scrolled to the flight with departure closest to user's current time | 4.1.15.1 Table 48 row 1 | all | — | TBD | Verify back-navigation with state restoration + scroll-to. | P5 |
| 4.1.15-R6 | Flight header contains: flight number, codeshare numbers, airline icon (full, not round), route-changed icon, airport-return icon, share, buy, online check-in, last-update timestamp | 4.1.15.1 Table 48 row 5 | all | FlightSchedule/ |
TBD | Verify all header elements present. | P5 |
| 4.1.15-R7 | On scroll down: day-tabs and flight header are sticky (fixed to top); mini-list scrolls with main content (always accessible); no sticky on mobile | 4.1.15.1 Table 49 | desktop, tablet | — | TBD | Verify sticky behavior. | P5 |
| 4.1.15-R8 | Day-change badge {-X} / {+X} must appear for ALL times on the flight card where applicable (night flights, registration starting previous day, etc.) |
4.1.15.1 TZ line 52 | all | — | TBD | Verify badge appears on all time fields (not just dep/arr). | P5 |
| 4.1.15-R9 | Day-change badge tooltip on hover: shows «День» if badge is -1/+1; shows «ДД.ММ.ГГГГ» departure/arrival date if badge is ±2 or more | 4.1.15.1 TZ line 53 | desktop, tablet | — | TBD | Verify tooltip content logic. | P5 |
| 4.1.15-R10 | Day-change badge tooltip NOT shown on mobile | 4.1.15.1 TZ line 53 | mobile | — | TBD | Verify tooltip suppressed on mobile. | P5 |
§4.1.15.2 — Мини-список (Mini-list)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.15-R11 | Mini-list shows the same results set the user searched from, with minimal data fields | 4.1.15.2 TZ line 56 | desktop, tablet | FlightsMiniList/ |
TBD | Verify data source matches search context. | P5 |
| 4.1.15-R12 | Selected flight in mini-list has distinct color indicator («выбранного рейса») | 4.1.15.2 TZ line 57 | desktop, tablet | — | TBD | Verify selected-state styling. | P5 |
| 4.1.15-R13 | Mini-list is auto-scrolled to the selected flight on load | 4.1.15.2 TZ line 58 | desktop, tablet | — | TBD | Verify auto-scroll on mount. | P5 |
| 4.1.15-R14 | Mini-list sort order: departure or arrival time (scheduled/expected/actual) per search mode — same as §4.1.13.2 sort rules | 4.1.15.2 TZ line 59 | desktop, tablet | — | TBD | Verify sort order follows §4.1.13.2. | P5 |
| 4.1.15-R15 | Mini-list panel scrolls as main page scrolls (sticky panel behavior) | 4.1.15.2 TZ line 60 | desktop, tablet | — | TBD | Verify panel scroll follows page scroll. | P5 |
| 4.1.15-R16 | Clicking another flight in mini-list: color indicator moves to new flight AND opens that flight's card | 4.1.15.2 TZ line 61 | desktop, tablet | — | TBD | Verify click behavior navigates + updates selection. | P5 |
| 4.1.15-R17 | Moving focus to main flight info panel does NOT remove the color indicator from mini-list | 4.1.15.2 TZ line 61 | desktop, tablet | — | TBD | Verify indicator persists on focus change. | P5 |
| 4.1.15-R18 | Mini-list row fields: flight number, departure time, status icon, arrival time; day-change badges if applicable; departure/arrival date (one of: scheduled/expected/actual); dep city name; dep airport name (SVO/VKO as hyperlink); dep terminal code; arr city name; arr airport name (SVO/VKO as hyperlink); arr terminal code | 4.1.15.2 Table 50 | desktop, tablet | — | TBD | Verify all fields rendered per Table 50. | P5 |
| 4.1.15-R19 | SVO airport name in mini-list shown as link → https://www.svo.aero/ru/main (new tab) |
4.1.15.2 Table 50 | desktop, tablet | — | TBD | Verify SVO link. | P5 |
| 4.1.15-R20 | VKO airport name in mini-list shown as link → http://www.vnukovo.ru (new tab) |
4.1.15.2 Table 50 | desktop, tablet | — | TBD | Verify VKO link. | P5 |
| 4.1.15-R21 | After browser refresh, mini-list retains full state (same search query as when card was first opened) — guaranteed by URL encoding of search params per §4.1.2 | 4.1.15.2 TZ line 76-77 | desktop, tablet | — | TBD | Verify URL carries search params so mini-list survives refresh. | P5 |
| 4.1.15-R22 | Mini-list NOT shown on mobile | 4.1.15.2 TZ line 78 | mobile | — | TBD | Verify mini-list hidden on mobile. | P5 |
§4.1.15.3 — Поведение Табов-дней (Day-tabs behavior)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.15-R23 | Day-tabs present on details page, grouped in sets of 7, starting from -1 from today | 4.1.15.3 TZ lines 80-84 | all | BoardDetailsHeader/ |
TBD | Verify 7-tab grouping and start offset. | P5 |
| 4.1.15-R24 | Active day-tabs range: [-1 from today, +14 from today]; days outside range are inactive (grayed, non-clickable) | 4.1.15.3 TZ line 82 | all | — | TBD | Verify Online-Board date window enforcement in day-tabs. | P5 |
| 4.1.15-R25 | Day-tabs also respect which days this flight actually operates (per §4.1.16.8 execution-days algorithm); non-operating days are blocked | 4.1.15.3 TZ line 83 | all | — | TBD | Verify per-flight operating-day blocking in tabs. | P5 |
| 4.1.15-R26 | If the last active tab is not the last in the 7-slot group, remaining slots are filled but rendered inactive; right-scroll arrow is inactive | 4.1.15.3 TZ line 85 | all | — | TBD | Verify fill-to-7 and right-arrow disabled. | P5 |
| 4.1.15-R27 | The tab matching the currently open day is highlighted; page auto-scrolls to it | 4.1.15.3 TZ line 87 | all | — | TBD | Verify active-tab highlight + scroll. | P5 |
| 4.1.15-R28 | Clicking a new day-tab loads that day's card; loader shown if response takes time | 4.1.15.3 TZ line 88 | all | — | TBD | Verify navigation + loader on day-tab click. | P5 |
| 4.1.15-R29 | Mobile: day-tabs replaced by a date list (not tab chips) | 4.1.15.3 TZ line 90 | mobile | — | TBD | Verify mobile day-list replaces tab chips. | P5 |
§4.1.15.4 — Информация о прямом рейсе (Direct flight info)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.15-R30 | Flight header: flight number format SU XXXX |
4.1.15.4 Table 51 row 1 | all | FlightSchedule/ |
TBD | Verify number format. | P5 |
| 4.1.15-R31 | Flight header: codeshare numbers shown as comma-separated list, no label | 4.1.15.4 Table 51 row 2 | all | — | TBD | Verify codeshare display. | P5 |
| 4.1.15-R32 | Flight header: full airline icon (not round mini icon) | 4.1.15.4 Table 51 row 3 | all | — | TBD | Verify full icon, not round. | P5 |
| 4.1.15-R33 | Flight header: «Последнее обновление» timestamp in format ЧЧ:ММ ДД.ММ.ГГГГ |
4.1.15.4 Table 51 row 7 | all | — | TBD | Verify last-update field and format. | P5 |
| 4.1.15-R34 | Departure time: shows one of [scheduled / expected / actual]; if changed, prior time shown smaller + strikethrough | 4.1.15.4 Table 51 row 1 (Info) | all | — | TBD | Verify time priority + strikethrough on change. | P5 |
| 4.1.15-R35 | Day-change badge for departure time with tooltip rules per §4.1.15.1 | 4.1.15.4 Table 51 row 2 (Info) | all | — | TBD | Verify dep badge + tooltip. | P5 |
| 4.1.15-R36 | Departure city name displayed | 4.1.15.4 Table 51 row 3 (Info) | all | — | TBD | Verify dep city. | P5 |
| 4.1.15-R37 | Departure airport name displayed; SVO/VKO shown as hyperlink (new tab to respective site) | 4.1.15.4 Table 51 rows 4, 11 (Info) | all | — | TBD | Verify airport link for SVO/VKO. | P5 |
| 4.1.15-R38 | Departure terminal code shown if data present | 4.1.15.4 Table 51 row 5 (Info) | all | — | TBD | Verify terminal conditional display. | P5 |
| 4.1.15-R39 | Status shown as icon + text; status-change rules per Appendix 2 | 4.1.15.4 Table 51 row 6 (Info) | all | — | TBD | Verify status icon+text pair. | P5 |
| 4.1.15-R40 | Timeline: moving aircraft icon colored per status (see §4.1.15.8) | 4.1.15.4 Table 51 row 7.1 | all | — | TBD | Verify aircraft color per status on timeline. | P5 |
| 4.1.15-R41 | Timeline: «В пути» label + elapsed time per §4.1.15.7 algorithm; format {Д}д. {ЧЧ}ч. {ММ}мин. (shorter units omitted if zero) |
4.1.15.4 Table 51 row 7.2 | all | — | TBD | Verify elapsed-time calculation and format. | P5 |
| 4.1.15-R42 | Timeline: «До прилета» label + remaining time per §4.1.15.7 algorithm; same format as «В пути» | 4.1.15.4 Table 51 row 7.3 | all | — | TBD | Verify remaining-time calculation and format. | P5 |
| 4.1.15-R43 | Day-change badge for arrival time with tooltip rules per §4.1.15.1 | 4.1.15.4 Table 51 row 8 (Info) | all | — | TBD | Verify arr badge + tooltip. | P5 |
| 4.1.15-R44 | Arrival time: shows one of [scheduled / expected / actual]; if changed, prior time shown smaller + strikethrough | 4.1.15.4 Table 51 row 9 (Info) | all | — | TBD | Verify arrival time priority + strikethrough. | P5 |
| 4.1.15-R45 | Arrival city name displayed | 4.1.15.4 Table 51 row 10 (Info) | all | — | TBD | Verify arr city. | P5 |
| 4.1.15-R46 | Arrival terminal code shown if data present | 4.1.15.4 Table 51 row 12 (Info) | all | — | TBD | Verify arr terminal conditional. | P5 |
| 4.1.15-R47 | «Времена выполнения рейса» block: scheduled dep time with UTC offset, scheduled arr time with UTC offset, per §4.1.13.4.2 | 4.1.15.4 Table 51 (Времена) | all | — | TBD | Verify time-with-UTC block. | P5 |
| 4.1.15-R48 | «Времена выполнения рейса» block: each time accompanied by its date ДД.ММ.ГГГГ |
4.1.15.4 Table 51 (Времена) row 2 | all | — | TBD | Verify dates next to UTC times. | P5 |
| 4.1.15-R49 | «Времена выполнения рейса» block: footnote «* Время прилета и расстояния являются расчетными и примерными. Время может измениться в зависимости от погодных условий и загрузки аэропорта.» | 4.1.15.4 Table 51 (Времена) row 3 | all | — | TBD | Verify footnote text. | P5 |
| 4.1.15-R50 | «Детали рейса» accordion: collapsible/expandable with chevron direction change | 4.1.15.4 Table 51 (Детали) row 1 | all | — | TBD | Verify accordion expand/collapse + icon flip. | P5 |
| 4.1.15-R51 | Registration block shown as soon as registration opens; never hidden again once shown | 4.1.15.4 Table 51 (Детали) row 2.1 | all | — | TBD | Verify registration block lifecycle. | P5 |
| 4.1.15-R52 | Registration block: start time ЧЧ:ММ ДД.ММ.ГГГГ under label «Время начала» |
4.1.15.4 Table 51 (Детали) row 2.2 | all | — | TBD | Verify reg start time label + format. | P5 |
| 4.1.15-R53 | Registration block: end time ЧЧ:ММ ДД.ММ.ГГГГ under label «Время окончания» |
4.1.15.4 Table 51 (Детали) row 2.3 | all | — | TBD | Verify reg end time label + format. | P5 |
| 4.1.15-R54 | Reg block footnote «* Время в системе - МЕСТНОЕ.» shown only when reg block is the SOLE block in «Детали рейса» (boarding/deboarding not yet shown) | 4.1.15.4 Table 51 (Детали) row 2.4 | all | — | TBD | Verify footnote conditional logic. | P5 |
| 4.1.15-R55 | Boarding block shown as soon as boarding opens; never hidden once shown; footnote «* Время в системе - МЕСТНОЕ.» shown if Registration block is present | 4.1.15.4 Table 51 (Детали) rows 3.1, 3.2 | all | — | TBD | Verify boarding block lifecycle + footnote condition. | P5 |
| 4.1.15-R56 | Deboarding block shown as soon as deboarding starts; never hidden once shown; footnote if reg+boarding blocks are both present | 4.1.15.4 Table 51 (Детали) rows 4.1, 4.2 | all | — | TBD | Verify deboarding lifecycle + footnote condition. | P5 |
| 4.1.15-R57 | Aircraft block («Борт»): shown only if any aircraft data received; if data present, show whatever attributes were received | 4.1.15.4 Table 51 (Детали) row 5.1 | all | — | TBD | Verify aircraft block conditional. | P5 |
| 4.1.15-R58 | Aircraft block: «Тип ВС» rendered as a hyperlink → https://www.aeroflot.ru/ru-ru/about/plane_park (new tab) |
4.1.15.4 Table 51 (Детали) row 5.2 | all | — | TBD | Verify aircraft-type link. | P5 |
| 4.1.15-R59 | Aircraft block: seat counts — «Количество мест», «Эконом», «Комфорт», «Бизнес» | 4.1.15.4 Table 51 (Детали) rows 5.3–5.6 | all | — | TBD | Verify seat-count fields. | P5 |
| 4.1.15-R60 | Aircraft block: «Название» (aircraft name/registration) | 4.1.15.4 Table 51 (Детали) row 5.7 | all | — | TBD | Verify aircraft name field. | P5 |
| 4.1.15-R61 | Aircraft block: «Предыдущий рейс» link to previous flight card (new tab); calculated per §4.1.15.9 | 4.1.15.4 Table 51 (Детали) row 5.8 | all | — | TBD | Verify previous-flight link + new tab. | P5 |
| 4.1.15-R62 | For -1 day flights: reg/boarding/deboarding blocks all shown with all attributes | 4.1.15.4 TZ line 153 | all | — | TBD | Verify -1 day flight shows all three blocks. | P5 |
| 4.1.15-R63 | For today's flights: blocks appear progressively per §4.1.13.4.3 algorithm; shown but not hidden once visible; hidden if data not yet received | 4.1.15.4 TZ line 154 | all | — | TBD | Verify progressive block appearance for today. | P5 |
| 4.1.15-R64 | For +1 day flights: same progressive algorithm as today (per §4.1.13.4.3); no block pre-shown | 4.1.15.4 TZ line 155 | all | — | TBD | Verify future-day block behavior. | P5 |
| 4.1.15-R65 | «Расписание рейса» accordion block: collapsible; fields = scheduled dep UTC±offset, scheduled arr UTC±offset, «Время в пути», days-of-week, footnote | 4.1.15.4 Table 51 (Расписание) | all | — | TBD | Verify schedule accordion and all fields. | P5 |
§4.1.15.5 — Информация о многосегментном рейсе (Multi-segment flight info)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.15-R66 | Multi-segment = single flight number, same airline on all legs | 4.1.15.5 TZ line 158 | all | FullRouteTimeline/ |
TBD | Verify definition applied to routing. | P5 |
| 4.1.15-R67 | Header «Маршрут» strip shown on desktop/tablet; hidden on mobile | 4.1.15.5 Table 52 (Маршрут header) | desktop, tablet | — | TBD | Verify route strip visibility. | P5 |
| 4.1.15-R68 | Route strip: left/right scroll arrows shown if more than one intermediate stop; hidden if all fits | 4.1.15.5 Table 52 rows 1, 16 | desktop, tablet | — | TBD | Verify route scroll arrows. | P5 |
| 4.1.15-R69 | Route strip: first-segment departure time (one of scheduled/expected/actual); if changed, old time strikethrough + smaller | 4.1.15.5 Table 52 row 2 | desktop, tablet | — | TBD | Verify route strip dep time. | P5 |
| 4.1.15-R70 | Route strip: segment-level day-change badges with tooltip | 4.1.15.5 Table 52 rows 3, 9 | desktop, tablet | — | TBD | Verify per-segment day-change on route strip. | P5 |
| 4.1.15-R71 | Route strip: segment index N=(n+1) displayed per segment | 4.1.15.5 Table 52 row 7 | desktop, tablet | — | TBD | Verify segment ordinal numbers. | P5 |
| 4.1.15-R72 | Route strip: segment duration = actual arrival − actual departure (using best available time per position) | 4.1.15.5 Table 52 row 8 | desktop, tablet | — | TBD | Verify segment duration calculation. | P5 |
| 4.1.15-R73 | Route strip: intermediate stop city — if dep.prev == arr.next same city shown once; if changed (route-change event) new city shown, old city strikethrough | 4.1.15.5 Table 52 row 12 | desktop, tablet | — | TBD | Verify intermediate-city display and route-change strikethrough. | P5 |
| 4.1.15-R74 | Route strip: intermediate stop airport name; SVO/VKO as link; same same/different airport logic as city | 4.1.15.5 Table 52 row 13 | desktop, tablet | — | TBD | Verify intermediate airport + SVO/VKO link. | P5 |
| 4.1.15-R75 | Route strip: intermediate stop terminal — if same terminal both sides show once; if different show both | 4.1.15.5 Table 52 row 14 | desktop, tablet | — | TBD | Verify terminal display logic. | P5 |
| 4.1.15-R76 | Route strip: stop duration (ground time) = next-seg dep − prev-seg arr (best available times) | 4.1.15.5 Table 52 row 11 | desktop, tablet | — | TBD | Verify ground-time calculation. | P5 |
| 4.1.15-R77 | «Общая информация по сегменту» block: segment #, flight#, codeshare, full airline icon, route-changed icon, airport-return icon, collapse/expand control | 4.1.15.5 Table 52 (Общая info) rows 1–7 | all | — | TBD | Verify per-segment header fields. | P5 |
| 4.1.15-R78 | Segment collapse: hides times block («Время выполнения сегмента») and details block («Детали сегмента»); always keeps rows 1–6 of header visible | 4.1.15.5 Table 52 (Общая info) row 7 | all | — | TBD | Verify segment collapse preserves header. | P5 |
| 4.1.15-R79 | Per-segment departure/arrival time fields: same rules as direct flight (priority, strikethrough, day-change badge) | 4.1.15.5 Table 52 (Общая info) rows 8–18 | all | — | TBD | Verify per-segment time rules. | P5 |
| 4.1.15-R80 | Per-segment timeline (embedded): aircraft icon + «В пути» + «До прилета» per §4.1.15.7 and §4.1.15.8 | 4.1.15.5 Table 52 rows 13.1–13.3 | all | — | TBD | Verify per-segment timeline. | P5 |
| 4.1.15-R81 | «Детали сегмента» block: same reg/boarding/deboarding/aircraft/meals/services sub-blocks as direct flight | 4.1.15.5 Table 52 (Детали) | all | — | TBD | Verify details block per segment. | P5 |
| 4.1.15-R82 | Intermediate-landing plaque (§4.1.15.6) rendered between segments | 4.1.15.5 Table 52 (Плашка) | all | — | TBD | Verify plaque rendered between segs. | P5 |
| 4.1.15-R83 | «Расписание рейса» block (multi-segment): single schedule for all segments; «Время в пути» = total (all segments + ground times); if unplanned extra stop, show original scheduled duration | 4.1.15.5 Table 52 (Расписание) | all | — | TBD | Verify combined schedule + total duration logic. | P5 |
§4.1.15.6 — Информация о промежуточной посадке (Intermediate landing)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.15-R84 | Intermediate-landing plaque shown between two segments when they share the same flight number | 4.1.15.6 TZ line 253 | all | FullRouteTimeline/ |
TBD | Verify plaque appears only for multi-seg same-number. | P5 |
| 4.1.15-R85 | Plaque fields: type icon, duration, start–end times with day-change badges, city, airport (optional), terminal (optional) | 4.1.15.6 TZ lines 258-270 | all | — | TBD | Verify all plaque fields. | P5 |
| 4.1.15-R86 | Plaque duration = arr time of prev segment − dep time of next segment (best available per position) | 4.1.15.6 TZ line 265 | all | — | TBD | Verify ground-time calculation for plaque. | P5 |
| 4.1.15-R87 | Plaque time format ЧЧ:ММ{±X}–ЧЧ:ММ{±X} using best available time per position |
4.1.15.6 TZ line 266 | all | — | TBD | Verify plaque time format with badges. | P5 |
| 4.1.15-R88 | SVO/VKO airport name on plaque shown as hyperlink (new tab) | 4.1.15.6 TZ line 272 | all | — | TBD | Verify SVO/VKO link on plaque. | P5 |
| 4.1.15-R89 | Day-change badge tooltip on plaque: «День» for ±1; no tooltip on mobile | 4.1.15.6 TZ lines 273-275 | desktop, tablet | — | TBD | Verify tooltip on plaque badge. | P5 |
| 4.1.15-R90 | Plaque type A (same city/airport/terminal): shown when arr-prev airport = dep-next airport AND terminals equal (or one side missing) | 4.1.15.6 TZ lines 277-286 | all | — | TBD | Verify plaque-A condition. | P5 |
| 4.1.15-R91 | Plaque type B (city change): shown when arr-prev city ≠ dep-next city | 4.1.15.6 TZ line 287 | all | — | TBD | Verify plaque-B condition. | P5 |
| 4.1.15-R92 | Plaque type C (terminal change): same city + same airport + different terminals | 4.1.15.6 TZ lines 288-293 | all | — | TBD | Verify plaque-C condition. | P5 |
| 4.1.15-R93 | Plaque type D (airport change within same city): same city, airports differ (using scheduled vs actual comparison matrix) | 4.1.15.6 TZ lines 294-306 | all | — | TBD | Verify plaque-D comparison matrix logic. | P5 |
§4.1.15.7 — Алгоритм расчета времени на «Временной шкале» (Timeline time algorithm)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.15-R94 | Total flight minutes = (actual/expected arr time UTC) − (actual dep time UTC) | 4.1.15.7 TZ line 309 | all | — | TBD | Verify total-minutes formula. | P5 |
| 4.1.15-R95 | Elapsed minutes «В пути» = current time UTC − dep time UTC | 4.1.15.7 TZ line 310 | all | — | TBD | Verify elapsed formula. | P5 |
| 4.1.15-R96 | Remaining minutes «До прилета» = arr time UTC − current time UTC | 4.1.15.7 TZ line 311 | all | — | TBD | Verify remaining formula. | P5 |
| 4.1.15-R97 | Aircraft position on timeline = elapsed / total as percentage | 4.1.15.7 TZ line 312 | all | — | TBD | Verify position percentage calculation. | P5 |
| 4.1.15-R98 | Display format: {Д}д. {ЧЧ}ч. {ММ}мин. — omit units that are zero; e.g. «45 мин.», «2ч. 15 мин.», «1д. 3ч. 5 мин.» |
4.1.15.7 TZ line 313 | all | — | TBD | Verify format with unit omission. | P5 |
§4.1.15.8 — Правила показа статусов на временной шкале (Status display rules)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.15-R99 | Aircraft icon on timeline is colored per flight status (colors per Fig 28 / Appendix 2) | 4.1.15.8 TZ line 315-317 | all | — | TBD | Verify status-to-color mapping. | P5 |
| 4.1.15-R100 | «В пути» and «До прилета» labels shown/hidden per status according to Fig 28 rules | 4.1.15.8 TZ line 315-317 | all | — | TBD | Verify label visibility per status. | P5 |
§4.1.15.9 — Алгоритм расчета предыдущего рейса (Previous-flight algorithm)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.15-R101 | System shows previous flight number (the flight this aircraft operated before the current one) | 4.1.15.9 TZ line 319 | all | — | TBD | Verify previous-flight field populated. | P5 |
| 4.1.15-R102 | Source: OnwardFlight field in AOMM telegram identifies the NEXT flight for this aircraft; PreviousFlight is derived inversely |
4.1.15.9 TZ line 320 | all | — | TBD | Verify backend derivation (front shows whatever API returns). | P5 |
| 4.1.15-R103 | If OnwardFlight for another flight changes/is removed, PreviousFlight on the current flight is also updated (backend concern; FE renders API result) |
4.1.15.9 TZ lines 321-323 | all | — | TBD | Verify FE re-renders when API returns updated prev-flight. | P5 |
§4.1.15.10 — Питание на борту (On-board meals)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.15-R104 | Meal block shows: icon + name for each meal class present (Economy / Comfort / Business / Special) | 4.1.15.10 TZ lines 326-332 | all | — | TBD | Verify meal class icons and names. | P5 |
| 4.1.15-R105 | Clicking a meal class opens https://www.aeroflot.ru/ru-ru/information/onboard/dining?0000#meal-type_{N} in new tab (N=0 Economy, 1 Comfort, 2 Business, 3 Special) |
4.1.15.10 TZ lines 333-341 | all | — | TBD | Verify meal click target URLs. | P5 |
| 4.1.15-R106 | Meal block hidden entirely if no meal data received | 4.1.15.10 TZ line 342 | all | — | TBD | Verify meal block absent when data missing. | P5 |
| 4.1.15-R107 | Special-meal icon shows a loading gif until API response; then show static icon if positive response, hide icon if negative | 4.1.15.10 TZ lines 344-347 | all | — | TBD | Verify special-meal loader → static/hidden flow. | P5 |
| 4.1.15-R108 | Special-meal API call rules: if no Economy AND no Business data → don't call API; if only Business → call with cabin=business; if both Economy+Business → call with cabin=econom only; no Business call needed |
4.1.15.10 TZ lines 349-363 | all | — | TBD | Verify API call conditions. | P5 |
| 4.1.15-R109 | Meal API responses cached for 3 hours | 4.1.15.10 TZ line 363 | all | — | TBD | Verify 3h cache on meal API. | P5 |
§4.1.15.11 — Услуги на борту (On-board services)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.15-R110 | Services block shows: icon + name for each service in data (Покупки на борту, Space+, Интернет на борту, Система мультимедийных развлечений, Выбор места) | 4.1.15.11 TZ lines 368-375 | all | — | TBD | Verify service icons and names. | P5 |
| 4.1.15-R111 | Clicking a service opens its URL in new tab (Покупки: .../shopping_onboard_ec; Space+: .../space_plus; Интернет: .../at_height; Мультимедиа: entertainment.aeroflot.ru; Выбор места: .../additional_service/#seat_reservation) |
4.1.15.11 TZ lines 376-381 | all | — | TBD | Verify each service URL target. | P5 |
| 4.1.15-R112 | Services block hidden entirely if no service data received | 4.1.15.11 TZ line 382 | all | — | TBD | Verify block absent when data missing. | P5 |
4.1.16 — Карточка рейса, открытого из Расписания
Flight details page entered from Schedule.
Same sub-structure as 4.1.15 plus connecting-flight variant (4.1.16.6) and intermediate-landing+transfer (4.1.16.7) and execution-days algorithm (4.1.16.8). TZ source lines 2309–2886.
§4.1.16.1 — Структура экранной формы (Screen form structure)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.16-R1 | Page entered via «Детали рейса» button from Schedule expanded row | 4.1.16.1 TZ line 385 | all | ScheduleDetailsPage.tsx |
TBD | Verify navigation entry point. | P5 |
| 4.1.16-R2 | Desktop/tablet layout: left = «Вернуться к Расписанию» + mini-list; right = breadcrumbs, page title, day-tabs, flight header, flight info | 4.1.16.1 Table 54 | desktop, tablet | ScheduleDetailsPage.tsx |
TBD | Verify two-column layout. | P5 |
| 4.1.16-R3 | Mobile layout: breadcrumbs → page title → «Вернуться к Расписанию» → day list → flight header → flight info (no mini-list) | 4.1.16.1 Table 54 | mobile | — | TBD | Verify mobile layout order. | P5 |
| 4.1.16-R4 | «Вернуться к Расписанию» navigates back with search state preserved (filter + data) | 4.1.16.1 Table 55 row 1 | all | — | TBD | Verify back-navigation with search state. | P5 |
| 4.1.16-R5 | Flight header contains: flight number(s), codeshare, airline icon, share, buy, «Статус рейса» button, last-update timestamp; no «Онлайн-Регистрация» button (Schedule variant) | 4.1.16.1 Table 55 row 5 | all | — | TBD | Verify header differs from §4.1.15 (no check-in, has status button). | P5 |
| 4.1.16-R6 | On scroll: day-tabs and flight header are sticky on desktop/tablet; mini-list scrolls with page; no sticky on mobile | 4.1.16.1 Table 56 | desktop, tablet | — | TBD | Verify sticky behavior. | P5 |
| 4.1.16-R7 | Flight info section supports three types: direct, multi-segment, connecting (стыковочный) | 4.1.16.1 Table 55 row 6 | all | — | TBD | Verify all three type variants render. | P5 |
| 4.1.16-R8 | Day-change badge {-X} / {+X} for ALL times on the card; tooltip shows «День» for ±1, date for ±2+ |
4.1.16.1 TZ lines 433-434 | all | — | TBD | Verify badge on all time fields. | P5 |
| 4.1.16-R9 | Day-change badge tooltip NOT shown on mobile | 4.1.16.1 TZ line 434 | mobile | — | TBD | Verify tooltip suppressed mobile. | P5 |
§4.1.16.2 — Мини-список (Mini-list)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.16-R10 | Schedule mini-list is split into three date groups: [-1 from flight date], [flight date X], [+1 from X] | 4.1.16.2 TZ line 438 | desktop, tablet | FlightsMiniList/ |
TBD | Verify three-group structure. | P5 |
| 4.1.16-R11 | Default: group [X] (flight date) is expanded on load | 4.1.16.2 TZ line 439 | desktop, tablet | — | TBD | Verify X group expanded by default. | P5 |
| 4.1.16-R12 | Selected flight has distinct color indicator («выбранного рейса») | 4.1.16.2 TZ line 440 | desktop, tablet | — | TBD | Verify selected-state styling. | P5 |
| 4.1.16-R13 | Mini-list auto-scrolled to selected flight | 4.1.16.2 TZ line 441 | desktop, tablet | — | TBD | Verify auto-scroll on mount. | P5 |
| 4.1.16-R14 | Each group can be collapsed/expanded; if a group has no flights it is blocked (non-expandable) with distinct color | 4.1.16.2 TZ line 442 | desktop, tablet | — | TBD | Verify empty-group blocked + distinct color. | P5 |
| 4.1.16-R15 | If the card was opened from the -1-day row (lowest boundary), the [-1 from X] group is shown but blocked (would become -2 from today, violating bounds) | 4.1.16.2 TZ line 443 | desktop, tablet | — | TBD | Verify boundary-edge group is blocked. | P5 |
| 4.1.16-R16 | Mini-list sort: departure time by schedule (00:00–23:59); no re-sorting | 4.1.16.2 TZ line 444 | desktop, tablet | — | TBD | Verify schedule-sort in mini-list. | P5 |
| 4.1.16-R17 | Mini-list scrolls as main page scrolls; always accessible | 4.1.16.2 TZ line 445 | desktop, tablet | — | TBD | Verify panel scroll behavior. | P5 |
| 4.1.16-R18 | Clicking another flight in mini-list: color indicator moves, new flight card opens | 4.1.16.2 TZ line 446 | desktop, tablet | — | TBD | Verify click → navigation + indicator. | P5 |
| 4.1.16-R19 | Mini-list row fields: flight number(s) (multiple if connecting), dep time, status icon (always «Запланирован» icon), arr time, day-change badges, dep/arr dates, dep/arr cities, dep/arr airports (SVO/VKO as link), dep/arr terminal codes | 4.1.16.2 Table 57 | desktop, tablet | — | TBD | Verify all fields including status always «Запланирован». | P5 |
| 4.1.16-R20 | After refresh, mini-list retains full state via URL-encoded search params per §4.1.2 | 4.1.16.2 TZ line 461-462 | desktop, tablet | — | TBD | Verify URL carries search params. | P5 |
| 4.1.16-R21 | Mini-list NOT shown on mobile | 4.1.16.2 TZ line 463 | mobile | — | TBD | Verify mini-list hidden on mobile. | P5 |
§4.1.16.3 — Поведение Табов-дней (Day-tabs behavior)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.16-R22 | Day-tabs grouped in sets of 7; active range [-1, +330] from today (Schedule window) | 4.1.16.3 TZ lines 466-467 | all | — | TBD | Verify +330 day window for Schedule day-tabs. | P5 |
| 4.1.16-R23 | Day-tabs scroll by 7 starting from -1 from today | 4.1.16.3 TZ line 468 | all | — | TBD | Verify scroll step of 7. | P5 |
| 4.1.16-R24 | Fill-to-7 padding with inactive tabs if last active tab is not last in group; right-scroll arrow disabled | 4.1.16.3 TZ line 469 | all | — | TBD | Verify fill + right-arrow disabled. | P5 |
| 4.1.16-R25 | Currently open day-tab highlighted; page scrolls to it | 4.1.16.3 TZ line 471 | all | — | TBD | Verify active-tab highlight + scroll. | P5 |
| 4.1.16-R26 | Mobile: day-tabs replaced by a date list | 4.1.16.3 TZ line 472 | mobile | — | TBD | Verify mobile list replaces tab chips. | P5 |
| 4.1.16-R27 | Clicking a day-tab runs the §4.1.16.3.1 navigation algorithm (not a simple date filter) | 4.1.16.3 TZ line 473 | all | — | TBD | Verify tab-click triggers full search navigation. | P5 |
| 4.1.16-R28 | §4.1.16.3.1 direct-search tab click: navigate to Schedule search page; pre-fill filter (dep city, arr city, week containing tab date, departure time 00:00–24:00, no direct-only, no return); auto-execute search; open the day matching the tab | 4.1.16.3.1 TZ lines 475-486 | all | — | TBD | Verify tab-click search navigation for direct search. | P5 |
| 4.1.16-R29 | §4.1.16.3.1 round-trip tab click «Туда»: same as direct but date for «Туда» = week of tab; «Обратно» checked | 4.1.16.3.1 TZ lines 488-501 | all | — | TBD | Verify round-trip outbound tab click. | P5 |
| 4.1.16-R30 | §4.1.16.3.1 round-trip tab click «Обратно»: return date week = tab week; outbound preserves original | 4.1.16.3.1 TZ lines 492-501 | all | — | TBD | Verify round-trip return tab click. | P5 |
| 4.1.16-R31 | §4.1.16.3.1 algorithm applies to all flight types (direct, multi-segment, connecting) and mobile (list select) | 4.1.16.3.1 TZ lines 504-505 | all | — | TBD | Verify algorithm scope. | P5 |
§4.1.16.4 — Информация о прямом рейсе (Direct flight info — Schedule variant)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.16-R32 | Departure time shown as scheduled only (no live estimated/actual in Schedule details) | 4.1.16.4 Table 58 row 1 (Info) | all | — | TBD | Verify Schedule card shows only scheduled time (no live). | P5 |
| 4.1.16-R33 | Departure date shown ДД.ММ.ГГГГ |
4.1.16.4 Table 58 row 2 (Info) | all | — | TBD | Verify dep date shown. | P5 |
| 4.1.16-R34 | Day-change badge for departure time | 4.1.16.4 Table 58 row 3 (Info) | all | — | TBD | Verify dep badge. | P5 |
| 4.1.16-R35 | Departure city, airport (SVO/VKO link), terminal shown if data present | 4.1.16.4 Table 58 rows 4–6 (Info) | all | — | TBD | Verify dep fields. | P5 |
| 4.1.16-R36 | Status shown as icon + text per Appendix 2 | 4.1.16.4 Table 58 row 7 (Info) | all | — | TBD | Verify status field. | P5 |
| 4.1.16-R37 | Day-change badge for arrival time | 4.1.16.4 Table 58 row 8 (Info) | all | — | TBD | Verify arr badge. | P5 |
| 4.1.16-R38 | Arrival time (scheduled), arrival date, arrival city, airport (SVO/VKO link), terminal | 4.1.16.4 Table 58 rows 9–13 (Info) | all | — | TBD | Verify arr fields. | P5 |
| 4.1.16-R39 | «Детали рейса» accordion: aircraft block only (тип ВС as link, no reg/boarding/deboarding for Schedule); meals block; services block | 4.1.16.4 Table 58 (Детали) rows 1–4 | all | — | TBD | Verify Schedule details has no live blocks, only aircraft+meals+services. | P5 |
| 4.1.16-R40 | «Расписание рейса» block: scheduled dep UTC±offset, scheduled arr UTC±offset, duration (dep−arr by schedule), days-of-week per §4.1.16.8, footnote | 4.1.16.4 Table 58 (Расписание) | all | — | TBD | Verify schedule block fields. | P5 |
| 4.1.16-R41 | Days-of-week: all 7 days shown; non-operating days have different color than operating days | 4.1.16.4 Table 58 row 5 (Расписание) | all | — | TBD | Verify weekday mask rendering. | P5 |
| 4.1.16-R42 | Schedule block footnote: «* Расписание на неделю ДД.ММ.ГГГГ - ДД.ММ.ГГГГ\nВремя вылета и прилета может меняться в зависимости от даты вылета» | 4.1.16.4 Table 58 row 6 (Расписание) | all | — | TBD | Verify footnote format with date range. | P5 |
§4.1.16.5 — Информация о многосегментном рейсе (Multi-segment — Schedule variant)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.16-R43 | Multi-segment Schedule: header uses round mini-icon for airline; if no mini-icon, no icon shown | 4.1.16.5 Table 59 row 3 | all | — | TBD | Verify mini-icon (round) vs full icon logic for multi-seg Schedule. | P5 |
| 4.1.16-R44 | «Статус рейса» link in header (not button); click navigates to Online-Board card for this flight | 4.1.16.5 Table 59 rows 6, 5 (for mobile: not shown) | desktop, tablet | — | TBD | Verify status link in Schedule multi-seg header. | P5 |
| 4.1.16-R45 | Route strip: departure time by schedule only (no live times) | 4.1.16.5 Table 59 row 2 (Маршрут) | desktop, tablet | — | TBD | Verify schedule-only times on route strip. | P5 |
| 4.1.16-R46 | Route strip: segment duration = scheduled arr − scheduled dep | 4.1.16.5 Table 59 row 8 (Маршрут) | desktop, tablet | — | TBD | Verify schedule-based segment duration. | P5 |
| 4.1.16-R47 | Per-segment: «Статус рейса» button on desktop/tablet; NOT shown on mobile | 4.1.16.5 Table 59 row 5 (Общая info) | desktop, tablet | — | TBD | Verify status button per-segment mobile suppression. | P5 |
| 4.1.16-R48 | Per-segment: dep/arr times are scheduled only; dep date and arr date shown | 4.1.16.5 Table 59 rows 6–17 (Общая info) | all | — | TBD | Verify schedule-only times + dates per segment. | P5 |
| 4.1.16-R49 | Per-segment «Детали сегмента»: aircraft block (тип ВС link), meals block, services block; no live blocks | 4.1.16.5 Table 59 (Детали) | all | — | TBD | Verify Schedule segment details fields. | P5 |
| 4.1.16-R50 | «Расписание рейса» block (multi-seg Schedule): single block for all segments; total duration = all seg durations + intermediate ground times; footnote with date range | 4.1.16.5 Table 59 (Расписание) | all | — | TBD | Verify combined schedule block for multi-seg. | P5 |
§4.1.16.6 — Информация о стыковочном рейсе (Connecting flight info)
Connecting = two or more separate flight numbers with a transfer between them. TZ covers three sub-cases: direct+direct, multi-seg+direct/direct+multi-seg, multi-seg+multi-seg.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.16-R51 | Connecting flight header: first flight number, first codeshare, «Статус рейса» link, round mini airline icon; THEN same for second flight; then share + buy + last-update | 4.1.16.6 Table 60 rows 1–8 (Header) | all | TransferBar/ |
TBD | Verify two-flight header structure. | P5 |
| 4.1.16-R52 | Header: no «Онлайн-регистрация» button in connecting Schedule card | 4.1.16.6 Table 60 (Header) | all | — | TBD | Verify no check-in button. | P5 |
| 4.1.16-R53 | Route strip: single combined strip for all segments (same scroll rules as multi-seg); dep city of first segment + transfer city + arr city of last segment; hidden on mobile | 4.1.16.6 Table 60 (Маршрут) | desktop, tablet | — | TBD | Verify combined route strip for connecting. | P5 |
| 4.1.16-R54 | Transfer duration in route strip = scheduled arr of leg-1 last seg − scheduled dep of leg-2 first seg | 4.1.16.6 Table 60 row 11 (Маршрут) | desktop, tablet | — | TBD | Verify transfer duration calc in route strip. | P5 |
| 4.1.16-R55 | Per-flight-segment (direct): segment #, flight#, codeshare, full airline icon, «Статус рейса» button (desktop/tablet only), collapse/expand | 4.1.16.6 Table 60 (Сегмент прямой) rows 1–6 | all | — | TBD | Verify per-direct-segment header. | P5 |
| 4.1.16-R56 | Per-segment times (connecting): scheduled dep time, dep date, day-change badge, dep city/airport/terminal, arrival badge, arr time, arr date, arr city/airport/terminal | 4.1.16.6 Table 60 rows 7–18 | all | — | TBD | Verify all time/location fields. | P5 |
| 4.1.16-R57 | Per-segment «Детали сегмента»: aircraft (тип ВС link), meals, services | 4.1.16.6 Table 60 (Детали) | all | — | TBD | Verify details for connecting segment. | P5 |
| 4.1.16-R58 | Per-segment «Расписание прямого рейса»: own schedule block for each leg (connecting have separate schedules per flight) | 4.1.16.6 Table 60 (Расписание прямого) | all | — | TBD | Verify each leg has its own schedule block. | P5 |
| 4.1.16-R59 | Transfer plaque (пересадка) rendered between legs 1 and 2 per §4.1.16.7 | 4.1.16.6 Table 60 (Плашка) | all | — | TBD | Verify transfer plaque between legs. | P5 |
| 4.1.16-R60 | Connecting with multi-segment+direct: multi-segment leg rendered with its own intermediate-landing plaque(s); then transfer plaque; then direct leg | 4.1.16.6 Table 61 | all | — | TBD | Verify mixed leg rendering order. | P5 |
| 4.1.16-R61 | Connecting with multi-segment+multi-segment: both legs rendered with their own intermediate-landing plaque(s); transfer plaque between the two legs | 4.1.16.6 Table 62 | all | — | TBD | Verify double multi-seg rendering. | P5 |
| 4.1.16-R62 | Multi-segment leg within connecting: no common «Расписание» block (each sub-flight in multi-seg has own schedule block as part of the connecting leg's «Расписание рейса» sub-block) | 4.1.16.6 Table 61/62 (Расписание) | all | — | TBD | Verify schedule block structure for multi-seg inside connecting. | P5 |
| 4.1.16-R63 | UI supports max one transfer/stыковка on the flight card (TZ: «так как на UI предусматривается одна стыковка») | 4.1.16.6 Table 60 TZ note | all | — | TBD | Verify only one transfer plaque rendered. | P5 |
§4.1.16.7 — Информация о промежуточной посадке и пересадке (Intermediate landing + transfer plaque)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.16-R64 | Plaque type = «промежуточная посадка» for multi-segment legs; «пересадка» for connecting transfer | 4.1.16.7 TZ line 908 | all | — | TBD | Verify plaque type label. | P5 |
| 4.1.16-R65 | Schedule plaque uses scheduled times only (not live) for duration and start–end | 4.1.16.7 TZ line 914-915 | all | — | TBD | Verify scheduled-only times on Schedule plaque. | P5 |
| 4.1.16-R66 | Plaque fields: icon, type, duration, start–end times ЧЧ:ММ{±X}–ЧЧ:ММ{±X}, city, airport, terminal, terminal/airport change indicator |
4.1.16.7 TZ lines 907-919 | all | — | TBD | Verify all plaque fields. | P5 |
| 4.1.16-R67 | SVO/VKO airport on plaque as hyperlink; day-change badge + tooltip (no tooltip on mobile) | 4.1.16.7 TZ lines 921-924 | all | — | TBD | Verify link + badge on Schedule plaque. | P5 |
| 4.1.16-R68 | Plaque display conditions (A/B/C/D) same as §4.1.15.6 but checking by flight type (multi-seg vs connecting); show matching plaque variant | 4.1.16.7 TZ lines 925-946 | all | — | TBD | Verify conditional plaque-type selection same logic. | P5 |
§4.1.16.8 — Алгоритм расчета дней выполнения рейса (Execution-days algorithm)
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.16-R69 | Days-of-week mask is computed per calendar week from actual schedule data, not a static field | 4.1.16.8 TZ line 948 | all | — | TBD | Verify dynamic week-mask computation. | P5 |
| 4.1.16-R70 | Calculation uses calendar weeks (Mon–Sun) ignoring time-of-day | 4.1.16.8 TZ line 949 | all | — | TBD | Verify week boundary is Mon–Sun. | P5 |
| 4.1.16-R71 | Data cached per (flight#, local departure date, calendar week); TTL = 1 hour; TTL is NOT in config file, only changeable by customer request | 4.1.16.8 TZ lines 950, 954 | all | — | TBD | Verify cache key + 1h TTL (backend concern; FE reads from API). | P5 |
| 4.1.16-R72 | Cache spans from current week through the week the user queries + 1 day | 4.1.16.8 TZ line 953 | all | — | TBD | Verify cache range. | P5 |
| 4.1.16-R73 | Live additions/removals of operating days (from SSM/ASM telegrams) are recalculated on-the-fly and update the cache for the affected calendar week | 4.1.16.8 TZ line 951 | all | — | TBD | Verify live schedule updates reflected in days mask. | P5 |
| 4.1.16-R74 | For connecting flights: days-of-week calculated per leg (per flight number), not combined | 4.1.16.8 TZ line 952 | all | — | TBD | Verify per-leg day calculation. | P5 |
| 4.1.16-R75 | Card displays days mask for the calendar week (Mon–Sun) that contains the flight's departure date | 4.1.16.8 TZ line 955 | all | — | TBD | Verify which week is displayed. | P5 |
| 4.1.16-R76 | Footnote in schedule block: «Расписание на неделю ДД.ММ.ГГГГ - ДД.ММ.ГГГГ» (Mon–Sun dates of the displayed week) | 4.1.16.8 TZ lines 958-960 | all | — | TBD | Verify footnote includes computed week start/end. | P5 |
4.1.17 — Алгоритм расчета признака перехода суток
Day-change indicator algorithm.
Specifies when the +1/+2/-1 chip appears next to a departure or arrival time. Logic compares the local date of the time at its airport against the local date of the query date. TZ source lines 2887–2907.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.17-R1 | Departure badge calculation: A = local date the user queried; B = local departure date for each time type (scheduled/expected/actual); if B−A = 0 → no badge; else show {sign}{ | B−A | } | 4.1.17 TZ lines 962-971 | all | dayChange.ts:computeDayChange |
Implemented |
| 4.1.17-R2 | Arrival badge calculation: same formula using local arrival date at arrival airport | 4.1.17 TZ lines 973-981 | all | dayChange.ts:computeDayChange |
Implemented | Same helper; arrival uses scheduledArrival.dayChange.value. |
P5 |
| 4.1.17-R3 | Badge shown as +1, +2, -1, etc.; hidden if 0 |
4.1.17 TZ lines 965-967 | all | dayChange.ts:formatDayChangeBadge, TimeGroup.tsx |
Implemented | formatDayChangeBadge(0) returns "" (hidden). Tests locked. |
P5 |
| 4.1.17-R4 | Badge calculated independently per time type: scheduled badge may differ from expected or actual badge | 4.1.17 TZ lines 971, 981 (step 7) | all | TimeGroup.tsx (scheduledDayChange + actualDayChange props) |
Implemented | TimeGroup now accepts separate per-type badges; FlightCard passes scheduledDayChange and actualDayChange independently. Expanded row also shows per-type badges. |
P5 |
| 4.1.17-R5 | Tooltip on badge: shows «День» if badge is -1 or +1; shows «ДД.ММ.ГГГГ» (departure/arrival date adjusted by X) if badge is ±2 or more | 4.1.17 TZ lines 969-970, 979-980 | desktop, tablet | dayChange.ts:dayChangeBadgeTooltip |
Implemented | Fixed: uses string-based date extraction (no TZ reprojection). «День» for ±1; DD.MM.YYYY for ±2+. Tests cover month/year boundaries. | P5 |
| 4.1.17-R6 | Badge appears next to the time field, not next to the date field | 4.1.17 (implicit per all tables referencing «Признак перехода суток» next to times) | all | TimeGroup.tsx |
Implemented | Badge is sibling of time span inside .time-group__times. |
P5 |
| 4.1.17-R7 | Badge applied consistently across all surfaces: results-list rows (collapsed + expanded), details page, mini-list, intermediate-landing/transfer plaques | 4.1.17 + §§4.1.13–4.1.16 tables | all | TimeGroup.tsx, FlightCard.tsx expanded row |
Implemented | Collapsed row: TimeGroup with per-type badges. Expanded row: inline badges added. Details accordion: badge present. Schedule: scheduled badge. Mini-list / plaques: deferred to P5 task 14/11. | P5 |
| 4.1.17-R8 | Tooltip NOT shown on mobile | 4.1.15.1/4.1.16.1 (both state mobile tooltip suppressed) | mobile | — | TBD | title attribute is always set; CSS pointer-events: none on mobile would suppress hover tooltip. Deferred — requires CSS media query or JS UA check. |
P5 |
4.1.18 — Кеширование данных
Data caching.
Single-paragraph section on acceptable client-side caching behavior (session cache of results per §4.1.1-R23, dictionary cache for cities/airports, etc.).
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.18-R1 | Session-scope cache for search results per §4.1.1-R23/R27 | 4.1.18 | all | src/shared/state/* |
TBD | Verify TTL + scope. | P6 |
| 4.1.18-R2 | Dictionary cache (cities, airports, aircraft types) — TTL per TZ | 4.1.18 | all | src/shared/dictionaries/* |
TBD | Verify TTL + refresh policy. | P6 |
| 4.1.18-R3 | SSR-rendered initial payload must not expose stale data older than TZ-specified TTL | 4.1.18 | all | src/server/* |
TBD | Verify SSR cache headers. | P6 |
4.1.19 — Микроразметка страниц «Онлайн-Табло и Расписания»
Microdata: JSON-LD + OpenGraph.
Each page must emit JSON-LD (schema.org types per TZ table) and OpenGraph meta tags. CLAUDE.md contract #6 lists this as binding.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.19-R1 | Every page emits JSON-LD <script type="application/ld+json"> in <head> |
4.1.19 | all | src/ui/seo/* |
TBD | Verify presence per page. | P6 |
| 4.1.19-R2 | Start pages JSON-LD schema type per TZ | 4.1.19 | all | — | TBD | Populate schema. | P6 |
| 4.1.19-R3 | Results-list JSON-LD schema (Itemlist?) per TZ | 4.1.19 | all | — | TBD | Populate. | P6 |
| 4.1.19-R4 | Flight-details JSON-LD schema (Flight?) per TZ | 4.1.19 | all | — | TBD | Populate. | P6 |
| 4.1.19-R5 | OpenGraph meta tags (og:title, og:description, og:url, og:image, og:locale) per page |
4.1.19 | all | src/ui/seo/* |
TBD | Verify. | P6 |
| 4.1.19-R6 | og:locale matches the active language |
4.1.19 | all | — | TBD | Verify. | P6 |
Rules to refine from 4.1.19 text at P6 kickoff.
4.1.20 — Robots.txt
Crawler policy.
Specifies indexable paths (start pages, results with canonical params) vs disallowed paths (pages with volatile params, search mutations). Actual robots.txt lives at the host site, but the app must emit correct <link rel="canonical"> and <meta name="robots"> per page.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.20-R1 | Start pages emit <meta name="robots" content="index,follow"> |
4.1.20 | all | — | TBD | Verify. | P6 |
| 4.1.20-R2 | Canonical link per page (normalized URL, no volatile query params) | 4.1.20 | all | — | TBD | Verify per page. | P6 |
| 4.1.20-R3 | Pages TZ marks as non-indexable emit noindex |
4.1.20 | all | — | TBD | Populate list. | P6 |
| 4.1.20-R4 | hreflang alternates for all 9 languages per page | 4.1.20 | all | — | TBD | Verify. | P6 |
4.1.21 — Внештатные ситуации, ошибки 404 и 500
Error pages: 404 + 500.
Must render the Aeroflot-standard 404/500 pages. Centralized error page at /error/404 and /error/500.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.21-R1 | Unknown route → /error/404 |
4.1.21 | all | src/routes/error/[code]/* |
Implemented | Verify. | P6 |
| 4.1.21-R2 | Server error → /error/500 |
4.1.21 | all | src/routes/error/[code]/* |
Implemented | Verify. | P6 |
| 4.1.21-R3 | 404 page includes link back to section root + top-level breadcrumb | 4.1.21 | all | — | TBD | Verify. | P6 |
| 4.1.21-R4 | 500 page includes refresh CTA + support contact | 4.1.21 | all | — | TBD | Verify. | P6 |
| 4.1.21-R5 | Both pages SEO: noindex; translated for all 9 languages |
4.1.21 | all | — | TBD | Verify. | P6 |
4.1.22 — Алгоритм вывода иконок типов ВС
Airline carrier icon display algorithm.
Note: §4.1.22 in the TZ is NOT an aircraft-type (A320/B737) icon section — it is the operating carrier icon algorithm. Icons are derived from the OperatingBy field (IATA carrier code), not from aircraft type code. TZ source lines 2985–3040.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.22-R1 | Carrier icon source: OperatingBy field in DB (populated from SSM/ASM telegrams or from aircraft-registration-to-owner lookup table fed by AOMM telegrams) |
4.1.22 TZ lines 1062-1063 | all | src/shared/dictionaries/* |
TBD | Verify icon lookup uses OperatingBy code. |
P5 |
| 4.1.22-R2 | If OperatingBy is null, show default icon based on flight-number range: SU1–2999 → SU icon; SU3000–4999 → no icon; SU5000–5399 → DP (Победа); SU5400–5799 → HZ (Аврора); SU5800–5999 → no icon; SU6000–6999 → FV (Россия); SU7000–9999 → SU |
4.1.22 TZ lines 1064-1071 | all | — | TBD | Verify 7-range fallback logic. | P5 |
| 4.1.22-R3 | Three icon variants: full RU-locale, full EN-locale, round mini icon (круглая, маленькая); each carrier may have all three or a subset | 4.1.22 Table 67 header | all | — | TBD | Verify three icon variants per carrier. | P5 |
| 4.1.22-R4 | Icon shown in: Online-Board results list, Schedule results list, Online-Board flight card, Schedule flight card | 4.1.22 TZ line 1060 | all | — | TBD | Verify icon presence on all four surfaces. | P5 |
| 4.1.22-R5 | In details page header for direct flights: full icon (not round); in multi-segment/connecting per-segment header: full icon | 4.1.15.4 Table 51 row 3; §4.1.16.5 Table 59 row 3 note | all | — | TBD | Verify full icon in direct-flight headers. | P5 |
| 4.1.22-R6 | In multi-segment Schedule header (шапка): round mini icon; if no mini icon for this carrier → no icon shown | 4.1.16.5 Table 59 row 3 | all | — | TBD | Verify multi-seg Schedule header uses round icon + absent-if-missing rule. | P5 |
| 4.1.22-R7 | In connecting flight header: round mini icon per flight; if no mini icon → no icon | 4.1.16.6 Table 60 row 4 | all | — | TBD | Verify connecting header uses round icon. | P5 |
| 4.1.22-R8 | Carrier lookup table (Table 67) contains 35 carriers: FV (Россия), SU (Аэрофлот), HZ (Аврора), RO (TAROM), DP (Побеdа), OM (MIAT), KL (KLM), AY (Finnair), DL (Delta), OK (Czech Airline), JU (Air Serbia), UX (Air Europa), BT (Air Baltic), AM (Aeromexico), AR (Aerolíneas Argentinas), KM (Airmalta), AF (Airfrance), AZ (Alitalia), PG (Bangkok Airways), SN (Brussels Airlines), FB (Bulgaria Air), CI (China Airlines), MU (China Eastern), CZ (China Southern), GA (Garuda Indonesia), FI (Icelandair), KO (Kenya Airways), KE (Korean Air), JL (Japan Airlines), LO (LOT), ME (Middle East Airlines), S7 (S7), SV (Saudi Arabian Airlines), VN (Vietnam Airlines), MF (XiamenAir) | 4.1.22 Table 67 | all | — | TBD | Verify all 35 carriers have assets in codebase. | P5 |
| 4.1.22-R9 | For Pobeda (DP): use EN icon for RU locale (no separate RU icon exists per Table 67) | 4.1.22 Table 67 row 5 | all | — | TBD | Verify DP uses EN icon for all locales. | P5 |
| 4.1.22-R10 | Carriers with round icon (≥ 15 carriers) get it in mini-list and connecting/multi-seg headers; carriers with only full icon get full icon or nothing in those slots | 4.1.22 Table 67 (round column) | all | — | TBD | Verify round-icon availability per carrier. | P5 |
| 4.1.22-R11 | OperatingBy updated from four sources: SSM/ASM new/SKD (DEI9/DEI127/DEI10/DEI50) — deletes+recreates flight; other SSM/ASM — updates if new data received; AOMM with AircraftRegistration — updates from registration-owner lookup |
4.1.22 TZ line 1073 | all | — | TBD | Backend concern; FE renders whatever OperatingBy the API returns. |
P5 |
4.1.23 — Правила вывода «Уточняется»
"Being clarified" fallback text rules.
Short subsection: when a data field is missing/pending from the API, UI shows the localized string "Уточняется" (not empty / not "—" / not "N/A"). TZ source lines 3041–3049.
Important: TZ specifies ORANGE color for «Уточняется» (not same as regular text — contradicts earlier spec assumption). «Уточняется» is styled distinctly in orange per Fig 32.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.23-R1 | All negative time values for flights in lists, cards, plaques render «Уточняется» | 4.1.23 TZ line 1117 | all | src/i18n/* |
TBD | Verify negative-time detection + «Уточняется» substitution across all time fields. | P5 |
| 4.1.23-R2 | Negative transfer/intermediate-landing durations in lists, cards, plaques render «Уточняется» | 4.1.23 TZ line 1118 | all | — | TBD | Verify negative-duration detection on transfer/landing plaques. | P5 |
| 4.1.23-R3 | Negative «Время в пути» (flight-duration) in schedule blocks of cards renders «Уточняется» | 4.1.23 TZ line 1119 | all | — | TBD | Verify negative duration in schedule block renders «Уточняется». | P5 |
| 4.1.23-R4 | Missing (absent) departure OR arrival time in lists, cards, plaques renders «Уточняется» | 4.1.23 TZ line 1120 | all | — | TBD | Verify null/missing time → «Уточняется» on all surfaces. | P5 |
| 4.1.23-R5 | «Уточняется» styled in ORANGE color (distinct from regular field text) | 4.1.23 TZ line 1121 + Fig 32 | all | — | TBD | Verify orange styling applied; NOT same color as regular text. | P5 |
| 4.1.23-R6 | «Уточняется» string is localized for all 9 languages (not a Russian-only literal) | 4.1.23 + §4.16 (9 languages) | all | — | TBD | Add i18n key for all 9 locales. | P5 |
4.1.24 — Карта полетов
Flight Map (new in revision С). Appendix 9 = binding mockup reference.
Six sub-subsections: start page (4.1.24.1), filter (4.1.24.2), search+map rendering (4.1.24.3), interactive map (4.1.24.4), internal API (4.1.24.5), "Buy ticket" CTA (4.1.24.6). Target rule count: 40–60.
Current impl:
src/features/flights-map/exists (phase-1 rewrite). Gap audit = verify existing code against revision-С spec.
| # | Rule | TZ cite | Viewport | Current impl | Status | Action | Plan |
|---|---|---|---|---|---|---|---|
| 4.1.24-R1 | 4.1.24.1 Start page composition (filter + empty map or route network as dots per §4.1.1-R21) | 4.1.24.1 + App. 9 | all | FlightsMapStartPage.tsx |
TBD | Verify against Appendix 9 mockups. | P6 |
| 4.1.24-R2 | 4.1.24.2 Filter attributes: Откуда, Куда, Дата рейса, toggles (Внутренние / Международные / С пересадкой) |
4.1.24.2 | all | FlightsMapFilter.tsx |
TBD | Enumerate per-attribute rules. | P6 |
| 4.1.24-R3 | 4.1.24.3 Search and map rendering — spider (direct), connecting lines, dots (full network). §4.1.1-R16 summarizes the three modes | 4.1.24.3 | all | MapCanvas.tsx |
TBD | Verify rendering logic. | P6 |
| 4.1.24-R4 | 4.1.24.4 Interactive behavior — click on destination, hover tooltip, zoom, pan, route highlight | 4.1.24.4 | all | MapCanvas.tsx |
TBD | Enumerate interactions. | P6 |
| 4.1.24-R5 | 4.1.24.5 Internal API — endpoints used by map (likely a subset of §4.3/4.5 methods) | 4.1.24.5 | all | flights-map/hooks/* |
TBD | Verify endpoints match TZ. | P6 |
| 4.1.24-R6 | 4.1.24.6 "Buy ticket" button navigates to booking flow with prefilled from/to/date (URL hand-off to booking subsystem) | 4.1.24.6 | all | — | TBD | Verify CTA target + params. | P6 |
| 4.1.24-R7 | No loader shown on Flight Map (per 4.1 ¶ intro: "Для «Карты полетов» «лоадера» не предусмотрено") | 4.1 ¶ intro | all | — | TBD | Verify loader absence. | P6 |
Rules enumerated at P6 kickoff.
NFR checklist (binding, cross-cutting)
Verified during P6 and finishing-a-development-branch check for each plan.
| # | NFR | TZ cite | Verification method | Status |
|---|---|---|---|---|
| NFR-1 | 100 RPS sustained | 4.8.2 | Load-test script (scripts/load-test/) run once; result archived in compliance report |
TBD |
| NFR-2 | Yandex.Metrica event tracking per TZ table | 4.9.2 | Unit tests on event dispatch + one manual observation in dev tools | TBD |
| NFR-3 | СТБ integration (checkout hand-off) | 4.9.1.3 | Contract test against СТБ endpoint | TBD |
| NFR-4 | Reliability: geo-distributed VMs, ≤6h recovery | 4.11 | Infra concern; acknowledge here, defer to deploy program | Deferred |
| NFR-5 | A11y: keyboard nav + screen reader support | 4.12 + CLAUDE.md | Automated Axe pass per page + manual screen-reader spot-check | Partial (many a11y commits present) |
| NFR-6 | Component isolation (no attack surface) | 4.14 + CLAUDE.md #5 | CSP validation + code-review check per plan | TBD |
| NFR-7 | Stack: Modern.js + MF 2.0 + React 18 + <Suspense> + no fetch outside useEffect + React.lazy() |
4.15.1 + CLAUDE.md #1 | Lint rule + code-review check | Implemented (phase-1) |
| NFR-8 | MF manifest exposed at https://<domain>/mf-manifest.json |
CLAUDE.md #1 | Integration test hits the URL | Implemented |
| NFR-9 | All 9 languages supported | 4.16 | i18n key-coverage test | Partial (keys present; coverage not all audited) |
Appendix inventory (mockup → subsection map)
Built at P0 (= this spec's commit). Every image in word/media/imageNN.{png,tiff,emf,jpeg} is mapped to the TZ subsection that references it. Images total: 197.
Inventory lives in a separate file for size: docs/superpowers/specs/2026-04-21-online-board-schedule-tz-mockup-inventory.md (generated at P1 kickoff by parsing the TZ docx).
Assumptions & open questions
- Responsive mockups completeness. Appendices 4 (web), 6 (mobile), 7 (tablet) are assumed to cover every subsection's UI. If a subsection lacks a mobile/tablet mockup, we fall back to responsive-CSS-driven layout and flag the gap in the subsection's Action column.
- Language-parity. TZ does not enumerate every string per language; we trust the existing
src/i18n/coverage and add keys for any new strings introduced by this audit. P1 will spot-audit 9-language coverage for page titles + breadcrumbs; other plans follow per-surface. - SignalR live updates. TZ does not explicitly mention live-updates via SignalR, but current impl uses it. We treat SignalR as an implementation detail that must preserve TZ behavior, not an additional TZ requirement. SignalR-specific bugs fall under their current owner, not this audit.
- Load test (NFR-1). Load testing requires a backend endpoint and infra access; if not available, NFR-1 is deferred to the deploy program with a note in the compliance report. Frontend-side perf targets (LCP, TTFB, bundle size) are still verified per-plan.
- Phase-1 compatibility. We keep phase-1 architecture (Modern.js 2.70.8 + MF 2.3.3) unchanged unless TZ requires otherwise — CLAUDE.md documents constraints that make phase-1 stack currently best-available.
Process for each plan
Each of P1–P6 follows this sequence:
- Populate remaining rule rows in its subsections (reading the full TZ text for those subsections + inspecting mockups).
- Arbitrate any
Conflict-status rules assigned to this plan — populate the Conflicts register with Resolution before writing the plan. - Invoke
superpowers:writing-planswith the rule IDs as input. - Execute plan per
superpowers:executing-plans(TDD-first where applicable persuperpowers:test-driven-development). - Code review per
superpowers:requesting-code-review. - Finish branch per
superpowers:finishing-a-development-branch— merge to main (after user authorization for the push). - Update this spec — change rule
StatusfromTBD/Missing/PartialtoDone+ commit SHA. Append row to Merge log.
Out-of-scope explicitly called out
- No database / telegram / backend work is initiated from this spec. Backend changes discovered during audit are flagged in a separate "Backend escalations" file, not addressed here.
- No refactoring beyond what serves a specific rule row. Cosmetic cleanups sit in a separate backlog.
- No new architectural patterns (e.g. state-management rewrite). If a rule is implementable with the existing pattern, we use it.