From 4c87a3b362323cd538e9825d6cb601c98cf074a0 Mon Sep 17 00:00:00 2001 From: gnezim Date: Fri, 17 Apr 2026 02:33:52 +0300 Subject: [PATCH] Add FullRouteTimeline wrapper component --- .../FullRouteTimeline/FullRouteTimeline.scss | 105 ++++++++++++++++++ .../FullRouteTimeline.test.tsx | 79 +++++++++++++ .../FullRouteTimeline/FullRouteTimeline.tsx | 18 +++ .../components/FullRouteTimeline/index.ts | 2 + 4 files changed, 204 insertions(+) create mode 100644 src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.scss create mode 100644 src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.test.tsx create mode 100644 src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.tsx create mode 100644 src/features/online-board/components/FullRouteTimeline/index.ts diff --git a/src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.scss b/src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.scss new file mode 100644 index 00000000..d026d757 --- /dev/null +++ b/src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.scss @@ -0,0 +1,105 @@ +.full-route-timeline { + background: #fff; + border-radius: 8px; + padding: 16px 24px; + margin-bottom: 16px; + + @media (max-width: 768px) { + display: none; + } +} + +.timeline { + display: flex; + align-items: center; + gap: 16px; + + &__arrow { + background: transparent; + border: 1px solid #d0dae5; + border-radius: 50%; + width: 32px; + height: 32px; + cursor: pointer; + color: #2060c0; + font-size: 16px; + + &:disabled { opacity: 0.3; cursor: not-allowed; } + } + + &__content { + flex: 1; + display: flex; + flex-direction: column; + gap: 8px; + } + + &__row { + display: flex; + align-items: center; + gap: 8px; + + &--times { font-size: 18px; font-weight: 500; color: #1a3a5c; } + &--stations { font-size: 14px; color: #666; } + } +} + +.timeline-section { + position: relative; + flex: 1; + display: flex; + align-items: center; + justify-content: center; + + &__separator { + flex: 1; + height: 1px; + background: #d0dae5; + } + + &__number { + position: absolute; + top: -20px; + background: #e3f0ff; + color: #2060c0; + border-radius: 10px; + padding: 2px 8px; + font-size: 12px; + font-weight: 600; + } + + &__duration { + font-size: 12px; + color: #666; + padding: 0 8px; + background: #fff; + + &--specifying { color: #ff9000; } + } +} + +.station { + display: flex; + flex-direction: column; + gap: 2px; + + &--right { align-items: flex-end; text-align: right; } + &--center { align-items: center; text-align: center; } + + &__city { font-size: 14px; font-weight: 500; color: #1a3a5c; } + &__code { font-size: 12px; color: #666; } + &__terminal { font-size: 11px; color: #999; } + + &--large { .station__city { font-size: 22px; } } + &--small { .station__city { font-size: 12px; } } +} + +.station-change { + display: flex; + align-items: center; + gap: 8px; + + &__arrow { color: #2060c0; } + &__city { font-size: 12px; color: #666; } + &__code { font-size: 14px; font-weight: 500; color: #1a3a5c; } +} diff --git a/src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.test.tsx b/src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.test.tsx new file mode 100644 index 00000000..980237bd --- /dev/null +++ b/src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.test.tsx @@ -0,0 +1,79 @@ +// @vitest-environment jsdom +import { describe, it, expect, vi } from "vitest"; +import { render, screen } from "@testing-library/react"; +import type { IFlightLeg } from "../../types.js"; + +vi.mock("@/i18n/provider.js", () => ({ + useTranslation: () => ({ t: (k: string) => k }), +})); + +import { FullRouteTimeline } from "./FullRouteTimeline.js"; + +function makeLeg(i: number): IFlightLeg { + return { + arrival: { + scheduled: { + airport: "", + airportCode: "AAA", + city: `City${i}`, + cityCode: `C${i}`, + countryCode: "RU", + }, + terminal: "", + times: { + scheduledArrival: { + dayChange: { value: 0, title: "" }, + local: `a${i}`, + localTime: `a${i}`, + tzOffset: 0, + utc: `2026-04-17T0${i}:00:00Z`, + }, + }, + }, + departure: { + scheduled: { + airport: "", + airportCode: "BBB", + city: `Dep${i}`, + cityCode: `D${i}`, + countryCode: "RU", + }, + terminal: "", + checkingStatus: "", + times: { + scheduledDeparture: { + dayChange: { value: 0, title: "" }, + local: `d${i}`, + localTime: `d${i}`, + tzOffset: 0, + utc: `2026-04-17T0${i}:00:00Z`, + }, + }, + }, + dayChange: 0, + equipment: {}, + flags: { checkinAvailable: false, returnToAirport: false, routeChanged: false }, + flyingTime: `${i}h`, + index: i, + operatingBy: {}, + status: "Scheduled", + updated: "", + } as IFlightLeg; +} + +describe("FullRouteTimeline", () => { + it("returns null when fewer than 2 legs", () => { + const { container } = render(); + expect(container.firstChild).toBeNull(); + }); + + it("renders container with data-testid=full-route-timeline when 2+ legs", () => { + render(); + expect(screen.getByTestId("full-route-timeline")).toBeTruthy(); + }); + + it("renders inner Timeline content (expect d0 visible when 2 legs)", () => { + render(); + expect(screen.getByText("d0")).toBeTruthy(); + }); +}); diff --git a/src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.tsx b/src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.tsx new file mode 100644 index 00000000..72a69a33 --- /dev/null +++ b/src/features/online-board/components/FullRouteTimeline/FullRouteTimeline.tsx @@ -0,0 +1,18 @@ +import type { FC } from "react"; +import type { IFlightLeg } from "../../types.js"; +import { Timeline } from "./Timeline.js"; +import "./FullRouteTimeline.scss"; + +export interface FullRouteTimelineProps { + legs: IFlightLeg[]; + viewType: "Onlineboard" | "Schedule"; +} + +export const FullRouteTimeline: FC = ({ legs, viewType }) => { + if (legs.length < 2) return null; + return ( +
+ +
+ ); +}; diff --git a/src/features/online-board/components/FullRouteTimeline/index.ts b/src/features/online-board/components/FullRouteTimeline/index.ts new file mode 100644 index 00000000..3a03c847 --- /dev/null +++ b/src/features/online-board/components/FullRouteTimeline/index.ts @@ -0,0 +1,2 @@ +export { FullRouteTimeline } from "./FullRouteTimeline.js"; +export type { FullRouteTimelineProps } from "./FullRouteTimeline.js";