Add shared helpers and DETAILS i18n keys for flight details panels
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import {
|
||||
shouldShowTransition,
|
||||
shouldShowAircraft,
|
||||
SERVICE_ICON_MAP,
|
||||
MEAL_LINKS,
|
||||
} from "./shared.js";
|
||||
import type { IFlightTransitionItem } from "../../types.js";
|
||||
|
||||
describe("shouldShowTransition", () => {
|
||||
const validItem: IFlightTransitionItem = {
|
||||
start: {} as never,
|
||||
end: {} as never,
|
||||
status: "InProgress",
|
||||
isActual: true,
|
||||
};
|
||||
|
||||
it("returns false for Schedule viewType", () => {
|
||||
expect(shouldShowTransition(validItem, "Scheduled", "Schedule")).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when leg is Cancelled", () => {
|
||||
expect(shouldShowTransition(validItem, "Cancelled", "Onlineboard")).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when item is undefined", () => {
|
||||
expect(shouldShowTransition(undefined, "Scheduled", "Onlineboard")).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when item.status is Scheduled", () => {
|
||||
const scheduled = { ...validItem, status: "Scheduled" as const };
|
||||
expect(shouldShowTransition(scheduled, "Scheduled", "Onlineboard")).toBe(false);
|
||||
});
|
||||
|
||||
it("returns true for active transition on Onlineboard", () => {
|
||||
expect(shouldShowTransition(validItem, "Scheduled", "Onlineboard")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("shouldShowAircraft", () => {
|
||||
it("returns true when actual.title exists", () => {
|
||||
expect(shouldShowAircraft({ aircraft: { actual: { title: "A320" } } })).toBe(true);
|
||||
});
|
||||
|
||||
it("returns true when scheduled.title exists", () => {
|
||||
expect(shouldShowAircraft({ aircraft: { scheduled: { title: "A320" } } })).toBe(true);
|
||||
});
|
||||
|
||||
it("returns true when configuration exists", () => {
|
||||
expect(shouldShowAircraft({ aircraft: { configuration: "C12Y138" } })).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when no aircraft info", () => {
|
||||
expect(shouldShowAircraft({})).toBe(false);
|
||||
expect(shouldShowAircraft({ aircraft: {} })).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when titles are empty strings", () => {
|
||||
expect(shouldShowAircraft({ aircraft: { actual: { title: "" }, scheduled: { title: "" } } })).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("SERVICE_ICON_MAP", () => {
|
||||
it("maps all 8 service IDs", () => {
|
||||
expect(SERVICE_ICON_MAP[1]).toBe("shopping");
|
||||
expect(SERVICE_ICON_MAP[2]).toBe("space");
|
||||
expect(SERVICE_ICON_MAP[3]).toBe("taxi");
|
||||
expect(SERVICE_ICON_MAP[4]).toBe("wifi");
|
||||
expect(SERVICE_ICON_MAP[5]).toBe("gsm");
|
||||
expect(SERVICE_ICON_MAP[6]).toBe("entertaintment");
|
||||
expect(SERVICE_ICON_MAP[7]).toBe("entertaintment");
|
||||
expect(SERVICE_ICON_MAP[8]).toBe("seat_reservation");
|
||||
});
|
||||
});
|
||||
|
||||
describe("MEAL_LINKS", () => {
|
||||
it("has links for Economy, Comfort, Business", () => {
|
||||
expect(MEAL_LINKS.Economy).toContain("meal-type_0");
|
||||
expect(MEAL_LINKS.Comfort).toContain("meal-type_1");
|
||||
expect(MEAL_LINKS.Business).toContain("meal-type_2");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,68 @@
|
||||
import type {
|
||||
FlightStatus,
|
||||
IEquipmentFull,
|
||||
IFlightTransitionItem,
|
||||
MealType,
|
||||
} from "../../types.js";
|
||||
|
||||
export type DetailsViewType = "Onlineboard" | "Schedule";
|
||||
|
||||
/**
|
||||
* Matches Angular's `showBoardProperty` in flight-details-wrapper.component.ts.
|
||||
* Transition panels are hidden for Schedule mode, Cancelled flights,
|
||||
* missing data, or when the transition hasn't started.
|
||||
*/
|
||||
export function shouldShowTransition(
|
||||
item: IFlightTransitionItem | undefined,
|
||||
legStatus: FlightStatus,
|
||||
viewType: DetailsViewType,
|
||||
): boolean {
|
||||
if (viewType === "Schedule") return false;
|
||||
if (legStatus === "Cancelled") return false;
|
||||
if (!item) return false;
|
||||
if (item.status === "Scheduled") return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches Angular's `showAircraft` getter. Shows when actual or scheduled
|
||||
* title exists, or when configuration string is present.
|
||||
*/
|
||||
export function shouldShowAircraft(equipment: Pick<IEquipmentFull, "aircraft">): boolean {
|
||||
const aircraft = equipment.aircraft;
|
||||
if (!aircraft) return false;
|
||||
const title = aircraft.actual?.title || aircraft.scheduled?.title;
|
||||
if (title) return true;
|
||||
if (aircraft.configuration) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service ID → icon filename mapping.
|
||||
* From Angular flight-details-services.component.ts.
|
||||
* IDs 6 and 7 both use the entertaintment icon (typo in original is preserved
|
||||
* because that's how Angular ships the filename).
|
||||
*/
|
||||
export const SERVICE_ICON_MAP: Record<number, string> = {
|
||||
1: "shopping",
|
||||
2: "space",
|
||||
3: "taxi",
|
||||
4: "wifi",
|
||||
5: "gsm",
|
||||
6: "entertaintment",
|
||||
7: "entertaintment",
|
||||
8: "seat_reservation",
|
||||
};
|
||||
|
||||
/** Fallback icon for unknown service IDs. */
|
||||
export const SERVICE_ICON_FALLBACK = "comfort-plus";
|
||||
|
||||
/**
|
||||
* Meal type → aeroflot.ru info page link.
|
||||
* From Angular flight-details-meal.component.ts.
|
||||
*/
|
||||
export const MEAL_LINKS: Record<Exclude<MealType, "Special">, string> = {
|
||||
Economy: "https://www.aeroflot.ru/ru-ru/information/onboard/dining?0000#meal-type_0",
|
||||
Comfort: "https://www.aeroflot.ru/ru-ru/information/onboard/dining?0000#meal-type_1",
|
||||
Business: "https://www.aeroflot.ru/ru-ru/information/onboard/dining?0000#meal-type_2",
|
||||
};
|
||||
@@ -37,6 +37,29 @@
|
||||
"TITLE": "Online Timetable",
|
||||
"YOU_SEARCH": "You searched"
|
||||
},
|
||||
"DETAILS": {
|
||||
"REGISTRATION": "Check-in",
|
||||
"BOARDING": "Boarding",
|
||||
"DEBOARDING": "Deboarding",
|
||||
"AIRCRAFT": "Aircraft",
|
||||
"MEAL": "Meal",
|
||||
"ON_BOARD_SERVICES": "On-board services",
|
||||
"SCHEDULED": "Scheduled",
|
||||
"ACTUAL": "Actual",
|
||||
"MEAL_ECONOMY": "Economy",
|
||||
"MEAL_COMFORT": "Comfort",
|
||||
"MEAL_BUSINESS": "Business",
|
||||
"STATUS_FINISHED": "Finished",
|
||||
"STATUS_EXPECTED": "Expected",
|
||||
"STATUS_IN_PROGRESS": "In progress",
|
||||
"STATUS_SPECIFIED": "Specified",
|
||||
"STATUS_SCHEDULED": "Scheduled",
|
||||
"TERMINAL": "Terminal",
|
||||
"GATE": "Gate",
|
||||
"BAG_BELT": "Baggage belt",
|
||||
"CONFIGURATION": "Configuration",
|
||||
"STATUS": "Status"
|
||||
},
|
||||
"BOARDING-STATUSES": {
|
||||
"Expected": "Expected",
|
||||
"Finished": "Completed",
|
||||
|
||||
@@ -37,6 +37,29 @@
|
||||
"TITLE": "Онлайн-Табло",
|
||||
"YOU_SEARCH": "Вы искали"
|
||||
},
|
||||
"DETAILS": {
|
||||
"REGISTRATION": "Регистрация",
|
||||
"BOARDING": "Посадка",
|
||||
"DEBOARDING": "Высадка",
|
||||
"AIRCRAFT": "Воздушное судно",
|
||||
"MEAL": "Питание",
|
||||
"ON_BOARD_SERVICES": "Услуги на борту",
|
||||
"SCHEDULED": "По расписанию",
|
||||
"ACTUAL": "Фактически",
|
||||
"MEAL_ECONOMY": "Эконом",
|
||||
"MEAL_COMFORT": "Комфорт",
|
||||
"MEAL_BUSINESS": "Бизнес",
|
||||
"STATUS_FINISHED": "Завершена",
|
||||
"STATUS_EXPECTED": "Ожидается",
|
||||
"STATUS_IN_PROGRESS": "В процессе",
|
||||
"STATUS_SPECIFIED": "Назначена",
|
||||
"STATUS_SCHEDULED": "По расписанию",
|
||||
"TERMINAL": "Терминал",
|
||||
"GATE": "Выход",
|
||||
"BAG_BELT": "Лента выдачи багажа",
|
||||
"CONFIGURATION": "Компоновка",
|
||||
"STATUS": "Статус"
|
||||
},
|
||||
"BOARDING-STATUSES": {
|
||||
"Expected": "Ожидается",
|
||||
"Finished": "Закончена",
|
||||
|
||||
Reference in New Issue
Block a user