diff --git a/web/admin.html b/web/admin.html
index 8026299..219c9a8 100644
--- a/web/admin.html
+++ b/web/admin.html
@@ -1256,40 +1256,57 @@
document.getElementById('departures-loading').style.display = 'none';
}
- function displayArrivals(arrivals) {
+ // ICAO code to airport name cache
+ const airportNameCache = {};
+
+ async function getAirportDisplay(code) {
+ if (!code || code.length !== 4 || !/^[A-Z]{4}$/.test(code)) return code;
+ if (airportNameCache[code]) return `${code}
${airportNameCache[code]}`;
+ try {
+ const resp = await authenticatedFetch(`/api/v1/airport/lookup/${code}`);
+ if (resp.ok) {
+ const data = await resp.json();
+ if (data && data.length && data[0].name) {
+ airportNameCache[code] = data[0].name;
+ return `${code}
${data[0].name}`;
+ }
+ }
+ } catch {}
+ return code;
+ }
+
+ async function displayArrivals(arrivals) {
const tbody = document.getElementById('arrivals-table-body');
const recordCount = document.getElementById('arrivals-count');
-
recordCount.textContent = arrivals.length;
-
if (arrivals.length === 0) {
document.getElementById('arrivals-no-data').style.display = 'block';
return;
}
-
tbody.innerHTML = '';
document.getElementById('arrivals-table-content').style.display = 'block';
-
- arrivals.forEach(ppr => {
+ for (const ppr of arrivals) {
const row = document.createElement('tr');
row.onclick = () => openPPRModal(ppr.id);
-
// Create notes indicator if notes exist
const notesIndicator = ppr.notes && ppr.notes.trim() ?
`
📝
${ppr.notes}
` : '';
-
// Display callsign as main item if present, registration below; otherwise show registration
const aircraftDisplay = ppr.ac_call && ppr.ac_call.trim() ?
`${ppr.ac_call}
${ppr.ac_reg}` :
`${ppr.ac_reg}`;
-
+ // Lookup airport name for in_from
+ let fromDisplay = ppr.in_from;
+ if (ppr.in_from && ppr.in_from.length === 4 && /^[A-Z]{4}$/.test(ppr.in_from)) {
+ fromDisplay = await getAirportDisplay(ppr.in_from);
+ }
row.innerHTML = `
${aircraftDisplay}${notesIndicator} |
${ppr.ac_type} |
- ${ppr.in_from} |
+ ${fromDisplay} |
${formatTimeOnly(ppr.eta)} |
${ppr.pob_in} |
${ppr.fuel || '-'} |
@@ -1302,45 +1319,42 @@
`;
-
tbody.appendChild(row);
- });
+ }
}
- function displayDepartures(departures) {
+ async function displayDepartures(departures) {
const tbody = document.getElementById('departures-table-body');
const recordCount = document.getElementById('departures-count');
-
recordCount.textContent = departures.length;
-
if (departures.length === 0) {
document.getElementById('departures-no-data').style.display = 'block';
return;
}
-
tbody.innerHTML = '';
document.getElementById('departures-table-content').style.display = 'block';
-
- departures.forEach(ppr => {
+ for (const ppr of departures) {
const row = document.createElement('tr');
row.onclick = () => openPPRModal(ppr.id);
-
// Create notes indicator if notes exist
const notesIndicator = ppr.notes && ppr.notes.trim() ?
`
📝
${ppr.notes}
` : '';
-
// Display callsign as main item if present, registration below; otherwise show registration
const aircraftDisplay = ppr.ac_call && ppr.ac_call.trim() ?
`${ppr.ac_call}
${ppr.ac_reg}` :
`${ppr.ac_reg}`;
-
+ // Lookup airport name for out_to
+ let toDisplay = ppr.out_to || '-';
+ if (ppr.out_to && ppr.out_to.length === 4 && /^[A-Z]{4}$/.test(ppr.out_to)) {
+ toDisplay = await getAirportDisplay(ppr.out_to);
+ }
row.innerHTML = `
${aircraftDisplay}${notesIndicator} |
${ppr.ac_type} |
- ${ppr.out_to || '-'} |
+ ${toDisplay} |
${ppr.etd ? formatTimeOnly(ppr.etd) : '-'} |
${ppr.pob_out || ppr.pob_in} |
${ppr.fuel || '-'} |
@@ -1354,9 +1368,8 @@
`;
-
tbody.appendChild(row);
- });
+ }
}
function formatTimeOnly(dateStr) {
diff --git a/web/index.html b/web/index.html
index f23a683..af05fb0 100644
--- a/web/index.html
+++ b/web/index.html
@@ -252,13 +252,40 @@
return `${status}`;
}
- // Create PPR item HTML
- function createPPRItem(ppr) {
+ // ICAO code to airport name cache
+ const airportNameCache = {};
+
+ async function getAirportDisplay(code) {
+ if (!code || code.length !== 4 || !/^[A-Z]{4}$/.test(code)) return code;
+ if (airportNameCache[code]) return `${code}
${airportNameCache[code]}`;
+ try {
+ const resp = await fetch(`/api/v1/airport/lookup/${code}`);
+ if (resp.ok) {
+ const data = await resp.json();
+ if (data && data.length && data[0].name) {
+ airportNameCache[code] = data[0].name;
+ return `${code}
${data[0].name}`;
+ }
+ }
+ } catch {}
+ return code;
+ }
+
+ // Create PPR item HTML (async)
+ async function createPPRItem(ppr) {
// Display callsign as main item if present, registration below; otherwise show registration
const aircraftDisplay = ppr.ac_call && ppr.ac_call.trim() ?
`${ppr.ac_call}
${ppr.ac_reg}` :
ppr.ac_reg;
-
+ // Lookup airport name for in_from/out_to
+ let fromDisplay = ppr.in_from;
+ if (ppr.in_from && ppr.in_from.length === 4 && /^[A-Z]{4}$/.test(ppr.in_from)) {
+ fromDisplay = await getAirportDisplay(ppr.in_from);
+ }
+ let toDisplay = ppr.out_to;
+ if (ppr.out_to && ppr.out_to.length === 4 && /^[A-Z]{4}$/.test(ppr.out_to)) {
+ toDisplay = await getAirportDisplay(ppr.out_to);
+ }
return `
@@ -269,6 +296,14 @@
Type
${ppr.ac_type}
+
+ From
+ ${fromDisplay || '-'}
+
+
+ To
+ ${toDisplay || '-'}
+
Time
${formatDateTime(ppr.eta || ppr.etd)}
@@ -298,19 +333,21 @@
try {
const response = await fetch('/api/v1/public/arrivals');
const arrivals = await response.json();
-
const loadingEl = document.getElementById('arrivals-loading');
const listEl = document.getElementById('arrivals-list');
const countEl = document.getElementById('arrivals-count');
-
loadingEl.style.display = 'none';
listEl.style.display = 'block';
-
if (arrivals.length === 0) {
listEl.innerHTML = createNoDataMessage('arrivals');
countEl.textContent = '0 flights';
} else {
- listEl.innerHTML = arrivals.map(createPPRItem).join('');
+ // Render each item async
+ const htmlArr = [];
+ for (const ppr of arrivals) {
+ htmlArr.push(await createPPRItem(ppr));
+ }
+ listEl.innerHTML = htmlArr.join('');
countEl.textContent = `${arrivals.length} flight${arrivals.length !== 1 ? 's' : ''}`;
}
} catch (error) {
@@ -330,19 +367,21 @@
try {
const response = await fetch('/api/v1/public/departures');
const departures = await response.json();
-
const loadingEl = document.getElementById('departures-loading');
const listEl = document.getElementById('departures-list');
const countEl = document.getElementById('departures-count');
-
loadingEl.style.display = 'none';
listEl.style.display = 'block';
-
if (departures.length === 0) {
listEl.innerHTML = createNoDataMessage('departures');
countEl.textContent = '0 flights';
} else {
- listEl.innerHTML = departures.map(createPPRItem).join('');
+ // Render each item async
+ const htmlArr = [];
+ for (const ppr of departures) {
+ htmlArr.push(await createPPRItem(ppr));
+ }
+ listEl.innerHTML = htmlArr.join('');
countEl.textContent = `${departures.length} flight${departures.length !== 1 ? 's' : ''}`;
}
} catch (error) {