From bcd582aee5d49354bef626b5adb577d024bd7a8b Mon Sep 17 00:00:00 2001 From: James Pattinson Date: Fri, 19 Dec 2025 08:53:47 -0500 Subject: [PATCH] Filtering enhancements --- web/reports.html | 336 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 263 insertions(+), 73 deletions(-) diff --git a/web/reports.html b/web/reports.html index c0f5339..37bbca3 100644 --- a/web/reports.html +++ b/web/reports.html @@ -378,18 +378,26 @@
-
-
- - +
+ +
+ + + +
-
- - + + + -
- - @@ -399,15 +407,19 @@
-
- - + + +
+ +
-
- -
@@ -417,67 +429,69 @@
📊 Movements Summary
-
- -
-
PPR Movements
-
-
-
Arrivals (Landings)
-
0
+
+
+ +
+
PPR Movements
+
+
+
Arrivals
+
0
+
+
+
Departures
+
0
+
+
+
Total
+
0
+
-
-
Departures (Takeoffs)
-
0
-
-
-
PPR Total
-
0
+
+ + +
+
Non-PPR Movements
+
+
+
Local
+
0
+
+
+
Circuits
+
0
+
+
+
Arrivals
+
0
+
+
+
Departures
+
0
+
+
+
Overflights
+
0
+
+
+
Total
+
0
+
- -
-
Non-PPR Movements
-
-
-
Local Flights
-
0
-
-
-
Circuits
-
0
-
-
-
Arrivals
-
0
-
-
-
Departures
-
0
-
-
-
Overflights
-
0
-
-
-
Non-PPR Total
-
0
-
-
-
- - -
-
Grand Total Movements
-
0
+ +
+
GRAND TOTAL
+
0
-
+
PPR Records @@ -590,6 +604,7 @@ let accessToken = null; let currentPPRs = []; // Store current results for export let currentOtherFlights = []; // Store other flights for export + let otherFlightsFilterType = null; // Track which non-PPR flight type is selected for filtering // Load UI configuration from API async function loadUIConfig() { @@ -639,14 +654,105 @@ await loadReports(); } - // Set default date range to current month + // Set default date range to today function setupDefaultDateRange() { + setDateRangeToday(); + } + + // Toggle custom date range picker + function toggleCustomRange() { + const container = document.getElementById('custom-range-container'); + const customBtn = document.getElementById('filter-custom'); + + const isVisible = container.style.display !== 'none'; + container.style.display = isVisible ? 'none' : 'flex'; + + // Update button style + if (isVisible) { + customBtn.classList.remove('btn-primary'); + customBtn.classList.add('btn-secondary'); + } else { + customBtn.classList.remove('btn-secondary'); + customBtn.classList.add('btn-primary'); + // Focus on the first date input when opening + document.getElementById('date-from').focus(); + } + } + + // Set date range to today + function setDateRangeToday() { + const today = new Date().toISOString().split('T')[0]; + document.getElementById('date-from').value = today; + document.getElementById('date-to').value = today; + + // Hide custom range picker if it's open + document.getElementById('custom-range-container').style.display = 'none'; + + updateFilterButtonStyles('today'); + loadReports(); + } + + // Set date range to this week (Monday to Sunday) + function setDateRangeThisWeek() { + const now = new Date(); + const dayOfWeek = now.getDay(); + const diff = now.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1); // Adjust when day is Sunday + const monday = new Date(now.setDate(diff)); + const sunday = new Date(now.setDate(diff + 6)); + + document.getElementById('date-from').value = monday.toISOString().split('T')[0]; + document.getElementById('date-to').value = sunday.toISOString().split('T')[0]; + + // Hide custom range picker if it's open + document.getElementById('custom-range-container').style.display = 'none'; + + updateFilterButtonStyles('week'); + loadReports(); + } + + // Set date range to this month + function setDateRangeThisMonth() { const now = new Date(); const firstDay = new Date(now.getFullYear(), now.getMonth(), 1); const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0); - + document.getElementById('date-from').value = firstDay.toISOString().split('T')[0]; document.getElementById('date-to').value = lastDay.toISOString().split('T')[0]; + + // Hide custom range picker if it's open + document.getElementById('custom-range-container').style.display = 'none'; + + updateFilterButtonStyles('month'); + loadReports(); + } + + // Update button styles to show which filter is active + function updateFilterButtonStyles(activeFilter) { + const todayBtn = document.getElementById('filter-today'); + const weekBtn = document.getElementById('filter-week'); + const monthBtn = document.getElementById('filter-month'); + + // Reset all buttons + [todayBtn, weekBtn, monthBtn].forEach(btn => { + btn.classList.remove('btn-primary'); + btn.classList.add('btn-secondary'); + }); + + // Highlight active button + switch(activeFilter) { + case 'today': + todayBtn.classList.remove('btn-secondary'); + todayBtn.classList.add('btn-primary'); + break; + case 'week': + weekBtn.classList.remove('btn-secondary'); + weekBtn.classList.add('btn-primary'); + break; + case 'month': + monthBtn.classList.remove('btn-secondary'); + monthBtn.classList.add('btn-primary'); + break; + } } // Authentication management @@ -985,20 +1091,103 @@ } } + // Filter other flights by type + function filterOtherFlights(flightType) { + // Toggle filter if clicking the same type + if (otherFlightsFilterType === flightType) { + otherFlightsFilterType = null; + } else { + otherFlightsFilterType = flightType; + } + + // Show/hide PPR section based on filter + const pprSection = document.getElementById('ppr-reports-section'); + if (pprSection) { + pprSection.style.display = otherFlightsFilterType ? 'none' : 'block'; + } + + // Update visual indication of active filter + updateFilterIndicators(); + + // Re-display flights with new filter + displayOtherFlights(currentOtherFlights); + } + + // Update visual indicators for active filter + function updateFilterIndicators() { + // Select all clickable non-PPR summary items (those with onclick attribute) + const summaryItems = document.querySelectorAll('.summary-item[onclick*="filterOtherFlights"]'); + summaryItems.forEach(item => { + item.style.opacity = '1'; + item.style.borderLeftColor = ''; + item.style.borderLeftWidth = '0'; + }); + + if (otherFlightsFilterType) { + // Get the ID of the selected filter's summary item + let selectedId = ''; + switch(otherFlightsFilterType) { + case 'LOCAL': + selectedId = 'local-flights-movements'; + break; + case 'CIRCUIT': + selectedId = 'circuits-movements'; + break; + case 'ARRIVAL': + selectedId = 'non-ppr-arrivals'; + break; + case 'DEPARTURE': + selectedId = 'non-ppr-departures'; + break; + case 'OVERFLIGHT': + selectedId = 'overflights-count'; + break; + } + + // Find and highlight the selected item + if (selectedId) { + const selectedElement = document.getElementById(selectedId); + if (selectedElement) { + const summaryItem = selectedElement.closest('.summary-item'); + if (summaryItem) { + summaryItem.style.borderLeftColor = '#4CAF50'; + summaryItem.style.borderLeftWidth = '4px'; + summaryItem.style.opacity = '1'; + } + } + } + + // Dim other items that are clickable (non-PPR items) + const allSummaryItems = document.querySelectorAll('.summary-item[onclick]'); + allSummaryItems.forEach(item => { + if (item.querySelector('#' + selectedId) === null) { + item.style.opacity = '0.5'; + } + }); + } + } + // Display other flights in table function displayOtherFlights(flights) { const tbody = document.getElementById('other-flights-table-body'); const tableInfo = document.getElementById('other-flights-info'); - tableInfo.textContent = `${flights.length} flights found`; + // Apply filter if one is selected + let filteredFlights = flights; + if (otherFlightsFilterType) { + filteredFlights = flights.filter(flight => flight.flightType === otherFlightsFilterType); + } - if (flights.length === 0) { + tableInfo.textContent = `${filteredFlights.length} flights found` + (otherFlightsFilterType ? ` (filtered by ${otherFlightsFilterType})` : ''); + + if (filteredFlights.length === 0) { document.getElementById('other-flights-no-data').style.display = 'block'; + document.getElementById('other-flights-table-content').style.display = 'none'; return; } // Sort by time field (ascending) - flights.sort((a, b) => { + filteredFlights.sort((a, b) => { const aTime = a.timeField; const bTime = b.timeField; if (!aTime) return 1; @@ -1008,8 +1197,9 @@ tbody.innerHTML = ''; document.getElementById('other-flights-table-content').style.display = 'block'; + document.getElementById('other-flights-no-data').style.display = 'none'; - for (const flight of flights) { + for (const flight of filteredFlights) { const row = document.createElement('tr'); const typeLabel = flight.flightType;