Files
calco2la.to-php/public/js/calco2lato.js
2025-10-02 09:45:00 +02:00

100 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Lightweight client that talks to your PHP proxy via fetch.
// Returns Airport/Flight objects with helpful methods.
export class Airport {
constructor(dto) {
Object.assign(this, dto);
}
get display() {
const code = this.iata || this.icao || '';
return `${code} ${this.name}${this.city ? ' (' + this.city + ')' : ''}`;
}
}
export class Flight {
constructor(dto) {
Object.assign(this, dto);
}
summary() {
const s = [];
if (this.departureAirport?.iata) s.push(this.departureAirport.iata);
if (this.arrivalAirport?.iata) s.push(this.arrivalAirport.iata);
const route = s.length ? s.join(' → ') : 'Flight';
const co2 = this.emissions?.co2_total ?? this.co2 ?? null;
return co2 != null ? `${route}: ${co2} kg CO₂e` : route;
}
}
export class Calco2latoClient {
/**
* @param {string} proxyUrl e.g. "/api-proxy.php"
* @param {object} [options]
* @param {number} [options.timeoutMs=10000]
*/
constructor(proxyUrl, { timeoutMs = 10000 } = {}) {
this.proxyUrl = proxyUrl;
this.timeoutMs = timeoutMs;
}
async _fetchJSON(payloadOrQuery) {
const { method = 'GET', query = null, body = null } = payloadOrQuery;
const url = new URL(this.proxyUrl, window.location.origin);
if (query) {
for (const [k, v] of Object.entries(query)) {
if (v !== undefined && v !== null) url.searchParams.set(k, String(v));
}
}
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), this.timeoutMs);
try {
const res = await fetch(url.toString(), {
method,
headers: body ? { 'Content-Type': 'application/json' } : undefined,
body: body ? JSON.stringify(body) : undefined,
credentials: 'include',
signal: ctrl.signal,
});
const data = await res.json().catch(() => ({}));
if (!res.ok) {
throw new Error(data?.error || `HTTP ${res.status}`);
}
return data;
} finally {
clearTimeout(t);
}
}
// ---------- Airports ----------
/**
* @param {string} q
* @param {number} [limit=20]
* @param {number} [offset=1]
* @returns {Promise<Airport[]>}
*/
async searchAirports(q, limit = 20, offset = 1) {
const data = await this._fetchJSON({
method: 'GET',
query: { endpoint: 'airports.search', iata: q, per_page: limit, page: offset }
});
const items = Array.isArray(data?.results) ? data.results : (Array.isArray(data) ? data : []);
return items.map(a => new Airport(a));
}
// ---------- Flights ----------
/**
* @param {object} params e.g. { origin: "FRA", destination: "LHR", date: "2025-09-20", pax: 1, cabin: "economy" }
* @returns {Promise<Flight>}
*/
async estimateFlight(params) {
const data = await this._fetchJSON({
method: 'POST',
body: { endpoint: 'flights.estimate', params }
});
return new Flight(data.flights[0]);
}
}