Major WIP state machine

This commit is contained in:
2026-03-24 11:22:20 -04:00
parent 423023d3d9
commit bb6597ff76
16 changed files with 5781 additions and 234 deletions
+86 -29
View File
@@ -29,6 +29,7 @@
⚙️ Admin
</button>
<div class="dropdown-menu" id="adminDropdownMenu">
<a href="#" onclick="window.location.href = '/atc'">🎛️ ATC View</a>
<a href="#" onclick="window.location.href = '/reports'">📊 Reports</a>
<a href="#" onclick="openUserAircraftModal(); closeAdminDropdown()" id="user-aircraft-dropdown">✈️ User Aircraft</a>
<a href="#" onclick="openUserManagementModal(); closeAdminDropdown()" id="user-management-dropdown" style="display: none;">👥 User Management</a>
@@ -1867,10 +1868,15 @@
try {
// Load PPR departures, local flight departures, and airport departures simultaneously
const [pprResponse, localResponse, depResponse] = await Promise.all([
const [pprResponse, localBookedOutResponse, localOutGroundResponse, localLocalResponse, localCircuitResponse, depBookedOutResponse, depOutGroundResponse, depLocalResponse] = await Promise.all([
authenticatedFetch('/api/v1/pprs/?limit=1000'),
authenticatedFetch('/api/v1/local-flights/?status=BOOKED_OUT&limit=1000'),
authenticatedFetch('/api/v1/departures/?status=BOOKED_OUT&limit=1000')
authenticatedFetch('/api/v1/local-flights/?status=GROUND&limit=1000'),
authenticatedFetch('/api/v1/local-flights/?status=LOCAL&limit=1000'),
authenticatedFetch('/api/v1/local-flights/?status=CIRCUIT&limit=1000'),
authenticatedFetch('/api/v1/departures/?status=BOOKED_OUT&limit=1000'),
authenticatedFetch('/api/v1/departures/?status=GROUND&limit=1000'),
authenticatedFetch('/api/v1/departures/?status=LOCAL&limit=1000')
]);
if (!pprResponse.ok) {
@@ -1878,6 +1884,18 @@
}
const allPPRs = await pprResponse.json();
const localBookedOut = localBookedOutResponse.ok ? await localBookedOutResponse.json() : [];
const localOutGround = localOutGroundResponse.ok ? await localOutGroundResponse.json() : [];
const localLocal = localLocalResponse.ok ? await localLocalResponse.json() : [];
const localCircuit = localCircuitResponse.ok ? await localCircuitResponse.json() : [];
const depBookedOut = depBookedOutResponse.ok ? await depBookedOutResponse.json() : [];
const depOutGround = depOutGroundResponse.ok ? await depOutGroundResponse.json() : [];
const depLocal = depLocalResponse.ok ? await depLocalResponse.json() : [];
// Combine local flights
const allLocalFlights = [...localBookedOut, ...localOutGround, ...localLocal, ...localCircuit];
// Combine departures
const allDepartures = [...depBookedOut, ...depOutGround, ...depLocal];
const today = new Date().toISOString().split('T')[0];
// Filter for PPR departures with ETD today and LANDED status only
@@ -1890,33 +1908,26 @@
return etdDate === today;
});
// Add local flights (BOOKED_OUT status - ready to go) - only those booked out today
if (localResponse.ok) {
const localFlights = await localResponse.json();
const today = new Date().toISOString().split('T')[0];
const localDepartures = localFlights
.filter(flight => {
// Only include flights booked out today (created_dt)
if (!flight.created_dt) return false;
const createdDate = flight.created_dt.split('T')[0];
return createdDate === today;
})
.map(flight => ({
...flight,
isLocalFlight: true // Flag to distinguish from PPR
}));
departures.push(...localDepartures);
}
// Add departures to other airports (BOOKED_OUT status)
if (depResponse.ok) {
const depFlights = await depResponse.json();
const depDepartures = depFlights.map(flight => ({
// Add local flights (BOOKED_OUT, GROUND, and LOCAL status - ready to go) - only those booked out today
const localDepartures = allLocalFlights
.filter(flight => {
// Only include flights booked out today (created_dt)
if (!flight.created_dt) return false;
const createdDate = flight.created_dt.split('T')[0];
return createdDate === today;
})
.map(flight => ({
...flight,
isDeparture: true // Flag to distinguish from PPR
isLocalFlight: true // Flag to distinguish from PPR
}));
departures.push(...depDepartures);
}
departures.push(...localDepartures);
// Add departures to other airports (BOOKED_OUT, GROUND, and LOCAL status)
const depDepartures = allDepartures.map(flight => ({
...flight,
isDeparture: true // Flag to distinguish from PPR
}));
departures.push(...depDepartures);
displayDepartures(departures);
} catch (error) {
@@ -2584,7 +2595,15 @@
// Action buttons for local flight
if (flight.status === 'BOOKED_OUT') {
actionButtons = `
<button class="btn btn-primary btn-icon" onclick="event.stopPropagation(); currentLocalFlightId = ${flight.id}; showTimestampModal('DEPARTED', ${flight.id}, true)" title="Mark as Departed">
<button class="btn btn-warning btn-icon" onclick="event.stopPropagation(); currentLocalFlightId = ${flight.id}; showTimestampModal('GROUND', ${flight.id}, true)" title="Contact Pilot">
CONTACT
</button>
`;
} else if (flight.status === 'GROUND') {
const takeoffStatus = flight.flight_type === 'CIRCUITS' ? 'CIRCUIT' : 'LOCAL';
const takeoffTitle = flight.flight_type === 'CIRCUITS' ? 'Mark as Circuit' : 'Mark as Local';
actionButtons = `
<button class="btn btn-primary btn-icon" onclick="event.stopPropagation(); currentLocalFlightId = ${flight.id}; showTimestampModal('${takeoffStatus}', ${flight.id}, true)" title="${takeoffTitle}">
TAKE OFF
</button>
`;
@@ -2599,6 +2618,26 @@
LAND
</button>
`;
} else if (flight.status === 'LOCAL') {
actionButtons = `
<button class="btn btn-info btn-icon" onclick="event.stopPropagation(); currentLocalFlightId = ${flight.id}; updateLocalFlightStatusFromTable(${flight.id}, 'CIRCUIT')" title="Rejoin Circuit">
REJOIN
</button>
`;
} else if (flight.status === 'CIRCUIT') {
// Circuit traffic - show LOCAL, T&G and LAND buttons
let circuitButton = `<button class="btn btn-info btn-icon" onclick="event.stopPropagation(); currentLocalFlightId = ${flight.id}; showCircuitModal()" title="Record Touch & Go">
T&G
</button>`;
actionButtons = `
<button class="btn btn-warning btn-icon" onclick="event.stopPropagation(); currentLocalFlightId = ${flight.id}; updateLocalFlightStatusFromTable(${flight.id}, 'LOCAL')" title="Move to Local Area">
LOCAL
</button>
${circuitButton}
<button class="btn btn-success btn-icon" onclick="event.stopPropagation(); currentLocalFlightId = ${flight.id}; showTimestampModal('LANDED', ${flight.id}, true)" title="Mark as Landed">
LAND
</button>
`;
} else {
actionButtons = '<span style="color: #999;">-</span>';
}
@@ -2622,10 +2661,22 @@
// Action buttons for departure
if (flight.status === 'BOOKED_OUT') {
actionButtons = `
<button class="btn btn-primary btn-icon" onclick="event.stopPropagation(); currentDepartureId = ${flight.id}; showTimestampModal('DEPARTED', ${flight.id}, false, true)" title="Mark as Departed">
<button class="btn btn-warning btn-icon" onclick="event.stopPropagation(); currentDepartureId = ${flight.id}; showTimestampModal('GROUND', ${flight.id}, false, true)" title="Contact Pilot">
CONTACT
</button>
`;
} else if (flight.status === 'GROUND') {
actionButtons = `
<button class="btn btn-primary btn-icon" onclick="event.stopPropagation(); currentDepartureId = ${flight.id}; showTimestampModal('LOCAL', ${flight.id}, false, true)" title="Mark as Local">
TAKE OFF
</button>
`;
} else if (flight.status === 'LOCAL') {
actionButtons = `
<button class="btn btn-success btn-icon" onclick="event.stopPropagation(); currentDepartureId = ${flight.id}; showTimestampModal('DEPARTED', ${flight.id}, false, true)" title="Mark as Departed">
QSY
</button>
`;
} else if (flight.status === 'DEPARTED') {
actionButtons = '<span style="color: #999;">Departed</span>';
} else {
@@ -2965,6 +3016,12 @@
} else if (status === 'DEPARTED') {
modalTitle.textContent = 'Confirm Departure Time';
submitBtn.textContent = '🛫 Confirm Departure';
} else if (status === 'GROUND') {
modalTitle.textContent = 'Confirm Contact Time';
submitBtn.textContent = '📞 Confirm Contact';
} else if (status === 'LOCAL') {
modalTitle.textContent = 'Confirm Takeoff Time';
submitBtn.textContent = '🛫 Confirm Takeoff';
}
// Set default timestamp to current time
+5543
View File
File diff suppressed because it is too large Load Diff