CSV Download and Notes highlight

This commit is contained in:
2025-03-16 17:17:42 +00:00
parent 82f2c5c16c
commit 935e13d44b
7 changed files with 141 additions and 115 deletions

View File

@@ -287,11 +287,11 @@ function opDetail() {
echo '<tr><th>Captain</th><td></td><td>' . $row['captain'] . '</td></tr>'; echo '<tr><th>Captain</th><td></td><td>' . $row['captain'] . '</td></tr>';
echo '<tr><th>Arriving From:</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><span class="editable" data-column="in_from">' . $row['in_from'] . '</span></td></tr>'; echo '<tr><th>Arriving From:</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><span class="editable" data-column="in_from">' . $row['in_from'] . '</span></td></tr>';
echo '<tr><th>POB IN</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><input type="number" class="editable" data-column="pob_in" value="' . $row['pob_in'] . '" readonly></td></tr>'; echo '<tr><th>POB IN</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><input type="number" class="editable" data-column="pob_in" value="' . $row['pob_in'] . '" readonly></td></tr>';
echo '<tr><th>ETA</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><input type="datetime-local" class="editable" data-column="eta" value="' . date('Y-m-d\TH:i', strtotime($row['eta'])) . '" readonly></td></tr>'; echo '<tr><th>ETA</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><input type="datetime-local" class="editable" data-column="eta" value="' . ($row['eta'] ? date('Y-m-d\TH:i', strtotime($row['eta'])) : '') . '" readonly></td></tr>';
echo '<tr><th>Fuel</th><td></td><td>' . $row['fuel'] . '</td></tr>'; echo '<tr><th>Fuel</th><td></td><td>' . $row['fuel'] . '</td></tr>';
echo '<tr><th>POB OUT</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><input type="number" class="editable" data-column="pob_out" value="' . $row['pob_out'] . '" readonly></td></tr>'; echo '<tr><th>POB OUT</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><input type="number" class="editable" data-column="pob_out" value="' . $row['pob_out'] . '" readonly></td></tr>';
echo '<tr><th>Outbound To</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><span class="editable" data-column="out_to">' . $row['out_to'] . '</span></td></tr>'; echo '<tr><th>Outbound To</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><span class="editable" data-column="out_to">' . $row['out_to'] . '</span></td></tr>';
echo '<tr><th>ETD</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><input type="datetime-local" class="editable" data-column="etd" value="' . date('Y-m-d\TH:i', strtotime($row['etd'])) . '" readonly></td></tr>'; echo '<tr><th>ETD</th><td><button class="edit-button" onclick="editField(this)"><img src="assets/edit.png" alt="Edit"></button></td><td><input type="datetime-local" class="editable" data-column="etd" value="' . ($row['etd'] ? date('Y-m-d\TH:i', strtotime($row['etd'])) : '') . '" readonly></td></tr>';
echo '<tr><th>Email Address</th><td></td><td>' . $row['email'] . '</td></tr>'; echo '<tr><th>Email Address</th><td></td><td>' . $row['email'] . '</td></tr>';
echo '<tr><th>Phone</th><td></td><td>' . $row['phone'] . '</td></tr>'; echo '<tr><th>Phone</th><td></td><td>' . $row['phone'] . '</td></tr>';
echo '<tr><th>Notes</th><td></td><td>' . $row['notes'] . '</td></tr>'; echo '<tr><th>Notes</th><td></td><td>' . $row['notes'] . '</td></tr>';

View File

@@ -148,6 +148,7 @@ require_db_auth();
</select> </select>
<select id="yearSelect"></select> <select id="yearSelect"></select>
<button onclick="selectMonthYear()">Submit</button> <button onclick="selectMonthYear()">Submit</button>
<button onclick="downloadCSV()">Download CSV</button>
<p id="output"></p> <p id="output"></p>
</div> </div>
@@ -186,6 +187,11 @@ require_db_auth();
selectMonth(); selectMonth();
populateYearDropdown(); populateYearDropdown();
function downloadCSV() {
let year = document.getElementById("yearSelect").value;
let month = document.getElementById("monthSelect").value;
window.location.href = `download.php?year=${year}&month=${month}`;
}
</script> </script>
<?php <?php

47
download.php Normal file
View File

@@ -0,0 +1,47 @@
<?php
include("functions.php");
require_db_auth();
// Create connection
$conn = new mysqli($host, $username, $password, $database);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$year = $_GET['year'] ?? date('Y');
$month = $_GET['month'] ?? date('n');
$datetime = DateTime::createFromFormat('!m', $month);
$monthName = $datetime->format('F');
$filename = $monthName . $year . '.csv';
header('Content-Type: text/csv');
header('Content-Disposition: attachment;filename=' . $filename);
$output = fopen('php://output', 'w');
$escape = '\\'; // Define the escape character
// Fetch data
$sql = "SELECT * FROM submitted WHERE status != 'DELETED' and MONTH(eta) = $month and YEAR(eta) = $year ORDER BY eta ASC;";
$result = $conn->query($sql);
// Output column headers
$fields = $result->fetch_fields();
$headers = [];
foreach ($fields as $field) {
$headers[] = $field->name;
}
fputcsv($output, $headers, ',', '"', $escape);
// Output rows
while ($row = $result->fetch_assoc()) {
fputcsv($output, $row, ',', '"', $escape);
}
// Close the database connection
$conn->close();
fclose($output);
?>

View File

@@ -8,7 +8,7 @@
let now = new Date(); let now = new Date();
let localDatetime = now.toISOString().slice(0, 16); // Format for datetime-local input let localDatetime = now.toISOString().slice(0, 16); // Format for datetime-local input
document.getElementById("eta").value = localDatetime; document.getElementById("eta").value = localDatetime;
document.getElementById("etd").value = localDatetime; // document.getElementById("etd").value = localDatetime;
}); });
function fetchResults() { function fetchResults() {

View File

@@ -146,9 +146,6 @@ function opView($entryId) {
echo "<p><strong>Notes:</strong> " . $row['notes'] . "</p></div>"; echo "<p><strong>Notes:</strong> " . $row['notes'] . "</p></div>";
echo '<button onclick="confirmWithSweetAlert(\'pilotppr.php?op=cancel&token=' . urlencode($_GET['token']) . '\')">Cancel PPR</button>'; echo '<button onclick="confirmWithSweetAlert(\'pilotppr.php?op=cancel&token=' . urlencode($_GET['token']) . '\')">Cancel PPR</button>';
echo '<p>Dear Pilot,<p>This is to confirm we have received your PPR information, and we look forward to welcoming you at Swansea Airport.<p>Please review our <a href=https://swansea-airport.wales/pilot-information/arrival-procedures.html>arrival procedures</a> prior to your arrival.<p>To view or cancel your PPR please click the button:</p>';
echo '<a href="$secureLink" style="display: inline-block; padding: 10px 20px; color: white; background-color: #007bff; text-decoration: none; border-radius: 5px;">View PPR</a>';
echo '<p><img src="https://ppr.swansea-airport.wales/dev/assets/egfh.webp" alt="Swansea Airport" style="width: 200px;">';
} else { } else {
echo ""; echo "";

View File

@@ -18,7 +18,7 @@
}, },
"data": { "data": {
"617dd0cd-2d17-4d7f-826b-5348afdb30b3": { "617dd0cd-2d17-4d7f-826b-5348afdb30b3": {
"value": "G-LORD", "value": "G-YSIR",
"name": "Aircraft Registration" "name": "Aircraft Registration"
}, },
"148a55d8-5357-49a3-b9aa-2a5d4dc64173": { "148a55d8-5357-49a3-b9aa-2a5d4dc64173": {
@@ -34,7 +34,7 @@
"name": "Arriving From" "name": "Arriving From"
}, },
"ca4ac44f-0388-4a70-a072-38276ed2ac13": { "ca4ac44f-0388-4a70-a072-38276ed2ac13": {
"value": "15\/03\/2025 17:22", "value": "16\/03\/2025 17:22",
"name": "ETA" "name": "ETA"
}, },
"6fc47c54-7383-48fd-93fc-d8080f5ed8f5": { "6fc47c54-7383-48fd-93fc-d8080f5ed8f5": {

190
tower.php
View File

@@ -140,35 +140,62 @@ require_db_auth();
cursor: pointer; cursor: pointer;
} }
/* Add this CSS for the red triangle */
.red-triangle {
position: relative;
}
.red-triangle::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
border-left: 10px solid red;
border-bottom: 10px solid transparent;
}
.red-triangle:hover::after {
content: attr(data-notes);
position: absolute;
top: 20px;
left: 0;
background: #fff;
border: 1px solid #ddd;
padding: 5px;
border-radius: 5px;
white-space: nowrap;
z-index: 10;
}
</style> </style>
</head> </head>
<body> <body>
<script> <script>
function markDeparted(id) { function markAction(id, action, title, buttonText) {
const now = new Date(); const now = new Date();
const currentTime = now.toISOString().slice(11, 16); // Extract HH:MM const currentTime = now.toISOString().slice(11, 16); // Extract HH:MM
Swal.fire({ Swal.fire({
title: "Depart Aircraft at time", title: title,
html: `<input type="time" id="timepicker" class="swal2-input" value="${currentTime}">`, html: `<input type="time" id="timepicker" class="swal2-input" value="${currentTime}">`,
icon: "info", icon: "info",
showCancelButton: true, showCancelButton: true,
confirmButtonColor: "#3085d6", confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33", cancelButtonColor: "#d33",
confirmButtonText: "Departed", confirmButtonText: buttonText,
preConfirm: () => { preConfirm: () => {
const time = document.getElementById("timepicker").value; const time = document.getElementById("timepicker").value;
if (!time) { if (!time) {
Swal.showValidationMessage("Please select a time"); Swal.showValidationMessage("Please select a time");
} }
return time; return time;
} }
}).then((result) => { }).then((result) => {
if (result.isConfirmed) { if (result.isConfirmed) {
page="action.php?op=departed&id=" + id + "&time=" + encodeURIComponent(result.value); const page = `action.php?op=${action}&id=${id}&time=${encodeURIComponent(result.value)}`;
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.open("GET", page, false); // 'false' makes the request synchronous xhr.open("GET", page, false); // 'false' makes the request synchronous
xhr.send(); xhr.send();
@@ -177,98 +204,43 @@ function markDeparted(id) {
}); });
} }
function markLanded(id) { function markDeparted(id) {
markAction(id, "departed", "Depart Aircraft at time", "Departed");
}
const now = new Date(); function markLanded(id) {
const currentTime = now.toISOString().slice(11, 16); // Extract HH:MM markAction(id, "landed", "Land Aircraft at time", "Landed");
}
Swal.fire({ function markCancel(id) {
title: "Land Aircraft at time", const page = `action.php?op=cancel&id=${id}`;
html: `<input type="time" id="timepicker" class="swal2-input" value="${currentTime}">`, var xhr = new XMLHttpRequest();
icon: "info", xhr.open("GET", page, false); // 'false' makes the request synchronous
showCancelButton: true, xhr.send();
confirmButtonColor: "#3085d6", window.location.reload(true);
cancelButtonColor: "#d33", }
confirmButtonText: "Landed",
preConfirm: () => {
const time = document.getElementById("timepicker").value;
if (!time) {
Swal.showValidationMessage("Please select a time");
}
return time;
}
}).then((result) => { function openDetail(id) {
if (result.isConfirmed) { const page = `action.php?op=detail&id=${id}`;
page="action.php?op=landed&id=" + id + "&time=" + encodeURIComponent(result.value); var popupWindow = window.open(page, "PopupWindow", "toolbar=no, location=no, directories=no,status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=yes, width=600, height=1100");
var xhr = new XMLHttpRequest(); popupWindow.onload = function () {
xhr.open("GET", page, false); // 'false' makes the request synchronous var contentHeight = popupWindow.document.body.scrollHeight;
xhr.send(); var contentWidth = popupWindow.document.body.scrollWidth;
window.location.reload(true); popupWindow.resizeTo(contentWidth + 20, contentHeight + 180); // Adding padding to prevent clipping
} };
}); }
} </script>
function markLanded(id) { <center><h2>Tower Ops <?php echo date('l d M Y'); ?></h2></center>
const now = new Date(); <!--
const currentTime = now.toISOString().slice(11, 16); // Extract HH:MM <div class="checkbox-container">
<label>
Swal.fire({ <input type="checkbox" id="toggle-canceled" onchange="toggleRows('state-CANCELED', this.checked)"> Show CANCELED
title: "Land Aircraft at time", </label>
html: `<input type="time" id="timepicker" class="swal2-input" value="${currentTime}">`,
icon: "info",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: "Landed",
preConfirm: () => {
const time = document.getElementById("timepicker").value;
if (!time) {
Swal.showValidationMessage("Please select a time");
}
return time;
}
}).then((result) => {
if (result.isConfirmed) {
page="action.php?op=landed&id=" + id + "&time=" + encodeURIComponent(result.value);
var xhr = new XMLHttpRequest();
xhr.open("GET", page, false); // 'false' makes the request synchronous
xhr.send();
window.location.reload(true);
}
});
}
function markCancel(id) {
page="action.php?op=cancel&id=" + id;
var xhr = new XMLHttpRequest();
xhr.open("GET", page, false); // 'false' makes the request synchronous
xhr.send();
window.location.reload(true);
}
function openDetail(id) {
page="action.php?op=detail&id=" + id;
var popupWindow = window.open(page, "PopupWindow", "toolbar=no, location=no, directories=no,status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=yes, width=600, height=1100");
popupWindow.onload = function () {
var contentHeight = popupWindow.document.body.scrollHeight;
var contentWidth = popupWindow.document.body.scrollWidth;
popupWindow.resizeTo(contentWidth + 20, contentHeight + 180); // Adding padding to prevent clipping
};
}
</script>
<center><h2>Tower Ops <?php echo date('l d M Y'); ?></h2></center>
<!--
<div class="checkbox-container">
<label>
<input type="checkbox" id="toggle-canceled" onchange="toggleRows('state-CANCELED', this.checked)"> Show CANCELED
</label>
</div> </div>
--> -->
<div class="heading">Inbound PPR</div> <div class="heading">Inbound Aircraft</div>
<?php <?php
@@ -281,7 +253,7 @@ if ($conn->connect_error) {
} }
// Define your SQL query // Define your SQL query
$sql = "SELECT id, status, ac_reg, ac_type, ac_call, TIME_FORMAT(eta,'%H:%i') AS ETA, fuel, in_from, pob_in FROM submitted WHERE DATE(eta) = CURDATE() AND (status = 'NEW' OR status = 'CANCELED') ORDER BY eta ASC;"; // Replace with your table name $sql = "SELECT id, status, ac_reg, ac_type, ac_call, TIME_FORMAT(eta,'%H:%i') AS ETA, fuel, in_from, pob_in, notes FROM submitted WHERE DATE(eta) = CURDATE() AND (status = 'NEW' OR status = 'CANCELED') ORDER BY eta ASC;"; // Replace with your table name
// Execute the query // Execute the query
$result = $conn->query($sql); $result = $conn->query($sql);
@@ -296,7 +268,7 @@ if ($result->num_rows > 0) {
// Output table headers (assuming column names are known) // Output table headers (assuming column names are known)
$fields = $result->fetch_fields(); $fields = $result->fetch_fields();
foreach ($fields as $field) { foreach ($fields as $field) {
if ($field->name != 'status' && $field->name != 'id' && $field->name != 'ac_call') { if ($field->name != 'notes' && $field->name != 'status' && $field->name != 'id' && $field->name != 'ac_call') {
echo '<th>' . htmlspecialchars($field->name ?? '') . '</th>'; echo '<th>' . htmlspecialchars($field->name ?? '') . '</th>';
} }
@@ -311,12 +283,14 @@ if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) { while ($row = $result->fetch_assoc()) {
echo '<tr class="state-' . $row['status'] . '" data-id=' . $row['id'] . '>'; echo '<tr class="state-' . $row['status'] . '" data-id=' . $row['id'] . '>';
foreach ($row as $key => $value) { foreach ($row as $key => $value) {
if ($key != 'status' && $key != 'id' && $key != 'ac_call') { if ($key != 'notes' && $key != 'status' && $key != 'id' && $key != 'ac_call') {
if ($key == 'ac_reg' && $row['ac_call'] != NULL) { if ($key == 'ac_reg' && $row['ac_call'] != NULL) {
echo '<td>' . htmlspecialchars($row['ac_call'] ?? '') . "<br><span class=acreg>" . $value . '</span></td>'; echo '<td>' . htmlspecialchars($row['ac_call'] ?? '') . "<br><span class=acreg>" . $value . '</span></td>';
} else if ($key == 'ac_reg' && !empty($row['notes'])) {
echo '<td class="red-triangle" data-notes="' . htmlspecialchars($row['notes'] ?? '') . '">' . htmlspecialchars($value ?? '') . '</td>';
} else { } else {
echo '<td>' . htmlspecialchars($value ?? '') . '</td>'; echo '<td>' . htmlspecialchars($value ?? '') . '</td>';
} }
} }
} }
echo '<td><img src="assets/cancel-icon.webp" title="Cancel PPR" style="width: 25px; height: auto;" onclick="markCancel(' . $row['id'] . ')"><img src="assets/arrive.png" title="Land" style="width: 30px; height: auto;" onclick="markLanded(' . $row['id'] . ')"></td>'; echo '<td><img src="assets/cancel-icon.webp" title="Cancel PPR" style="width: 25px; height: auto;" onclick="markCancel(' . $row['id'] . ')"><img src="assets/arrive.png" title="Land" style="width: 30px; height: auto;" onclick="markLanded(' . $row['id'] . ')"></td>';
@@ -330,14 +304,14 @@ if ($result->num_rows > 0) {
?> ?>
<div class="heading">Booking Out</div> <div class="heading">Visiting Aircraft</div>
<div id="landed"> <div id="landed">
<?php <?php
// Define your SQL query // Define your SQL query
$sql = "SELECT id, status, ac_reg, ac_type, ac_call, TIME_FORMAT(etd,'%H:%i') AS ETD, fuel, out_to, pob_out FROM submitted WHERE DATE(eta) = CURDATE() AND status = 'LANDED' ORDER BY eta ASC;"; // Replace with your table name $sql = "SELECT id, status, ac_reg, ac_type, ac_call, TIME_FORMAT(etd,'%H:%i') AS ETD, fuel, out_to, pob_out, notes FROM submitted WHERE DATE(eta) = CURDATE() AND status = 'LANDED' ORDER BY eta ASC;"; // Replace with your table name
// Execute the query // Execute the query
$result = $conn->query($sql); $result = $conn->query($sql);
@@ -352,7 +326,7 @@ if ($result->num_rows > 0) {
// Output table headers (assuming column names are known) // Output table headers (assuming column names are known)
$fields = $result->fetch_fields(); $fields = $result->fetch_fields();
foreach ($fields as $field) { foreach ($fields as $field) {
if ($field->name != 'status' && $field->name != 'id' && $field->name != 'ac_call') { if ($field->name != 'notes' && $field->name != 'status' && $field->name != 'id' && $field->name != 'ac_call') {
echo '<th>' . htmlspecialchars($field->name ?? '') . '</th>'; echo '<th>' . htmlspecialchars($field->name ?? '') . '</th>';
} }
@@ -367,12 +341,14 @@ if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) { while ($row = $result->fetch_assoc()) {
echo '<tr class="state-' . $row['status'] . '" data-id=' . $row['id'] . '>'; echo '<tr class="state-' . $row['status'] . '" data-id=' . $row['id'] . '>';
foreach ($row as $key => $value) { foreach ($row as $key => $value) {
if ($key != 'status' && $key != 'id' && $key != 'ac_call') { if ($key != 'notes' && $key != 'status' && $key != 'id' && $key != 'ac_call') {
if ($key == 'ac_reg' && $row['ac_call'] != NULL) { if ($key == 'ac_reg' && $row['ac_call'] != NULL) {
echo '<td>' . htmlspecialchars($row['ac_call'] ?? '') . "<br><span class=acreg>" . $value . '</span></td>'; echo '<td>' . htmlspecialchars($row['ac_call'] ?? '') . "<br><span class=acreg>" . $value . '</span></td>';
} else if ($key == 'ac_reg' && !empty($row['notes'])) {
echo '<td class="red-triangle" data-notes="' . htmlspecialchars($row['notes'] ?? '') . '">' . htmlspecialchars($value ?? '') . '</td>';
} else { } else {
echo '<td>' . htmlspecialchars($value ?? '') . '</td>'; echo '<td>' . htmlspecialchars($value ?? '') . '</td>';
} }
} }
} }
echo '<td><img src="assets/cancel-icon.webp" title="Cancel PPR" style="width: 25px; height: auto;" onclick="markCancel(' . $row['id'] . ')"><img src="assets/depart.png" title="Depart" style="width: 30px; height: auto;" onclick="markDeparted(' . $row['id'] . ')"></td>'; echo '<td><img src="assets/cancel-icon.webp" title="Cancel PPR" style="width: 25px; height: auto;" onclick="markCancel(' . $row['id'] . ')"><img src="assets/depart.png" title="Depart" style="width: 30px; height: auto;" onclick="markDeparted(' . $row['id'] . ')"></td>';