eve-indy-job-tracker/blueprints_dashboard.php

286 lines
9.8 KiB
PHP
Executable file

<?php
require_once __DIR__ . "/session_bootstrap.php";
require_once "functions.php";
// Set a timestamp for when the page was loaded
$page_load_time = time();
// Refresh tokens only when necessary
if (isset($_SESSION["characters"]) && !empty($_SESSION["characters"])) {
// Only refresh tokens once every 5 minutes per user session
$last_token_refresh = $_SESSION['last_token_refresh'] ?? 0;
if ($page_load_time - $last_token_refresh > 300) {
foreach ($_SESSION["characters"] as $character_id => &$charData) {
if (isset($charData["refresh_token"])) {
if (
!isset($charData["access_token"]) ||
is_token_expired($charData["access_token"])
) {
$new_tokens = refresh_token($charData["refresh_token"]);
if (!empty($new_tokens["access_token"])) {
$charData["access_token"] = $new_tokens["access_token"];
} else {
error_log(
"Failed to refresh token for character ID $character_id"
);
}
}
}
}
unset($charData);
$_SESSION['last_token_refresh'] = $page_load_time;
}
}
if (!isset($_SESSION["characters"]) || empty($_SESSION["characters"])) {
echo "No characters logged in. <a href='index.php'>Go back</a>";
exit();
}
// Check if we have a cached blueprint list
$cache_key = "all_character_blueprints";
$cached_data = get_cache_data($cache_key);
if ($cached_data !== null) {
$blueprints = $cached_data;
} else {
// Fetch blueprints for all characters
$blueprints = [];
$blueprint_ids = [];
foreach ($_SESSION["characters"] as $character_id => $charData) {
$access_token = $charData["access_token"] ?? null;
if (!$access_token) {
continue;
}
$character_blueprints = fetch_character_blueprints(
$character_id,
$access_token
);
foreach ($character_blueprints as $bp) {
$key =
$bp["blueprint_type_id"] .
"-" .
$bp["material_efficiency"] .
"-" .
$bp["time_efficiency"] .
"-" .
$bp["runs"];
$blueprints[$key] = $bp;
$blueprint_ids[] = $bp["blueprint_type_id"];
}
}
$blueprint_names = fetch_type_names(array_unique($blueprint_ids));
foreach ($blueprints as &$bp) {
$bp["blueprint_name"] =
$blueprint_names[$bp["blueprint_type_id"]] ?? "Unknown Blueprint";
}
unset($bp);
// Cache the results for 10 minutes
set_cache_data($cache_key, $blueprints, 600);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Blueprints</title>
<style>
th.sorted-asc::after { content: " ▲"; }
th.sorted-desc::after { content: " ▼"; }
#blueprintsTable {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
table-layout: auto;
}
#blueprintsTable th,
#blueprintsTable td {
padding: 10px;
text-align: left;
border-bottom: 1px solid #333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 100px;
}
#blueprintsTable th {
background-color: #2a2a2a;
color: #00ffcc;
cursor: pointer;
position: sticky;
top: 0;
z-index: 1;
}
#blueprintsTable tr:nth-child(even) {
background-color: #1e1e1e;
}
#blueprintsTable tr:hover {
background-color: #2c2c2c;
}
</style>
</head>
<body>
<h1>Blueprints</h1>
<table id="blueprintsTable" class="dashboard-table">
<thead>
<tr>
<th>Blueprint Name</th>
<th>Material Efficiency</th>
<th>Time Efficiency</th>
<th>Number of Runs</th>
<th>Runs Remaining</th>
</tr>
</thead>
<tbody>
<?php foreach ($blueprints as $bp): ?>
<tr>
<td><?php echo htmlspecialchars(
$bp["blueprint_name"]
); ?></td>
<td><?php echo htmlspecialchars(
$bp["material_efficiency"]
); ?>%</td>
<td><?php echo htmlspecialchars(
$bp["time_efficiency"]
); ?>%</td>
<td><?php echo htmlspecialchars(
$bp["runs"] == -1 ? "Original" : $bp["runs"]
); ?></td>
<td><?php echo htmlspecialchars(
$bp["runs"] == -1 ? "∞" : $bp["runs"]
); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<script>
document.addEventListener("DOMContentLoaded", () => {
let sortDirection = [];
document.getElementById('blueprintsTable').querySelector('thead').addEventListener('click', (event) => {
const th = event.target;
if (th.tagName === 'TH') {
const col = Array.from(th.parentNode.children).indexOf(th);
sortTable(col);
}
});
function sortTable(col) {
const table = document.getElementById("blueprintsTable");
const rows = Array.from(table.tBodies[0].rows);
const dir = (sortDirection[col] = !sortDirection[col]);
// Create a document fragment for better performance
const fragment = document.createDocumentFragment();
rows.sort((a, b) => {
const aCell = a.cells[col];
const bCell = b.cells[col];
const aText = aCell.textContent.trim();
const bText = bCell.textContent.trim();
if (!isNaN(aText) && !isNaN(bText)) {
return dir ? bText - aText : aText - bText;
}
return dir ? bText.localeCompare(aText) : aText.localeCompare(bText);
});
// Add rows to fragment
rows.forEach((row) => fragment.appendChild(row));
// Clear and append in a single operation
const tbody = table.tBodies[0];
tbody.innerHTML = '';
tbody.appendChild(fragment);
Array.from(table.querySelectorAll("th")).forEach((th, idx) => {
th.classList.remove("sorted-asc", "sorted-desc");
if (idx === col) {
th.classList.add(dir ? "sorted-desc" : "sorted-asc");
}
});
}
});
</script>
<script>
document.addEventListener("DOMContentLoaded", () => {
let sortDirection = [];
document.getElementById('blueprintsTable').querySelector('thead').addEventListener('click', (event) => {
const th = event.target;
if (th.tagName === 'TH') {
const col = Array.from(th.parentNode.children).indexOf(th);
sortTable(col);
}
});
function sortTable(col) {
const table = document.getElementById("blueprintsTable");
const rows = Array.from(table.tBodies[0].rows);
const dir = (sortDirection[col] = !sortDirection[col]);
rows.sort((a, b) => {
const aCell = a.cells[col];
const bCell = b.cells[col];
const aText = aCell.textContent.trim();
const bText = bCell.textContent.trim();
if (!isNaN(aText) && !isNaN(bText)) {
return dir ? bText - aText : aText - bText;
}
return dir ? bText.localeCompare(aText) : aText.localeCompare(bText);
});
rows.forEach((row) => table.tBodies[0].appendChild(row));
Array.from(table.querySelectorAll("th")).forEach((th, idx) => {
th.classList.remove("sorted-asc", "sorted-desc");
if (idx === col) {
th.classList.add(dir ? "sorted-desc" : "sorted-asc");
}
});
}
// Session keep-alive mechanism
function keepSessionAlive() {
// Add cache-busting parameter to prevent browser caching
fetch("keep_alive.php?t=" + Date.now())
.then(response => response.json())
.then(data => {
if (data.status !== "success") {
console.error("Failed to refresh session:", data.message);
}
})
.catch(error => console.error("Error in keep-alive request:", error));
}
// Call keepSessionAlive only if the user is active
let sessionTimer;
const resetSessionTimer = () => {
clearTimeout(sessionTimer);
sessionTimer = setTimeout(keepSessionAlive, 300000); // 5 minutes
};
// Reset timer on user activity
['mousemove', 'keydown', 'click', 'scroll'].forEach(event => {
document.addEventListener(event, resetSessionTimer, false);
});
// Initial setup
resetSessionTimer();
});
</script>
</body>
</html>