Compare commits
18 Commits
main
...
a8d87582c9
| Author | SHA1 | Date | |
|---|---|---|---|
| a8d87582c9 | |||
| f0d26295d8 | |||
| 9c77d8ffb0 | |||
| 426c5092ba | |||
| c7eddb5465 | |||
| 1e63adf9d5 | |||
| 8ce6b3d0fd | |||
| ce9de8d7ff | |||
| 02f1d46493 | |||
| 2b7d3e5d2a | |||
| 5077445d5d | |||
| 9d40de216f | |||
| 70af1d3e30 | |||
| 0637a004a0 | |||
| e9042f8c21 | |||
| 6cd92f4314 | |||
| 46f44f54d3 | |||
| 393f155c37 |
323
action.php
323
action.php
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@@ -34,6 +33,10 @@
|
|||||||
background-color: #f9f9f9;
|
background-color: #f9f9f9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.details th {
|
||||||
|
text-align: right; /* Justify table headings to the right */
|
||||||
|
}
|
||||||
|
|
||||||
.details p {
|
.details p {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@@ -71,9 +74,140 @@
|
|||||||
button:hover {
|
button:hover {
|
||||||
background-color: #0056b3;
|
background-color: #0056b3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.editable {
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 90%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus {
|
||||||
|
border-color: #007bff;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-button {
|
||||||
|
margin-left: 10px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-button img {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-button:hover img {
|
||||||
|
filter: brightness(0.8);
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
let id = "<?php echo $_GET['id'];?>";
|
||||||
|
|
||||||
|
// Select all editable elements
|
||||||
|
document.querySelectorAll(".editable").forEach((element) => {
|
||||||
|
let oldValue = element.value || element.textContent.trim(); // Store initial value
|
||||||
|
|
||||||
|
element.addEventListener("focus", function () {
|
||||||
|
oldValue = this.value || this.textContent.trim(); // Store old value when focused
|
||||||
|
});
|
||||||
|
|
||||||
|
element.addEventListener("blur", function () {
|
||||||
|
let newValue = this.value || this.textContent.trim();
|
||||||
|
let column = this.getAttribute("data-column");
|
||||||
|
|
||||||
|
if (newValue !== oldValue) {
|
||||||
|
sendUpdate(id, column, oldValue, newValue, element);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
element.addEventListener("keydown", function (event) {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
event.preventDefault(); // Prevent new line
|
||||||
|
this.blur(); // Trigger blur event to save changes
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Select all edit buttons
|
||||||
|
document.querySelectorAll(".edit-button").forEach((button) => {
|
||||||
|
button.addEventListener("click", function () {
|
||||||
|
editField(button);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables editing for the field
|
||||||
|
*/
|
||||||
|
function editField(button) {
|
||||||
|
let element = button.parentElement.nextElementSibling.firstElementChild;
|
||||||
|
if (element.tagName === "INPUT") {
|
||||||
|
element.readOnly = false;
|
||||||
|
element.focus();
|
||||||
|
} else {
|
||||||
|
element.contentEditable = true;
|
||||||
|
element.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
element.addEventListener("blur", function () {
|
||||||
|
if (element.tagName === "INPUT") {
|
||||||
|
element.readOnly = true;
|
||||||
|
} else {
|
||||||
|
element.contentEditable = false;
|
||||||
|
}
|
||||||
|
}, { once: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the updated data to the server
|
||||||
|
*/
|
||||||
|
function sendUpdate(flightId, column, oldValue, newValue, element) {
|
||||||
|
fetch("update_data.php", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||||
|
body: `id=${flightId}&column=${encodeURIComponent(column)}&old_value=${encodeURIComponent(oldValue)}&new_value=${encodeURIComponent(newValue)}`
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
console.log(`Updated: ${data.column} changed from '${data.old_value}' to '${data.new_value}'`);
|
||||||
|
oldValue = newValue; // ✅ Update oldValue to prevent reverting
|
||||||
|
} else {
|
||||||
|
alert("Error updating data");
|
||||||
|
if (element.tagName === "INPUT") {
|
||||||
|
element.value = oldValue; // ❌ Revert ONLY if update fails
|
||||||
|
} else {
|
||||||
|
element.textContent = oldValue; // ❌ Revert ONLY if update fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("Fetch error:", error);
|
||||||
|
if (element.tagName === "INPUT") {
|
||||||
|
element.value = oldValue; // ❌ Revert only on network failure
|
||||||
|
} else {
|
||||||
|
element.textContent = oldValue; // ❌ Revert only on network failure
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
include("functions.php");
|
include("functions.php");
|
||||||
@@ -83,12 +217,58 @@ function opCancel() {
|
|||||||
$conn = connectDb();
|
$conn = connectDb();
|
||||||
$sql = "UPDATE submitted SET status = 'CANCELED' where id = " . $_GET['id'];
|
$sql = "UPDATE submitted SET status = 'CANCELED' where id = " . $_GET['id'];
|
||||||
$result = $conn->query($sql);
|
$result = $conn->query($sql);
|
||||||
|
logJournal($conn, $_GET['id'], "Marked Canceled");
|
||||||
|
$conn->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function opLanded() {
|
function opLanded() {
|
||||||
|
|
||||||
|
$date = date('Y-m-d');
|
||||||
|
$time = urldecode($_GET['time']);
|
||||||
|
$landed_dt = $date . ' ' . $time;
|
||||||
|
|
||||||
$conn = connectDb();
|
$conn = connectDb();
|
||||||
$sql = "UPDATE submitted SET status = 'LANDED', landed_dt = NOW() where id = " . $_GET['id'];
|
$sql = "UPDATE submitted SET status = 'LANDED', landed_dt = ? WHERE id = ?";
|
||||||
|
|
||||||
|
$stmt = $conn->prepare($sql);
|
||||||
|
$stmt->bind_param("si", $landed_dt, $_GET['id']);
|
||||||
|
|
||||||
|
$stmt->execute();
|
||||||
|
$stmt->close();
|
||||||
|
|
||||||
|
logJournal($conn, $_GET['id'], "Marked Landed at time " . $time);
|
||||||
|
|
||||||
|
$conn->close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function opDeparted() {
|
||||||
|
|
||||||
|
$date = date('Y-m-d');
|
||||||
|
$time = urldecode($_GET['time']);
|
||||||
|
$departed_dt = $date . ' ' . $time;
|
||||||
|
|
||||||
|
$conn = connectDb();
|
||||||
|
$sql = "UPDATE submitted SET status = 'DEPARTED', departed_dt = ? WHERE id = ?";
|
||||||
|
|
||||||
|
$stmt = $conn->prepare($sql);
|
||||||
|
$stmt->bind_param("si", $departed_dt, $_GET['id']);
|
||||||
|
|
||||||
|
$stmt->execute();
|
||||||
|
$stmt->close();
|
||||||
|
|
||||||
|
logJournal($conn, $_GET['id'], "Marked Departed at time " . $time);
|
||||||
|
|
||||||
|
$conn->close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function opDelete() {
|
||||||
|
$conn = connectDb();
|
||||||
|
$sql = "UPDATE submitted SET status = 'DELETED' where id = " . $_GET['id'];
|
||||||
$result = $conn->query($sql);
|
$result = $conn->query($sql);
|
||||||
|
logJournal($conn, $_GET['id'], "Marked Deleted");
|
||||||
|
$conn->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function opDetail() {
|
function opDetail() {
|
||||||
@@ -100,32 +280,56 @@ function opDetail() {
|
|||||||
// Output data of the row
|
// Output data of the row
|
||||||
$row = $result->fetch_assoc();
|
$row = $result->fetch_assoc();
|
||||||
echo '<div class="container">';
|
echo '<div class="container">';
|
||||||
echo '<div class="details"><p><strong>Aircraft Reg: </strong>' . $row['ac_reg'] . "</p>";
|
echo '<table class="details">';
|
||||||
echo "<p><strong>Aircraft Type:</strong> " . $row['ac_type'] . "</p>";
|
echo '<tr><th>Aircraft Reg:</th><td></td><td>' . $row['ac_reg'] . '</td></tr>';
|
||||||
echo "<p><strong>Callsign:</strong> " . $row['ac_call'] . "</p>";
|
echo '<tr><th>Aircraft Type:</th><td></td><td>' . $row['ac_type'] . '</td></tr>';
|
||||||
echo "<p><strong>Captain's Name:</strong> " . $row['captain'] . "</p>";
|
echo '<tr><th>Callsign:</th><td></td><td>' . $row['ac_call'] . '</td></tr>';
|
||||||
echo "<p><strong>Arriving From:</strong> " . $row['in_from'] . "</p>";
|
echo '<tr><th>Captain\'s Name:</th><td></td><td>' . $row['captain'] . '</td></tr>';
|
||||||
echo "<p><strong>POB IN:</strong> " . $row['pob_in'] . "</p>";
|
echo '<tr><th>Arriving From:</th><td><button class="edit-button" onclick="editField(this)"><img src="edit.png" alt="Edit"></button></td><td><span class="editable" data-column="in_from">' . $row['in_from'] . '</span></td></tr>';
|
||||||
echo "<p><strong>ETA:</strong> " . $row['eta'] . "</p>";
|
echo '<tr><th>POB IN:</th><td></td><td>' . $row['pob_in'] . '</td></tr>';
|
||||||
|
echo '<tr><th>ETA:</th><td><button class="edit-button" onclick="editField(this)"><img src="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>Fuel Required:</th><td></td><td>' . $row['fuel'] . '</td></tr>';
|
||||||
|
echo '<tr><th>POB OUT:</th><td><button class="edit-button" onclick="editField(this)"><img src="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="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="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>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>Notes:</th><td></td><td>' . $row['notes'] . '</td></tr>';
|
||||||
|
echo '<tr><th>PPR created at:</th><td></td><td>' . $row['submitted_dt'] . ' by ' . $row['created_by'] . '</td></tr>';
|
||||||
|
echo '</table>';
|
||||||
|
|
||||||
echo "<p><strong>Fuel Required:</strong> " . $row['fuel'] . "</p>";
|
// Fetch journal entries
|
||||||
|
$journalSql = "SELECT * FROM journal WHERE ppr_id = " . $_GET['id'] . " ORDER BY id DESC";
|
||||||
|
$journalResult = $conn->query($journalSql);
|
||||||
|
$journalCount = $journalResult->num_rows;
|
||||||
|
|
||||||
echo "<p><strong>POB OUT:</strong> " . $row['pob_out'] . "</p>";
|
// Add button to toggle journal entries
|
||||||
echo "<p><strong>Outbound To:</strong> " . $row['out_to'] . "</p>";
|
echo '<br><button onclick="window.close()">Close Window</button>';
|
||||||
echo "<p><strong>ETD:</strong> " . $row['etd'] . "</p>";
|
echo ' <button onclick="toggleJournal()">Show Journal Entries (' . $journalCount . ')</button>';
|
||||||
|
echo '<div id="journal-entries" style="display:none;">';
|
||||||
|
echo '<h3>Journal Entries</h3>';
|
||||||
|
echo '<table class="journal-table">';
|
||||||
|
echo '<tr><th>Timestamp</th><th>User</th><th>Entry</th></tr>';
|
||||||
|
|
||||||
|
if ($journalCount > 0) {
|
||||||
|
while ($journalRow = $journalResult->fetch_assoc()) {
|
||||||
|
echo '<tr>';
|
||||||
|
echo '<td>' . $journalRow['entry_dt'] . '</td>';
|
||||||
|
echo '<td>' . $journalRow['user'] . '</td>';
|
||||||
|
echo '<td>' . $journalRow['entry'] . '</td>';
|
||||||
|
echo '</tr>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo '<tr><td colspan="3">No journal entries found.</td></tr>';
|
||||||
|
}
|
||||||
|
|
||||||
echo "<p><strong>Email Address:</strong> " . $row['email'] . "</p>";
|
echo '</table>';
|
||||||
echo "<p><strong>Phone:</strong> " . $row['phone'] . "</p>";
|
echo '</div>';
|
||||||
|
echo '</div>';
|
||||||
|
|
||||||
echo "<p><strong>Notes:</strong> " . $row['notes'] . "</p>";
|
|
||||||
echo "<p><i>PPR created at:</strong> " . $row['submitted_dt'] . " by " . $row['created_by'] . "</p></div>";
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
echo "No details found for the given ID.";
|
echo "No details found for the given ID.";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
$conn->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch($_GET['op']) {
|
switch($_GET['op']) {
|
||||||
@@ -135,6 +339,12 @@ switch($_GET['op']) {
|
|||||||
case "landed":
|
case "landed":
|
||||||
opLanded();
|
opLanded();
|
||||||
break;
|
break;
|
||||||
|
case "departed":
|
||||||
|
opDeparted();
|
||||||
|
break;
|
||||||
|
case "delete":
|
||||||
|
opDelete();
|
||||||
|
break;
|
||||||
case "detail":
|
case "detail":
|
||||||
opDetail();
|
opDetail();
|
||||||
break;
|
break;
|
||||||
@@ -142,7 +352,74 @@ switch($_GET['op']) {
|
|||||||
default:
|
default:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<p><center><button onclick="window.close()">Close Window</button></center>
|
|
||||||
|
<script>
|
||||||
|
function toggleJournal() {
|
||||||
|
var journalEntries = document.getElementById("journal-entries");
|
||||||
|
var toggleButton = document.querySelector("button[onclick='toggleJournal()']");
|
||||||
|
if (journalEntries.style.display === "none") {
|
||||||
|
journalEntries.style.display = "block";
|
||||||
|
toggleButton.textContent = "Hide Journal Entries";
|
||||||
|
} else {
|
||||||
|
journalEntries.style.display = "none";
|
||||||
|
toggleButton.textContent = "Show Journal Entries";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.journal-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.journal-table th, .journal-table td {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.journal-table th {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.journal-table tr:nth-child(even) {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.journal-table tr:hover {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-button {
|
||||||
|
margin-left: 10px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-button img {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-button:hover img {
|
||||||
|
filter: brightness(0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable {
|
||||||
|
background-color: transparent;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editable:focus {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|||||||
258
admin.php
Normal file
258
admin.php
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
<?php
|
||||||
|
include("functions.php");
|
||||||
|
require_db_auth();
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="refresh" content="300">
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
let rows = document.querySelectorAll("table tbody tr");
|
||||||
|
|
||||||
|
rows.forEach(row => {
|
||||||
|
let fuelCell = row.cells[3]; // Get the "Fuel" cell (index 3)
|
||||||
|
|
||||||
|
if (fuelCell.textContent == "100LL") {
|
||||||
|
row.classList.add("highlight100LL"); // Add the class
|
||||||
|
} else if (fuelCell.textContent == "JET A1") {
|
||||||
|
row.classList.add("highlightJET"); // Add the class
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Swansea Daily PPR</title>
|
||||||
|
<style>
|
||||||
|
|
||||||
|
/* Styling for the table */
|
||||||
|
table {
|
||||||
|
width: 90%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 20px 0;
|
||||||
|
margin-left: auto; /* Automatically adjusts left margin */
|
||||||
|
margin-right: auto; /* Automatically adjusts right margin */
|
||||||
|
|
||||||
|
}
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
padding: 2px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
padding: 2px;
|
||||||
|
text-align: center;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
font-size: 8pt;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
tr:hover {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight100LL {
|
||||||
|
background-color: #ADD8E6 !important;
|
||||||
|
#font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlightJET {
|
||||||
|
background-color: yellow !important; /* Allow it to override the odd/even shading */
|
||||||
|
#font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 1rem;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function markLanded(id) {
|
||||||
|
page="action.php?op=landed&id=" + id;
|
||||||
|
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 deletePpr(id) {
|
||||||
|
page="action.php?op=delete&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>Swansea Inbound PPR ADMIN</h2></center>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h2>Select a Month</h2>
|
||||||
|
<select id="monthSelect">
|
||||||
|
<option value="1">January</option>
|
||||||
|
<option value="2">February</option>
|
||||||
|
<option value="3">March</option>
|
||||||
|
<option value="4">April</option>
|
||||||
|
<option value="5">May</option>
|
||||||
|
<option value="6">June</option>
|
||||||
|
<option value="7">July</option>
|
||||||
|
<option value="8">August</option>
|
||||||
|
<option value="9">September</option>
|
||||||
|
<option value="10">October</option>
|
||||||
|
<option value="11">November</option>
|
||||||
|
<option value="12">December</option>
|
||||||
|
</select>
|
||||||
|
<select id="yearSelect"></select>
|
||||||
|
<button onclick="selectMonthYear()">Submit</button>
|
||||||
|
<p id="output"></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function populateYearDropdown() {
|
||||||
|
let yearSelect = document.getElementById("yearSelect");
|
||||||
|
let currentYear = new Date().getFullYear();
|
||||||
|
let startYear = currentYear;
|
||||||
|
let endYear = currentYear - 10; // Last 10 years
|
||||||
|
|
||||||
|
for (let year = startYear; year >= endYear; year--) { // Descending order
|
||||||
|
let option = document.createElement("option");
|
||||||
|
option.value = year;
|
||||||
|
option.textContent = year;
|
||||||
|
if (year === currentYear) {
|
||||||
|
option.selected = true; // Set default to current year
|
||||||
|
}
|
||||||
|
yearSelect.appendChild(option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectMonthYear() {
|
||||||
|
let month = document.getElementById("monthSelect").value;
|
||||||
|
let year = document.getElementById("yearSelect").value;
|
||||||
|
window.location.href = `admin.php?year=${year}&month=${month}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectMonth() {
|
||||||
|
let month = new URLSearchParams(window.location.search).get('month') ?? new Date().getMonth() + 1;
|
||||||
|
document.getElementById("monthSelect").value = month;
|
||||||
|
}
|
||||||
|
|
||||||
|
const year = new URLSearchParams(window.location.search).get('year') ?? new Date().getFullYear();
|
||||||
|
const month = new URLSearchParams(window.location.search).get('month') ?? new Date().getMonth() + 1;
|
||||||
|
|
||||||
|
selectMonth();
|
||||||
|
populateYearDropdown();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 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');
|
||||||
|
|
||||||
|
$sql = "SELECT * FROM submitted WHERE status != 'DELETED' and MONTH(eta) = $month and YEAR(eta) = $year ORDER BY eta ASC;"; // Replace with your table name
|
||||||
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
|
// Check if there are results
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
// Start HTML table
|
||||||
|
echo '<table border="1">
|
||||||
|
<thead>
|
||||||
|
<tr>';
|
||||||
|
|
||||||
|
// Output table headers (assuming column names are known)
|
||||||
|
$fields = $result->fetch_fields();
|
||||||
|
foreach ($fields as $field) {
|
||||||
|
if ($field->name != 'id') {
|
||||||
|
echo '<th>' . htmlspecialchars($field->name ?? '') . '</th>';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// echo '<th>actions</th>';
|
||||||
|
|
||||||
|
echo ' </tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>';
|
||||||
|
|
||||||
|
// Output table rows
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
echo '<tr onclick="openDetail(' . $row['id'] . ')">';
|
||||||
|
foreach ($row as $key => $value) {
|
||||||
|
if ($key != 'id') {
|
||||||
|
echo '<td>' . htmlspecialchars($value ?? '') . '</td>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// echo '<td><img src="cancel-icon.webp" title="Cancel PPR" style="width: 25px; height: auto;" onclick="markCancel(' . $row['id'] . ')"><img src="cancel-icon.webp" title="DELETE PPR" style="width: 25px; height: auto;" onclick="deletePpr(' . $row['id'] . ')"><img src="land.webp" title="Mark Landed" style="width: 30px; height: auto;" onclick="markLanded(' . $row['id'] . ')"></td>';
|
||||||
|
echo '</tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo ' </tbody></table>';
|
||||||
|
} else {
|
||||||
|
echo "No results found.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the database connection
|
||||||
|
$conn->close();
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<center><button onclick="openPopup()">Log New PPR</button></center>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function openPopup() {
|
||||||
|
window.open("input.html", "PopupWindow", "toolbar=no, location=no, directories=no,status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=yes, width=600, height=1100");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
BIN
arrive.png
Normal file
BIN
arrive.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
BIN
depart.png
Normal file
BIN
depart.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
196
functions.php
196
functions.php
@@ -6,46 +6,86 @@ $username = 'ppruser'; // Replace with your database username
|
|||||||
$password = 'iJ8kN*5[g6P3jaqN'; // Replace with your database password
|
$password = 'iJ8kN*5[g6P3jaqN'; // Replace with your database password
|
||||||
$database = 'pprdevdb'; // Replace with your database name
|
$database = 'pprdevdb'; // Replace with your database name
|
||||||
|
|
||||||
|
$mailHost = 'send.one.com'; // Your SMTP server
|
||||||
|
$mailSMTPAuth = true;
|
||||||
|
$mailUsername = 'noreply@swansea-airport.wales';
|
||||||
|
$mailPassword = 'SASAGoForward2155';
|
||||||
|
//$mailSMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
||||||
|
$mailPort = 465;
|
||||||
|
$mailFromAddress = 'noreply@swansea-airport.wales';
|
||||||
|
$mailFromName = 'Swansea Airport';
|
||||||
|
|
||||||
|
$baseUrl = "https://ppr.swansea-airport.wales/dev";
|
||||||
|
|
||||||
|
use PHPMailer\PHPMailer\PHPMailer;
|
||||||
|
use PHPMailer\PHPMailer\Exception;
|
||||||
|
|
||||||
|
function getUserIP() {
|
||||||
|
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
||||||
|
return $_SERVER['HTTP_CLIENT_IP'];
|
||||||
|
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||||
|
return $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||||
|
} else {
|
||||||
|
return $_SERVER['REMOTE_ADDR'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function connectDb() {
|
function connectDb() {
|
||||||
|
|
||||||
// Create connection
|
// Create connection
|
||||||
$conn = new mysqli( $GLOBALS['host'], $GLOBALS['username'], $GLOBALS['password'], $GLOBALS['database']);
|
$conn = new mysqli( $GLOBALS['host'], $GLOBALS['username'], $GLOBALS['password'], $GLOBALS['database']);
|
||||||
|
|
||||||
// Check connection
|
// Check connection
|
||||||
if ($conn->connect_error) {
|
if ($conn->connect_error) {
|
||||||
die("Connection failed: " . $conn->connect_error);
|
die("Connection failed: " . $conn->connect_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $conn;
|
return $conn;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function logJournal($conn, $id, $message) {
|
||||||
|
|
||||||
|
if (isset($_SERVER['PHP_AUTH_USER'])) {
|
||||||
|
$user = $_SERVER['PHP_AUTH_USER'];
|
||||||
|
} else {
|
||||||
|
$user = "None";
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("INSERT INTO journal (ppr_id, entry, user, ip) VALUES (?, ?, ?, ?)");
|
||||||
|
$ip = getUserIP();
|
||||||
|
$stmt->bind_param("isss", $id, $message, $user, $ip);
|
||||||
|
$stmt->execute();
|
||||||
|
$stmt->close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function require_db_auth() {
|
function require_db_auth() {
|
||||||
|
|
||||||
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
|
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
|
||||||
send_auth_headers();
|
send_auth_headers();
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = $_SERVER['PHP_AUTH_USER'];
|
$user = $_SERVER['PHP_AUTH_USER'];
|
||||||
$pass = $_SERVER['PHP_AUTH_PW'];
|
$pass = $_SERVER['PHP_AUTH_PW'];
|
||||||
|
|
||||||
$conn = connectDb();
|
$conn = connectDb();
|
||||||
|
|
||||||
$stmt = $conn->prepare("SELECT password FROM users WHERE username = ?");
|
$stmt = $conn->prepare("SELECT password FROM users WHERE username = ?");
|
||||||
$stmt->bind_param("s", $user);
|
$stmt->bind_param("s", $user);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
$stmt->store_result();
|
$stmt->store_result();
|
||||||
$stmt->bind_result($stored_hash);
|
$stmt->bind_result($stored_hash);
|
||||||
$stmt->fetch();
|
$stmt->fetch();
|
||||||
|
|
||||||
// Verify the password
|
// Verify the password
|
||||||
if ($stmt->num_rows == 0 || !password_verify($pass, $stored_hash)) {
|
if ($stmt->num_rows == 0 || !password_verify($pass, $stored_hash)) {
|
||||||
send_auth_headers();
|
send_auth_headers();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the connection
|
// Close the connection
|
||||||
$stmt->close();
|
$stmt->close();
|
||||||
$conn->close();
|
$conn->close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,19 +96,93 @@ function send_auth_headers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function require_auth() {
|
function require_auth() {
|
||||||
$AUTH_USER = 'admin';
|
$AUTH_USER = 'admin';
|
||||||
$AUTH_PASS = 'admin';
|
$AUTH_PASS = 'admin';
|
||||||
header('Cache-Control: no-cache, must-revalidate, max-age=0');
|
header('Cache-Control: no-cache, must-revalidate, max-age=0');
|
||||||
$has_supplied_credentials = !(empty($_SERVER['PHP_AUTH_USER']) && empty($_SERVER['PHP_AUTH_PW']));
|
$has_supplied_credentials = !(empty($_SERVER['PHP_AUTH_USER']) && empty($_SERVER['PHP_AUTH_PW']));
|
||||||
$is_not_authenticated = (
|
$is_not_authenticated = (
|
||||||
!$has_supplied_credentials ||
|
!$has_supplied_credentials ||
|
||||||
$_SERVER['PHP_AUTH_USER'] != $AUTH_USER ||
|
$_SERVER['PHP_AUTH_USER'] != $AUTH_USER ||
|
||||||
$_SERVER['PHP_AUTH_PW'] != $AUTH_PASS
|
$_SERVER['PHP_AUTH_PW'] != $AUTH_PASS
|
||||||
);
|
);
|
||||||
if ($is_not_authenticated) {
|
if ($is_not_authenticated) {
|
||||||
header('HTTP/1.1 401 Authorization Required');
|
header('HTTP/1.1 401 Authorization Required');
|
||||||
header('WWW-Authenticate: Basic realm="PPR"');
|
header('WWW-Authenticate: Basic realm="PPR"');
|
||||||
echo 'Text to send if user hits Cancel button';
|
echo 'Text to send if user hits Cancel button';
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateSecureToken($email, $entryId) {
|
||||||
|
$secretKey = "your-very-secret-key"; // Use an environment variable for this
|
||||||
|
$timestamp = time();
|
||||||
|
$data = "$email|$entryId|$timestamp";
|
||||||
|
$hash = hash_hmac('sha256', $data, $secretKey);
|
||||||
|
return base64_encode("$data|$hash");
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateSecureToken($token) {
|
||||||
|
$secretKey = "your-very-secret-key";
|
||||||
|
$decoded = base64_decode($token);
|
||||||
|
|
||||||
|
if (!$decoded) return false;
|
||||||
|
|
||||||
|
list($email, $entryId, $timestamp, $hash) = explode('|', $decoded);
|
||||||
|
|
||||||
|
// Check expiration (e.g., valid for 1 hour)
|
||||||
|
//if (time() - $timestamp > 3600) {
|
||||||
|
// return false;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Verify hash
|
||||||
|
$data = "$email|$entryId|$timestamp";
|
||||||
|
$validHash = hash_hmac('sha256', $data, $secretKey);
|
||||||
|
|
||||||
|
if (!hash_equals($validHash, $hash)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['email' => $email, 'entryId' => $entryId];
|
||||||
|
}
|
||||||
|
|
||||||
|
function generatePprEmail($entryId, $email, $ac_reg) {
|
||||||
|
global $conn, $mailHost, $mailSMTPAuth, $mailUsername, $mailPassword, $mailPort, $baseUrl, $mailFromAddress, $mailFromName;
|
||||||
|
|
||||||
|
if (!class_exists('PHPMailer\PHPMailer\PHPMailer')) {
|
||||||
|
require '../vendor/autoload.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = generateSecureToken($email, $entryId);
|
||||||
|
$secureLink = $baseUrl . "/pilotppr.php?op=view&token=" . urlencode($token);
|
||||||
|
|
||||||
|
$mail = new PHPMailer(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$mail->isSMTP();
|
||||||
|
$mail->Host = $mailHost;
|
||||||
|
$mail->SMTPAuth = $mailSMTPAuth;
|
||||||
|
$mail->Username = $mailUsername;
|
||||||
|
$mail->Password = $mailPassword;
|
||||||
|
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
|
||||||
|
$mail->Port = $mailPort;
|
||||||
|
|
||||||
|
$mail->setFrom($mailFromAddress, $mailFromName);
|
||||||
|
$mail->addAddress($email);
|
||||||
|
|
||||||
|
$mail->isHTML(true);
|
||||||
|
$mail->Subject = "PPR Confirmation for " . $ac_reg;
|
||||||
|
$mail->Body = "
|
||||||
|
<p>This is to confirm we have received your PPR. To view or cancel your PPR please click the button:</p>
|
||||||
|
<a href='$secureLink' style='display: inline-block; padding: 10px 20px; color: white; background-color: #007bff; text-decoration: none; border-radius: 5px;'>View PPR</a>
|
||||||
|
";
|
||||||
|
|
||||||
|
$mail->send();
|
||||||
|
echo "Email sent successfully!";
|
||||||
|
logJournal($conn, $entryId, "Confirm email sent");
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "Email sending failed: {$mail->ErrorInfo}";
|
||||||
|
logJournal($conn, $entryId, "Confirm email FAILED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
30
input.html
30
input.html
@@ -8,6 +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;
|
||||||
});
|
});
|
||||||
|
|
||||||
function fetchResults() {
|
function fetchResults() {
|
||||||
@@ -121,6 +122,12 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
|
box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.optional-label {
|
||||||
|
color: gray;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -138,7 +145,7 @@
|
|||||||
<input type="text" id="ac_type" name="ac_type" required>
|
<input type="text" id="ac_type" name="ac_type" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="ac_call">Callsign</label>
|
<label class="optional-label" for="ac_call">Callsign (optional)</label>
|
||||||
<input type="text" id="ac_call" name="ac_call">
|
<input type="text" id="ac_call" name="ac_call">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -150,13 +157,26 @@
|
|||||||
<input type="text" id="in_from" name="in_from" required>
|
<input type="text" id="in_from" name="in_from" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="pob_in">POB</label>
|
<label for="pob_in">POB Inbound</label>
|
||||||
<input type="number" id="pob_in" name="pob_in" required>
|
<input type="number" id="pob_in" name="pob_in" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group"></div>
|
<div class="form-group"></div>
|
||||||
<label for="eta">ETA</label>
|
<label for="eta">ETA</label>
|
||||||
<input type="datetime-local" id="eta" name="eta">
|
<input type="datetime-local" id="eta" name="eta">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="out_to">Out to</label>
|
||||||
|
<input type="text" id="out_to" name="out_to">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="pob_out">POB Outbound</label>
|
||||||
|
<input type="number" id="pob_out" name="pob_out" >
|
||||||
|
</div>
|
||||||
|
<div class="form-group"></div>
|
||||||
|
<label for="eta">Departing At</label>
|
||||||
|
<input type="datetime-local" id="etd" name="etd">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="fuel">Fuel Needed</label>
|
<label for="fuel">Fuel Needed</label>
|
||||||
<select id="fuel" name="fuel" single>
|
<select id="fuel" name="fuel" single>
|
||||||
@@ -167,16 +187,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="email">Email</label>
|
<label class="optional-label" for="email">Email (optional)</label>
|
||||||
<input type="email" id="email" name="email" >
|
<input type="email" id="email" name="email" >
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="phone">Phone</label>
|
<label class="optional-label" for="phone">Phone (optional)</label>
|
||||||
<input type="text" id="phone" name="phone" >
|
<input type="text" id="phone" name="phone" >
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="notes">Notes</label>
|
<label class="optional-label" for="notes">Notes (optional)</label>
|
||||||
<textarea id="message" name="notes" rows="4" ></textarea>
|
<textarea id="message" name="notes" rows="4" ></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
26
newppr.php
26
newppr.php
@@ -1,33 +1,41 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
include("functions.php");
|
include("functions.php");
|
||||||
require_db_auth();
|
require_db_auth();
|
||||||
|
|
||||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||||
|
|
||||||
$conn = connectDb();
|
$conn = connectDb();
|
||||||
|
|
||||||
$columns = [];
|
$columns = [];
|
||||||
$values = [];
|
$values = [];
|
||||||
|
|
||||||
echo "<h2>Received POST Data:</h2>";
|
echo "<h2>Received POST Data:</h2><ul>";
|
||||||
echo "<ul>";
|
|
||||||
foreach ($_POST as $key => $value) {
|
foreach ($_POST as $key => $value) {
|
||||||
$columns[] = "`" . $conn->real_escape_string($key) . "`";
|
$escaped_key = "`" . $conn->real_escape_string($key) . "`";
|
||||||
$values[] = "'" . $conn->real_escape_string($value) . "'";
|
$escaped_value = ($value === '' || $value === null) ? "NULL" : (is_numeric($value) ? $value : "'" . $conn->real_escape_string($value) . "'");
|
||||||
|
$columns[] = $escaped_key;
|
||||||
|
$values[] = $escaped_value;
|
||||||
echo "<li><strong>" . htmlspecialchars($key) . ":</strong> " . htmlspecialchars($value) . "</li>";
|
echo "<li><strong>" . htmlspecialchars($key) . ":</strong> " . htmlspecialchars($value) . "</li>";
|
||||||
}
|
}
|
||||||
|
echo "</ul>";
|
||||||
|
|
||||||
if (!empty($columns)) {
|
if (!empty($columns)) {
|
||||||
$sql = "INSERT INTO submitted (created_by, " . implode(",", $columns) . ") VALUES ('" . $_SERVER['PHP_AUTH_USER'] . "'," . implode(",", $values) . ")";
|
$sql = "INSERT INTO submitted (created_by, " . implode(",", $columns) . ") VALUES ('" . $_SERVER['PHP_AUTH_USER'] . "'," . implode(",", $values) . ")";
|
||||||
echo $sql;
|
echo $sql;
|
||||||
|
|
||||||
if ($conn->query($sql) === TRUE) {
|
if ($conn->query($sql) === TRUE) {
|
||||||
echo "<p>Data successfully inserted into database.</p>";
|
$lastId = $conn->insert_id;
|
||||||
|
echo "<p>Data successfully inserted into database with id = " . $lastId . "</p>";
|
||||||
|
if (!empty($_POST['email'])) {
|
||||||
|
echo "Email is set to " . $_POST['email'];
|
||||||
|
generatePprEmail($lastId, $_POST['email'], $_POST['ac_reg']);
|
||||||
|
} else {
|
||||||
|
echo "Email is not set.";
|
||||||
|
}
|
||||||
echo '<script>window.close();</script>';
|
echo '<script>window.close();</script>';
|
||||||
} else {
|
} else {
|
||||||
echo "<p>Error inserting data: " . $conn->error . "</p>";
|
echo "<p>Error inserting data: " . $conn->error . "</p>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
echo "</ul>";
|
|
||||||
} else {
|
} else {
|
||||||
echo "<h2>No POST data received.</h2>";
|
echo "<h2>No POST data received.</h2>";
|
||||||
}
|
}
|
||||||
|
|||||||
181
pilotppr.php
Normal file
181
pilotppr.php
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<?php
|
||||||
|
include("functions.php");
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Swansea PPR Details</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 80%;
|
||||||
|
margin: 20px auto;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.details {
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.details p {
|
||||||
|
margin: 10px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.details p strong {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-link {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 20px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #007BFF;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-link:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 1rem;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container" id="message">
|
||||||
|
These details have been submitted as your PPR. We look forward to seeing you at Swansea Airport!<p>To cancel your PPR, use the button below. It is currently not possible to make any changes here, but please feel free to cancel if you need to and create a new PPR.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
if (isset($_GET['token'])) {
|
||||||
|
$result = validateSecureToken($_GET['token']);
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
// Token is valid, allow changes to database entry
|
||||||
|
$email = $result['email'];
|
||||||
|
$entryId = $result['entryId'];
|
||||||
|
} else {
|
||||||
|
die("Invalid or expired token.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch($_GET['op']) {
|
||||||
|
case "cancel":
|
||||||
|
opCancel($entryId);
|
||||||
|
break;
|
||||||
|
case "view":
|
||||||
|
opView($entryId);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function opCancel($entryId) {
|
||||||
|
|
||||||
|
$conn = connectDb();
|
||||||
|
$sql = "UPDATE submitted SET status = 'CANCELED' where id = " . $entryId;
|
||||||
|
$result = $conn->query($sql);
|
||||||
|
logJournal($conn, $entryId, "Marked Canceled by Pilot");
|
||||||
|
$conn->close();
|
||||||
|
echo'<script>document.getElementById("message").innerHTML = "Your PPR has been canceled. Thank you for letting us know!";</script>';
|
||||||
|
}
|
||||||
|
|
||||||
|
function opView($entryId) {
|
||||||
|
|
||||||
|
$conn = connectDb();
|
||||||
|
$sql = "SELECT * FROM submitted WHERE status = 'NEW' AND id = " . $entryId;
|
||||||
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
// Output data of the row
|
||||||
|
$row = $result->fetch_assoc();
|
||||||
|
echo '<div class="container">';
|
||||||
|
echo '<div class="details"><p><strong>Aircraft Reg: </strong>' . $row['ac_reg'] . "</p>";
|
||||||
|
echo "<p><strong>Aircraft Type:</strong> " . $row['ac_type'] . "</p>";
|
||||||
|
echo "<p><strong>Callsign:</strong> " . $row['ac_call'] . "</p>";
|
||||||
|
echo "<p><strong>Captain's Name:</strong> " . $row['captain'] . "</p>";
|
||||||
|
echo "<p><strong>Arriving From:</strong> " . $row['in_from'] . "</p>";
|
||||||
|
echo "<p><strong>POB IN:</strong> " . $row['pob_in'] . "</p>";
|
||||||
|
echo "<p><strong>ETA:</strong> " . $row['eta'] . "</p>";
|
||||||
|
|
||||||
|
echo "<p><strong>Fuel Required:</strong> " . $row['fuel'] . "</p>";
|
||||||
|
|
||||||
|
echo "<p><strong>POB OUT:</strong> " . $row['pob_out'] . "</p>";
|
||||||
|
echo "<p><strong>Outbound To:</strong> " . $row['out_to'] . "</p>";
|
||||||
|
echo "<p><strong>ETD:</strong> " . $row['etd'] . "</p>";
|
||||||
|
|
||||||
|
echo "<p><strong>Email Address:</strong> " . $row['email'] . "</p>";
|
||||||
|
echo "<p><strong>Phone:</strong> " . $row['phone'] . "</p>";
|
||||||
|
|
||||||
|
echo "<p><strong>Notes:</strong> " . $row['notes'] . "</p></div>";
|
||||||
|
echo '<button onclick="confirmWithSweetAlert(\'pilotppr.php?op=cancel&token=' . urlencode($_GET['token']) . '\')">Cancel PPR</button>';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
echo "";
|
||||||
|
echo'<script>document.getElementById("message").innerHTML = "No details found for the given ID. This could mean the PPR has been canceled already.";</script>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$conn->close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!-- Include SweetAlert -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function confirmWithSweetAlert(url) {
|
||||||
|
Swal.fire({
|
||||||
|
title: "Cancel PPR?",
|
||||||
|
text: "We hope to see you soon!",
|
||||||
|
icon: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: "Cancel PPR",
|
||||||
|
cancelButtonText: "Keep PPR"
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
window.location.href = url;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
"name": "Arriving From"
|
"name": "Arriving From"
|
||||||
},
|
},
|
||||||
"ca4ac44f-0388-4a70-a072-38276ed2ac13": {
|
"ca4ac44f-0388-4a70-a072-38276ed2ac13": {
|
||||||
"value": "11\/02\/2025 14:33",
|
"value": "14\/03\/2025 14:33",
|
||||||
"name": "ETA"
|
"name": "ETA"
|
||||||
},
|
},
|
||||||
"6fc47c54-7383-48fd-93fc-d8080f5ed8f5": {
|
"6fc47c54-7383-48fd-93fc-d8080f5ed8f5": {
|
||||||
|
|||||||
276
tower.php
276
tower.php
@@ -7,6 +7,8 @@ require_db_auth();
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="refresh" content="300">
|
<meta http-equiv="refresh" content="300">
|
||||||
|
<!-- Include SweetAlert -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
let rows = document.querySelectorAll("table tbody tr");
|
let rows = document.querySelectorAll("table tbody tr");
|
||||||
@@ -27,6 +29,37 @@ require_db_auth();
|
|||||||
<title>Swansea Daily PPR</title>
|
<title>Swansea Daily PPR</title>
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
|
.checkbox-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
padding: 10px;
|
||||||
|
background: #f9f9f9;
|
||||||
|
border-radius: 8px;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading {
|
||||||
|
width: 80%;
|
||||||
|
margin: 20px auto;
|
||||||
|
background-color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
font-size: 20pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* Styling for the table */
|
/* Styling for the table */
|
||||||
table {
|
table {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
@@ -91,18 +124,121 @@ require_db_auth();
|
|||||||
background-color: #0056b3;
|
background-color: #0056b3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.state-CANCELED {
|
||||||
|
text-decoration: line-through;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.state-LANDED {
|
||||||
|
font-style: italic;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function markLanded(id) {
|
function markDeparted(id) {
|
||||||
page="action.php?op=landed&id=" + id;
|
|
||||||
|
const now = new Date();
|
||||||
|
const currentTime = now.toISOString().slice(11, 16); // Extract HH:MM
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: "Depart Aircraft at time",
|
||||||
|
html: `<input type="time" id="timepicker" class="swal2-input" value="${currentTime}">`,
|
||||||
|
icon: "info",
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: "Departed",
|
||||||
|
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=departed&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();
|
||||||
window.location.reload(true);
|
window.location.reload(true);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function markLanded(id) {
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const currentTime = now.toISOString().slice(11, 16); // Extract HH:MM
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: "Land Aircraft at time",
|
||||||
|
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 markLanded(id) {
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const currentTime = now.toISOString().slice(11, 16); // Extract HH:MM
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: "Land Aircraft at time",
|
||||||
|
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) {
|
function markCancel(id) {
|
||||||
page="action.php?op=cancel&id=" + id;
|
page="action.php?op=cancel&id=" + id;
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
@@ -120,8 +256,19 @@ require_db_auth();
|
|||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<center><h2>Swansea Inbound PPR <?php echo date('l d M Y'); ?></h2></center>
|
<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 class="heading">Inbound PPR</div>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
@@ -133,15 +280,8 @@ if ($conn->connect_error) {
|
|||||||
die("Connection failed: " . $conn->connect_error);
|
die("Connection failed: " . $conn->connect_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
$custom_headings = [
|
|
||||||
'column1' => 'Custom Heading 1',
|
|
||||||
'column2' => 'Custom Heading 2',
|
|
||||||
'column3' => 'Custom Heading 3'
|
|
||||||
// Add more custom headings as needed
|
|
||||||
];
|
|
||||||
|
|
||||||
// Define your SQL query
|
// Define your SQL query
|
||||||
$sql = "SELECT id, 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' 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 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);
|
||||||
@@ -149,14 +289,14 @@ $result = $conn->query($sql);
|
|||||||
// Check if there are results
|
// Check if there are results
|
||||||
if ($result->num_rows > 0) {
|
if ($result->num_rows > 0) {
|
||||||
// Start HTML table
|
// Start HTML table
|
||||||
echo '<table border="1">
|
echo '<table border="1" id="arrivals">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>';
|
<tr>';
|
||||||
|
|
||||||
// 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 != 'id' && $field->name != 'ac_call') {
|
if ($field->name != 'status' && $field->name != 'id' && $field->name != 'ac_call') {
|
||||||
echo '<th>' . htmlspecialchars($field->name ?? '') . '</th>';
|
echo '<th>' . htmlspecialchars($field->name ?? '') . '</th>';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,9 +309,9 @@ if ($result->num_rows > 0) {
|
|||||||
|
|
||||||
// Output table rows
|
// Output table rows
|
||||||
while ($row = $result->fetch_assoc()) {
|
while ($row = $result->fetch_assoc()) {
|
||||||
echo '<tr onclick="openDetail(' . $row['id'] . ')">';
|
echo '<tr class="state-' . $row['status'] . '" data-id=' . $row['id'] . '>';
|
||||||
foreach ($row as $key => $value) {
|
foreach ($row as $key => $value) {
|
||||||
if ($key != 'id' && $key != 'ac_call') {
|
if ($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 {
|
} else {
|
||||||
@@ -179,7 +319,63 @@ if ($result->num_rows > 0) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
echo '<td><img src="cancel-icon.webp" title="Cancel PPR" style="width: 25px; height: auto;" onclick="markCancel(' . $row['id'] . ')"><img src="land.webp" title="Mark Landed" style="width: 30px; height: auto;" onclick="markLanded(' . $row['id'] . ')"></td>';
|
echo '<td><img src="cancel-icon.webp" title="Cancel PPR" style="width: 25px; height: auto;" onclick="markCancel(' . $row['id'] . ')"><img src="arrive.png" title="Land" style="width: 30px; height: auto;" onclick="markLanded(' . $row['id'] . ')"></td>';
|
||||||
|
echo '</tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo ' </tbody></table>';
|
||||||
|
} else {
|
||||||
|
echo "No results found.";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="heading">Booking Out</div>
|
||||||
|
|
||||||
|
<div id="landed">
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// Execute the query
|
||||||
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
|
// Check if there are results
|
||||||
|
if ($result->num_rows > 0) {
|
||||||
|
// Start HTML table
|
||||||
|
echo '<table border="1" id="landed">
|
||||||
|
<thead>
|
||||||
|
<tr>';
|
||||||
|
|
||||||
|
// Output table headers (assuming column names are known)
|
||||||
|
$fields = $result->fetch_fields();
|
||||||
|
foreach ($fields as $field) {
|
||||||
|
if ($field->name != 'status' && $field->name != 'id' && $field->name != 'ac_call') {
|
||||||
|
echo '<th>' . htmlspecialchars($field->name ?? '') . '</th>';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
echo '<th>actions</th>';
|
||||||
|
|
||||||
|
echo ' </tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>';
|
||||||
|
|
||||||
|
// Output table rows
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
echo '<tr class="state-' . $row['status'] . '" data-id=' . $row['id'] . '>';
|
||||||
|
foreach ($row as $key => $value) {
|
||||||
|
if ($key != 'status' && $key != 'id' && $key != 'ac_call') {
|
||||||
|
if ($key == 'ac_reg' && $row['ac_call'] != NULL) {
|
||||||
|
echo '<td>' . htmlspecialchars($row['ac_call'] ?? '') . "<br><span class=acreg>" . $value . '</span></td>';
|
||||||
|
} else {
|
||||||
|
echo '<td>' . htmlspecialchars($value ?? '') . '</td>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo '<td><img src="cancel-icon.webp" title="Cancel PPR" style="width: 25px; height: auto;" onclick="markCancel(' . $row['id'] . ')"><img src="depart.png" title="Depart" style="width: 30px; height: auto;" onclick="markDeparted(' . $row['id'] . ')"></td>';
|
||||||
echo '</tr>';
|
echo '</tr>';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,10 +389,52 @@ $conn->close();
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<center><button onclick="openPopup()">Log New PPR</button></center>
|
<center><button onclick="openPopup()">Log New PPR</button></center>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function openPopup() {
|
function openPopup() {
|
||||||
window.open("input.html", "PopupWindow", "toolbar=no, location=no, directories=no,status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=yes, width=600, height=1100");
|
popup = window.open("input.html", "PopupWindow", "toolbar=no, location=no, directories=no,status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=yes, width=600, height=1100");
|
||||||
|
const checkPopup = setInterval(() => {
|
||||||
|
if (popup && popup.closed) {
|
||||||
|
clearInterval(checkPopup);
|
||||||
|
window.location.reload(); // Reload parent window
|
||||||
|
}
|
||||||
|
}, 500); // Check every 500ms
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function toggleRows(className) {
|
||||||
|
document.querySelectorAll('.' + className).forEach(row => {
|
||||||
|
row.classList.toggle('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
document.querySelectorAll('.state-CANCELED').forEach(row => {
|
||||||
|
row.classList.add('hidden');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("arrivals")?.addEventListener("click", clickRow);
|
||||||
|
document.getElementById("landed")?.addEventListener("click", clickRow);
|
||||||
|
|
||||||
|
function clickRow (event) {
|
||||||
|
let td = event.target.closest("td");
|
||||||
|
if (!td) return; // Clicked outside <td>
|
||||||
|
|
||||||
|
let tr = td.parentElement; // Get the row
|
||||||
|
|
||||||
|
if (td !== tr.lastElementChild) {
|
||||||
|
let rowId = tr.dataset.id; // Get the unique row ID
|
||||||
|
openDetail(rowId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
52
update_data.php
Normal file
52
update_data.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
include("functions.php");
|
||||||
|
require_db_auth();
|
||||||
|
|
||||||
|
$conn = connectDb();
|
||||||
|
|
||||||
|
// Ensure required parameters are received
|
||||||
|
if (!isset($_POST['id'], $_POST['column'], $_POST['new_value'], $_POST['old_value'])) {
|
||||||
|
die(json_encode(['error' => 'Invalid request']));
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = intval($_POST['id']); // Sanitize ID
|
||||||
|
$column = $_POST['column'];
|
||||||
|
$old_value = $_POST['old_value'];
|
||||||
|
$new_value = $_POST['new_value'];
|
||||||
|
|
||||||
|
// Allowed columns for security (prevent SQL injection)
|
||||||
|
$allowed_columns = [
|
||||||
|
'ac_reg', 'ac_type', 'ac_call', 'captain',
|
||||||
|
'in_from', 'pob_in', 'eta', 'fuel',
|
||||||
|
'pob_out', 'out_to', 'etd', 'email', 'phone', 'notes'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!in_array($column, $allowed_columns)) {
|
||||||
|
die(json_encode(['error' => 'Invalid column']));
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $conn->prepare("UPDATE submitted SET `$column` = ? WHERE id = ?");
|
||||||
|
if (!$stmt) {
|
||||||
|
die(json_encode(['error' => 'Prepare statement failed']));
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt->bind_param("si", $new_value, $id);
|
||||||
|
$success = $stmt->execute();
|
||||||
|
$stmt->close();
|
||||||
|
|
||||||
|
// If update successful, log the change
|
||||||
|
if ($success) {
|
||||||
|
$message = $column . " changed from " . $old_value . " to " . $new_value;
|
||||||
|
logJournal($conn, $id, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
$conn->close();
|
||||||
|
|
||||||
|
// Return JSON response
|
||||||
|
echo json_encode([
|
||||||
|
'success' => $success,
|
||||||
|
'column' => $column,
|
||||||
|
'old_value' => $old_value,
|
||||||
|
'new_value' => $new_value
|
||||||
|
]);
|
||||||
|
?>
|
||||||
150
webhook.php
150
webhook.php
@@ -1,84 +1,104 @@
|
|||||||
<?php
|
<?php
|
||||||
|
include("functions.php");
|
||||||
|
|
||||||
// Basic connection settings
|
$created_by = "Website (DEV)";
|
||||||
$databaseHost = 'sasaprod.pattinson.org';
|
|
||||||
$databaseUsername = 'root';
|
|
||||||
$databasePassword = 'PugPictureMousePen';
|
|
||||||
$databaseName = 'pprdevdb';
|
|
||||||
$created_by = "webhook-dev";
|
|
||||||
|
|
||||||
//ini_set("error_log", "ppr.log");
|
$conn = connectDb();
|
||||||
error_log("Webhook handler called");
|
|
||||||
|
|
||||||
// Connect to the database
|
|
||||||
$mysqli = mysqli_connect($databaseHost, $databaseUsername, $databasePassword, $databaseName);
|
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
|
|
||||||
#if($json = json_decode(file_get_contents("php://input"), true)) {
|
|
||||||
if($json = json_decode(file_get_contents("testhook.json"), true)) {
|
|
||||||
|
|
||||||
$data = $json;
|
|
||||||
|
|
||||||
|
// Check if the URL has a 'test' parameter set
|
||||||
|
if (isset($_GET['test'])) {
|
||||||
|
$payload = json_decode(file_get_contents('testhook.json'), true);
|
||||||
|
} else {
|
||||||
|
$payload = json_decode(file_get_contents('php://input'), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
print_r($data);
|
// Log the received payload for debugging
|
||||||
|
error_log("Received payload: " . print_r($payload, true));
|
||||||
|
|
||||||
$fieldMap = array();
|
// Mapping of JSON 'name' keys to database column names
|
||||||
$fieldMap['ac_reg'] = '617dd0cd-2d17-4d7f-826b-5348afdb30b3';
|
$columnMapping = [
|
||||||
$fieldMap['ac_type'] = '148a55d8-5357-49a3-b9aa-2a5d4dc64173';
|
"Aircraft Registration" => "ac_reg",
|
||||||
$fieldMap['ac_call'] = '52d7bc90-9d26-48a1-82db-b91b4ccd2f92';
|
"Aircraft Type" => "ac_type",
|
||||||
$fieldMap['captain'] = '49b2de0d-5bd6-4b0c-86dd-b18b85f8b8ff';
|
"Callsign" => "ac_call",
|
||||||
$fieldMap['fuel'] = 'd153c8a5-8345-4e6a-abfd-cf8adcc06f2d';
|
"Captain or PIC Name" => "captain",
|
||||||
$fieldMap['in_from'] = '4b4f7ecd-f80c-4e86-a7ab-6fadb3220df8';
|
"Arriving From" => "in_from",
|
||||||
$fieldMap['eta'] = 'ca4ac44f-0388-4a70-a072-38276ed2ac13';
|
"ETA" => "eta",
|
||||||
$fieldMap['pob_in'] = '6fc47c54-7383-48fd-93fc-d8080f5ed8f5';
|
"POB Inbound" => "pob_in",
|
||||||
$fieldMap['out_to'] = 'ba95fd3f-1ec0-4553-95d3-a0b6a850738d';
|
"Fuel Required" => "fuel",
|
||||||
$fieldMap['etd'] = '53d60abd-eb75-4b1f-92b6-5d47d26367ec';
|
"Departing To" => "out_to",
|
||||||
$fieldMap['pob_out'] = 'd1ac0860-31f4-4914-9d0b-cae42dfc7eda';
|
"ETD" => "etd",
|
||||||
$fieldMap['email'] = '0198c86c-edd1-4aaf-93a1-d68f8fc8c365';
|
"POB Outbound" => "pob_out",
|
||||||
$fieldMap['phone'] = 'e40ebc2d-887b-42b3-931d-c981c76b0c20';
|
"Email" => "email",
|
||||||
$fieldMap['notes'] = '73d26c2c-1d3d-44e2-82fc-3a1a2600c393';
|
"Phone Number" => "phone",
|
||||||
|
"Additional Information" => "notes"
|
||||||
|
];
|
||||||
|
|
||||||
#print_r($json['data'][$fieldMap['eta']]['value']);
|
// Prepare the SQL statement dynamically
|
||||||
|
$columns = [];
|
||||||
|
$values = [];
|
||||||
|
$placeholders = [];
|
||||||
|
$types = '';
|
||||||
|
$email = '';
|
||||||
|
$ac_reg = '';
|
||||||
|
|
||||||
$stmt = mysqli_prepare($mysqli, "INSERT INTO submitted (ac_reg, ac_type, captain, fuel, in_from, eta, pob_in, etd, pob_out, email, phone, notes, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
foreach ($payload['data'] as $key => $field) {
|
||||||
|
$name = $field['name'];
|
||||||
|
if (isset($columnMapping[$name])) {
|
||||||
|
$columns[] = $columnMapping[$name];
|
||||||
|
$value = $field['value'];
|
||||||
|
|
||||||
|
// Transform ETA and ETD to MySQL datetime format
|
||||||
|
if ($name == "ETA" || $name == "ETD") {
|
||||||
|
$date = DateTime::createFromFormat('d/m/Y H:i', $value);
|
||||||
|
$value = $date->format('Y-m-d H:i:s');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle POB Inbound and POB Outbound as integers
|
||||||
|
if ($name == "POB Inbound" || $name == "POB Outbound") {
|
||||||
|
$types .= 'i';
|
||||||
|
} else {
|
||||||
|
$types .= 's'; // Assuming all other values are strings
|
||||||
|
}
|
||||||
|
|
||||||
|
$values[] = $value;
|
||||||
|
$placeholders[] = '?';
|
||||||
|
|
||||||
// Check if the statement was prepared correctly
|
// Capture email and aircraft registration for email sending
|
||||||
if ($stmt === false) {
|
if ($name == "Email") {
|
||||||
die('MySQL prepare error: ' . mysqli_error($conn));
|
$email = $value;
|
||||||
|
}
|
||||||
|
if ($name == "Aircraft Registration") {
|
||||||
|
$ac_reg = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$ac_reg = $json['data'][$fieldMap['ac_reg']]['value'];
|
// Add created_by to the columns, values, and placeholders
|
||||||
$ac_type = $json['data'][$fieldMap['ac_type']]['value'];
|
$columns[] = 'created_by';
|
||||||
$captain = $json['data'][$fieldMap['captain']]['value'];
|
$values[] = $created_by;
|
||||||
$in_from = $json['data'][$fieldMap['in_from']]['value'];
|
$placeholders[] = '?';
|
||||||
$fuel = $json['data'][$fieldMap['fuel']]['value'];
|
$types .= 's';
|
||||||
$date = DateTime::createFromFormat('d/m/Y H:i', $json['data'][$fieldMap['eta']]['value']);
|
|
||||||
$eta = $date->format('Y-m-d H:i:s');
|
|
||||||
$pob_in = $json['data'][$fieldMap['pob_in']]['value'];
|
|
||||||
|
|
||||||
if (array_key_exists($fieldMap['out_to'], $json['data'])) {
|
$sql = "INSERT INTO submitted (" . implode(', ', $columns) . ") VALUES (" . implode(', ', $placeholders) . ")";
|
||||||
$date = DateTime::createFromFormat('d/m/Y H:i', $json['data'][$fieldMap['etd']]['value']);
|
$stmt = $conn->prepare($sql);
|
||||||
$etd = $date->format('Y-m-d H:i:s');
|
|
||||||
$pob_out = $json['data'][$fieldMap['pob_out']]['value'];
|
|
||||||
$out_to = $json['data'][$fieldMap['out_to']]['value'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$email = $json['data'][$fieldMap['email']]['value'];
|
// Bind parameters dynamically
|
||||||
$phone = $json['data'][$fieldMap['phone']]['value'];
|
$stmt->bind_param($types, ...$values);
|
||||||
$notes = $json['data'][$fieldMap['notes']]['value'];
|
|
||||||
|
|
||||||
mysqli_stmt_bind_param($stmt, "ssssssisissss", $ac_reg, $ac_type, $captain, $fuel, $in_from, $eta, $pob_in, $etd, $pob_out, $email, $phone, $notes, $created_by);
|
|
||||||
|
|
||||||
// Execute the statement
|
// Execute the statement
|
||||||
if (mysqli_stmt_execute($stmt)) {
|
if ($stmt->execute()) {
|
||||||
error_log("Record inserted for " . $ac_reg);
|
error_log("New record created successfully");
|
||||||
|
$lastId = $stmt->insert_id;
|
||||||
|
if (!empty($email)) {
|
||||||
|
generatePprEmail($lastId, $email, $ac_reg);
|
||||||
|
} else {
|
||||||
|
error_log("Email is not set.");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error_log("Error: " . mysqli_stmt_error($stmt));
|
error_log("Error: " . $stmt->error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the statement and connection
|
// Close the connection
|
||||||
mysqli_stmt_close($stmt);
|
$stmt->close();
|
||||||
mysqli_close($mysqli);
|
$conn->close();
|
||||||
?>
|
?>
|
||||||
84
webhook_old.php
Normal file
84
webhook_old.php
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Basic connection settings
|
||||||
|
$databaseHost = 'sasaprod.pattinson.org';
|
||||||
|
$databaseUsername = 'root';
|
||||||
|
$databasePassword = 'PugPictureMousePen';
|
||||||
|
$databaseName = 'pprdevdb';
|
||||||
|
$created_by = "webhook-dev";
|
||||||
|
|
||||||
|
//ini_set("error_log", "ppr.log");
|
||||||
|
error_log("Webhook handler called");
|
||||||
|
|
||||||
|
// Connect to the database
|
||||||
|
$mysqli = mysqli_connect($databaseHost, $databaseUsername, $databasePassword, $databaseName);
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
#if($json = json_decode(file_get_contents("php://input"), true)) {
|
||||||
|
if($json = json_decode(file_get_contents("testhook.json"), true)) {
|
||||||
|
|
||||||
|
$data = $json;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
print_r($data);
|
||||||
|
|
||||||
|
$fieldMap = array();
|
||||||
|
$fieldMap['ac_reg'] = '617dd0cd-2d17-4d7f-826b-5348afdb30b3';
|
||||||
|
$fieldMap['ac_type'] = '148a55d8-5357-49a3-b9aa-2a5d4dc64173';
|
||||||
|
$fieldMap['ac_call'] = '52d7bc90-9d26-48a1-82db-b91b4ccd2f92';
|
||||||
|
$fieldMap['captain'] = '49b2de0d-5bd6-4b0c-86dd-b18b85f8b8ff';
|
||||||
|
$fieldMap['fuel'] = 'd153c8a5-8345-4e6a-abfd-cf8adcc06f2d';
|
||||||
|
$fieldMap['in_from'] = '4b4f7ecd-f80c-4e86-a7ab-6fadb3220df8';
|
||||||
|
$fieldMap['eta'] = 'ca4ac44f-0388-4a70-a072-38276ed2ac13';
|
||||||
|
$fieldMap['pob_in'] = '6fc47c54-7383-48fd-93fc-d8080f5ed8f5';
|
||||||
|
$fieldMap['out_to'] = 'ba95fd3f-1ec0-4553-95d3-a0b6a850738d';
|
||||||
|
$fieldMap['etd'] = '53d60abd-eb75-4b1f-92b6-5d47d26367ec';
|
||||||
|
$fieldMap['pob_out'] = 'd1ac0860-31f4-4914-9d0b-cae42dfc7eda';
|
||||||
|
$fieldMap['email'] = '0198c86c-edd1-4aaf-93a1-d68f8fc8c365';
|
||||||
|
$fieldMap['phone'] = 'e40ebc2d-887b-42b3-931d-c981c76b0c20';
|
||||||
|
$fieldMap['notes'] = '73d26c2c-1d3d-44e2-82fc-3a1a2600c393';
|
||||||
|
|
||||||
|
#print_r($json['data'][$fieldMap['eta']]['value']);
|
||||||
|
|
||||||
|
$stmt = mysqli_prepare($mysqli, "INSERT INTO submitted (ac_reg, ac_type, captain, fuel, in_from, eta, pob_in, etd, pob_out, email, phone, notes, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
|
|
||||||
|
// Check if the statement was prepared correctly
|
||||||
|
if ($stmt === false) {
|
||||||
|
die('MySQL prepare error: ' . mysqli_error($conn));
|
||||||
|
}
|
||||||
|
|
||||||
|
$ac_reg = $json['data'][$fieldMap['ac_reg']]['value'];
|
||||||
|
$ac_type = $json['data'][$fieldMap['ac_type']]['value'];
|
||||||
|
$captain = $json['data'][$fieldMap['captain']]['value'];
|
||||||
|
$in_from = $json['data'][$fieldMap['in_from']]['value'];
|
||||||
|
$fuel = $json['data'][$fieldMap['fuel']]['value'];
|
||||||
|
$date = DateTime::createFromFormat('d/m/Y H:i', $json['data'][$fieldMap['eta']]['value']);
|
||||||
|
$eta = $date->format('Y-m-d H:i:s');
|
||||||
|
$pob_in = $json['data'][$fieldMap['pob_in']]['value'];
|
||||||
|
|
||||||
|
if (array_key_exists($fieldMap['out_to'], $json['data'])) {
|
||||||
|
$date = DateTime::createFromFormat('d/m/Y H:i', $json['data'][$fieldMap['etd']]['value']);
|
||||||
|
$etd = $date->format('Y-m-d H:i:s');
|
||||||
|
$pob_out = $json['data'][$fieldMap['pob_out']]['value'];
|
||||||
|
$out_to = $json['data'][$fieldMap['out_to']]['value'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$email = $json['data'][$fieldMap['email']]['value'];
|
||||||
|
$phone = $json['data'][$fieldMap['phone']]['value'];
|
||||||
|
$notes = $json['data'][$fieldMap['notes']]['value'];
|
||||||
|
|
||||||
|
mysqli_stmt_bind_param($stmt, "ssssssisissss", $ac_reg, $ac_type, $captain, $fuel, $in_from, $eta, $pob_in, $etd, $pob_out, $email, $phone, $notes, $created_by);
|
||||||
|
|
||||||
|
// Execute the statement
|
||||||
|
if (mysqli_stmt_execute($stmt)) {
|
||||||
|
error_log("Record inserted for " . $ac_reg);
|
||||||
|
} else {
|
||||||
|
error_log("Error: " . mysqli_stmt_error($stmt));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the statement and connection
|
||||||
|
mysqli_stmt_close($stmt);
|
||||||
|
mysqli_close($mysqli);
|
||||||
|
?>
|
||||||
Reference in New Issue
Block a user