ICAO code expansion
This commit is contained in:
@@ -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}<br><span style="font-size:0.8em;color:#666;font-style:italic;">${airportNameCache[code]}</span>`;
|
||||
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}<br><span style="font-size:0.8em;color:#666;font-style:italic;">${data[0].name}</span>`;
|
||||
}
|
||||
}
|
||||
} 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() ?
|
||||
`<span class="notes-tooltip">
|
||||
<span class="notes-indicator">📝</span>
|
||||
<span class="tooltip-text">${ppr.notes}</span>
|
||||
</span>` : '';
|
||||
|
||||
// Display callsign as main item if present, registration below; otherwise show registration
|
||||
const aircraftDisplay = ppr.ac_call && ppr.ac_call.trim() ?
|
||||
`<strong>${ppr.ac_call}</strong><br><span style="font-size: 0.8em; color: #666; font-style: italic;">${ppr.ac_reg}</span>` :
|
||||
`<strong>${ppr.ac_reg}</strong>`;
|
||||
|
||||
// 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 = `
|
||||
<td>${aircraftDisplay}${notesIndicator}</td>
|
||||
<td>${ppr.ac_type}</td>
|
||||
<td>${ppr.in_from}</td>
|
||||
<td>${fromDisplay}</td>
|
||||
<td>${formatTimeOnly(ppr.eta)}</td>
|
||||
<td>${ppr.pob_in}</td>
|
||||
<td>${ppr.fuel || '-'}</td>
|
||||
@@ -1302,45 +1319,42 @@
|
||||
</button>
|
||||
</td>
|
||||
`;
|
||||
|
||||
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() ?
|
||||
`<span class="notes-tooltip">
|
||||
<span class="notes-indicator">📝</span>
|
||||
<span class="tooltip-text">${ppr.notes}</span>
|
||||
</span>` : '';
|
||||
|
||||
// Display callsign as main item if present, registration below; otherwise show registration
|
||||
const aircraftDisplay = ppr.ac_call && ppr.ac_call.trim() ?
|
||||
`<strong>${ppr.ac_call}</strong><br><span style="font-size: 0.8em; color: #666; font-style: italic;">${ppr.ac_reg}</span>` :
|
||||
`<strong>${ppr.ac_reg}</strong>`;
|
||||
|
||||
// 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 = `
|
||||
<td>${aircraftDisplay}${notesIndicator}</td>
|
||||
<td>${ppr.ac_type}</td>
|
||||
<td>${ppr.out_to || '-'}</td>
|
||||
<td>${toDisplay}</td>
|
||||
<td>${ppr.etd ? formatTimeOnly(ppr.etd) : '-'}</td>
|
||||
<td>${ppr.pob_out || ppr.pob_in}</td>
|
||||
<td>${ppr.fuel || '-'}</td>
|
||||
@@ -1354,9 +1368,8 @@
|
||||
</button>
|
||||
</td>
|
||||
`;
|
||||
|
||||
tbody.appendChild(row);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function formatTimeOnly(dateStr) {
|
||||
|
||||
@@ -252,13 +252,40 @@
|
||||
return `<span class="status ${status.toLowerCase()}">${status}</span>`;
|
||||
}
|
||||
|
||||
// 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}<br><span style="font-size:0.8em;color:#888;font-style:italic;">${airportNameCache[code]}</span>`;
|
||||
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}<br><span style="font-size:0.8em;color:#888;font-style:italic;">${data[0].name}</span>`;
|
||||
}
|
||||
}
|
||||
} 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}<br><span style="font-size: 0.85em; color: #888; font-style: italic;">${ppr.ac_reg}</span>` :
|
||||
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 `
|
||||
<div class="ppr-item">
|
||||
<div class="ppr-field">
|
||||
@@ -269,6 +296,14 @@
|
||||
<strong>Type</strong>
|
||||
<span>${ppr.ac_type}</span>
|
||||
</div>
|
||||
<div class="ppr-field">
|
||||
<strong>From</strong>
|
||||
<span>${fromDisplay || '-'}</span>
|
||||
</div>
|
||||
<div class="ppr-field">
|
||||
<strong>To</strong>
|
||||
<span>${toDisplay || '-'}</span>
|
||||
</div>
|
||||
<div class="ppr-field">
|
||||
<strong>Time</strong>
|
||||
<span>${formatDateTime(ppr.eta || ppr.etd)}</span>
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user