Added airport data to map
This commit is contained in:
40
ui/src/lib/airport.ts
Normal file
40
ui/src/lib/airport.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Airport, AirportCategory, Bounds, GetAirportsResponse } from '@lib/airport.types.ts';
|
||||
import { getRequest } from '@lib/index.ts';
|
||||
|
||||
export async function getAirport({ icao }: { icao: string }): Promise<Airport> {
|
||||
const response = await getRequest(`airports/${icao}`);
|
||||
return response?.json() || {};
|
||||
}
|
||||
|
||||
interface GetAirportsParameters {
|
||||
icaos?: string[];
|
||||
name?: string;
|
||||
categories?: AirportCategory[];
|
||||
bounds?: Bounds;
|
||||
metars?: boolean;
|
||||
page?: number;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export async function getAirports({
|
||||
icaos,
|
||||
name,
|
||||
categories,
|
||||
bounds,
|
||||
metars = false,
|
||||
limit = 1000,
|
||||
page = 1
|
||||
}: GetAirportsParameters): Promise<GetAirportsResponse> {
|
||||
const response = await getRequest('airports', {
|
||||
bounds: bounds
|
||||
? `${bounds?.northEast.lat},${bounds?.northEast.lon},${bounds?.southWest.lat},${bounds?.southWest.lon}`
|
||||
: undefined,
|
||||
categories: categories ?? undefined,
|
||||
icaos: icaos ?? undefined,
|
||||
name: name ?? undefined,
|
||||
metars: metars ?? undefined,
|
||||
limit,
|
||||
page
|
||||
});
|
||||
return response?.json() || { data: [] };
|
||||
}
|
||||
93
ui/src/lib/airport.types.ts
Normal file
93
ui/src/lib/airport.types.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { Metar } from './metar.types';
|
||||
|
||||
export enum AirportCategory {
|
||||
SMALL = 'small_airport',
|
||||
MEDIUM = 'medium_airport',
|
||||
LARGE = 'large_airport',
|
||||
HELIPORT = 'heliport',
|
||||
BALLOONPORT = 'balloon_port',
|
||||
CLOSED = 'closed',
|
||||
SEAPLANE = 'seaplane_base',
|
||||
UNKNOWN = 'unknown'
|
||||
}
|
||||
|
||||
export function airportCategoryToText(category: AirportCategory): string {
|
||||
switch (category) {
|
||||
case AirportCategory.SMALL:
|
||||
return 'Small';
|
||||
case AirportCategory.MEDIUM:
|
||||
return 'Medium';
|
||||
case AirportCategory.LARGE:
|
||||
return 'Large';
|
||||
case AirportCategory.HELIPORT:
|
||||
return 'Helipad';
|
||||
case AirportCategory.CLOSED:
|
||||
return 'Closed';
|
||||
case AirportCategory.SEAPLANE:
|
||||
return 'Seaplane Base';
|
||||
case AirportCategory.BALLOONPORT:
|
||||
return 'Balloon Port';
|
||||
default:
|
||||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
|
||||
export enum AirportOrderField {
|
||||
ICAO = 'icao',
|
||||
NAME = 'name',
|
||||
CATEGORY = 'category',
|
||||
CONTINENT = 'continent',
|
||||
ISO_COUNTRY = 'iso_country',
|
||||
ISO_REGION = 'iso_region',
|
||||
MUNICIPALITY = 'municipality'
|
||||
}
|
||||
|
||||
export interface Bounds {
|
||||
northEast: Coordinate;
|
||||
southWest: Coordinate;
|
||||
}
|
||||
|
||||
export interface Coordinate {
|
||||
lat: number;
|
||||
lon: number;
|
||||
}
|
||||
|
||||
export interface Airport {
|
||||
icao: string;
|
||||
iata: string;
|
||||
local: string;
|
||||
name: string;
|
||||
category: AirportCategory;
|
||||
iso_country: string;
|
||||
iso_region: string;
|
||||
municipality: string;
|
||||
elevation_ft: number;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
has_tower: boolean;
|
||||
has_beacon: boolean;
|
||||
has_metar: boolean;
|
||||
public: boolean;
|
||||
runways: Runway[];
|
||||
frequencies: Frequency[];
|
||||
latest_metar?: Metar;
|
||||
}
|
||||
|
||||
export interface Runway {
|
||||
id: string;
|
||||
length_ft: number;
|
||||
width_ft: number;
|
||||
surface: string;
|
||||
}
|
||||
|
||||
export interface Frequency {
|
||||
id: string;
|
||||
frequency_mhz: number;
|
||||
}
|
||||
|
||||
export interface GetAirportsResponse {
|
||||
data: Airport[];
|
||||
limit: number;
|
||||
page: number;
|
||||
total: number;
|
||||
}
|
||||
72
ui/src/lib/index.ts
Normal file
72
ui/src/lib/index.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
// const serviceHost = process.env.SERVICE_HOST || 'http://localhost';
|
||||
// const servicePort = process.env.SERVICE_PORT || 5000;'
|
||||
// const baseURL = `${serviceHost}:${servicePort}`;
|
||||
const baseUrl = 'http://localhost:5000';
|
||||
|
||||
export async function getRequest(endpoint: string, params: Record<string, any> = {}): Promise<Response> {
|
||||
Object.keys(params).forEach((key) => params[key] === undefined && delete params[key]);
|
||||
const urlParams = new URLSearchParams(params);
|
||||
const url = urlParams && urlParams.size > 0 ? `${baseUrl}/${endpoint}?${urlParams}` : `${baseUrl}/${endpoint}`;
|
||||
return await fetch(url, {
|
||||
method: 'GET',
|
||||
credentials: 'include'
|
||||
});
|
||||
}
|
||||
|
||||
interface PostOptions {
|
||||
headers?: Record<string, any>;
|
||||
type?: 'json' | 'form';
|
||||
}
|
||||
|
||||
export async function postRequest(endpoint: string, body?: any, options?: PostOptions): Promise<Response> {
|
||||
const url = `${baseUrl}/${endpoint}`;
|
||||
let response;
|
||||
if (body && (!options?.type || options.type === 'json')) {
|
||||
response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
} else {
|
||||
response = await fetch(url, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body
|
||||
});
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function putRequest(endpoint: string, body?: any, options?: PostOptions): Promise<Response> {
|
||||
const url = `${baseUrl}/${endpoint}`;
|
||||
let response;
|
||||
if (body && (!options?.type || options.type === 'json')) {
|
||||
response = await fetch(url, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
} else {
|
||||
response = await fetch(url, {
|
||||
method: 'PUT',
|
||||
credentials: 'include',
|
||||
body
|
||||
});
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function deleteRequest(endpoint: string): Promise<Response> {
|
||||
const url = `${baseUrl}/${endpoint}`;
|
||||
const response = await fetch(url, {
|
||||
method: 'DELETE',
|
||||
credentials: 'include'
|
||||
});
|
||||
return response;
|
||||
}
|
||||
43
ui/src/lib/metar.types.ts
Normal file
43
ui/src/lib/metar.types.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
export interface SkyCondition {
|
||||
sky_cover: string;
|
||||
cloud_base_ft_agl: number;
|
||||
}
|
||||
|
||||
export interface QualityControlFlags {
|
||||
auto: boolean;
|
||||
auto_station_without_precipitation: boolean;
|
||||
auto_station_with_precipication: boolean;
|
||||
maintenance_indicator_on: boolean;
|
||||
corrected: boolean;
|
||||
}
|
||||
|
||||
export interface RunwayVisualRange {
|
||||
runway: string;
|
||||
visibility_ft: string;
|
||||
variable_visibility_high_ft: string;
|
||||
variable_visibility_low_ft: string;
|
||||
}
|
||||
|
||||
export interface Metar {
|
||||
raw_text: string;
|
||||
station_id: string;
|
||||
observation_time: string;
|
||||
temp_c: number;
|
||||
dewpoint_c: number;
|
||||
wind_dir_degrees: string;
|
||||
wind_speed_kt: number;
|
||||
wind_gust_kt: number;
|
||||
variable_wind_dir_degrees: string;
|
||||
visibility_statute_mi: string;
|
||||
runway_visual_range: RunwayVisualRange[];
|
||||
altim_in_hg: number;
|
||||
sea_level_pressure_mb: number;
|
||||
quality_control_flags: QualityControlFlags;
|
||||
weather_phenomena: string[];
|
||||
sky_condition: SkyCondition[];
|
||||
flight_category: 'VFR' | 'MVFR' | 'LIFR' | 'IFR' | 'UNKN';
|
||||
three_hr_pressure_tendency_mb: number;
|
||||
max_t_c: number;
|
||||
min_t_c: number;
|
||||
precip_in: number;
|
||||
}
|
||||
Reference in New Issue
Block a user