f61e050e8c
API functions now build the full localized path matching the Angular
EndpointService pattern (/api/flights/{version}/{locale}/{endpoint}).
The dev proxy forwards /api and /flights to the test backend.
119 lines
3.5 KiB
TypeScript
119 lines
3.5 KiB
TypeScript
/**
|
|
* Flights Map API functions.
|
|
*
|
|
* Pure functions -- each takes an `ApiClient` as a parameter (dependency
|
|
* injection). No React hooks, no context, no side effects.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
import type { ApiClient } from "@/shared/api/client.js";
|
|
import type {
|
|
FlightsMapSearchParams,
|
|
FlightsMapCalendarParams,
|
|
IDestinationsResponse,
|
|
IFlightsMapDaysResponse,
|
|
} from "./types.js";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// API functions
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Search flight destinations/routes on the map.
|
|
* Maps to: `GET destinations/1?departure=...&arrival=...&dateFrom=...&dateTo=...&connections=0`
|
|
*/
|
|
export async function searchDestinations(
|
|
client: ApiClient,
|
|
params: FlightsMapSearchParams,
|
|
): Promise<IDestinationsResponse> {
|
|
const query: Record<string, string> = {
|
|
departure: params.departure,
|
|
dateFrom: params.dateFrom,
|
|
dateTo: params.dateTo,
|
|
connections: String(params.connections ?? 0),
|
|
};
|
|
|
|
if (params.arrival) {
|
|
query["arrival"] = params.arrival;
|
|
}
|
|
|
|
return client.get<IDestinationsResponse>(`flights/1/${client.locale}/destinations`, query);
|
|
}
|
|
|
|
/**
|
|
* Get available calendar days for a flights-map route.
|
|
* Maps to: `GET days/{date}/200/{routeSegment}/flights-map/v1`
|
|
*
|
|
* The `days` response field is a binary string ("0110...") where each
|
|
* character represents one day starting from `date`. We parse it into
|
|
* an array of available date strings.
|
|
*/
|
|
export async function getFlightsMapCalendar(
|
|
client: ApiClient,
|
|
params: FlightsMapCalendarParams,
|
|
): Promise<string[]> {
|
|
const routeSegment = buildRouteSegment(params);
|
|
if (!routeSegment) return [];
|
|
|
|
const path = `flights/v1/${client.locale}/days/${params.date}/200/${routeSegment}/flights-map/`;
|
|
const response = await client.get<IFlightsMapDaysResponse>(path);
|
|
return parseBinaryDays(response.days, params.date);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Internal helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function buildRouteSegment(params: FlightsMapCalendarParams): string | null {
|
|
if (params.departure && params.arrival) {
|
|
return params.connections
|
|
? `connections/${params.departure}-${params.arrival}-1`
|
|
: `route/${params.departure}-${params.arrival}`;
|
|
}
|
|
|
|
if (params.departure) {
|
|
return `departure/${params.departure}`;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Parse a binary days string ("01101...") into an array of ISO date strings
|
|
* representing the available (=1) days, starting from `startDate`.
|
|
*/
|
|
function parseBinaryDays(days: string, startDate: string): string[] {
|
|
if (!days) return [];
|
|
|
|
const result: string[] = [];
|
|
const start = parseYyyymmdd(startDate);
|
|
if (!start) return [];
|
|
|
|
for (let i = 0; i < days.length; i++) {
|
|
if (days[i] === "1") {
|
|
const d = new Date(start);
|
|
d.setDate(d.getDate() + i);
|
|
result.push(formatYyyymmdd(d));
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
function parseYyyymmdd(s: string): Date | null {
|
|
if (s.length !== 8) return null;
|
|
const year = Number(s.slice(0, 4));
|
|
const month = Number(s.slice(4, 6)) - 1;
|
|
const day = Number(s.slice(6, 8));
|
|
const d = new Date(year, month, day);
|
|
return Number.isNaN(d.getTime()) ? null : d;
|
|
}
|
|
|
|
function formatYyyymmdd(d: Date): string {
|
|
const y = d.getFullYear().toString();
|
|
const m = (d.getMonth() + 1).toString().padStart(2, "0");
|
|
const day = d.getDate().toString().padStart(2, "0");
|
|
return `${y}${m}${day}`;
|
|
}
|