374 lines
18 KiB
PHP
374 lines
18 KiB
PHP
<?php
|
||
/**
|
||
* Airline Tycoon - Airports & World Map
|
||
* Interaktive Weltkarte mit Touch-Support
|
||
*/
|
||
|
||
require_once dirname(__DIR__) . '/src/bootstrap.php';
|
||
requireLogin();
|
||
|
||
$userId = Session::getUserId();
|
||
$user = $db->getUserById($userId);
|
||
|
||
if (!$user) {
|
||
Session::logout();
|
||
redirect('/login.php');
|
||
}
|
||
|
||
Session::refreshUserData($db);
|
||
$user = $db->getUserById($userId);
|
||
|
||
// Airports laden falls noch nicht in DB
|
||
$airports = $db->getAllAirports();
|
||
if (empty($airports)) {
|
||
$db->loadAirportsFromCsv($config['paths']['data'] . '/airports.csv');
|
||
$airports = $db->getAllAirports();
|
||
}
|
||
|
||
$aircraft = $db->getUserAircraft($userId);
|
||
$routes = $db->getUserRoutes($userId);
|
||
|
||
// Route erstellen
|
||
$message = '';
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'create_route') {
|
||
if (!validate_csrf($_POST['csrf_token'] ?? '')) {
|
||
$message = 'Ungültige Anfrage.';
|
||
} else {
|
||
$fromId = (int) ($_POST['from_airport'] ?? 0);
|
||
$toId = (int) ($_POST['to_airport'] ?? 0);
|
||
|
||
if ($fromId > 0 && $toId > 0 && $fromId !== $toId) {
|
||
$fromAirport = $db->selectOne("SELECT * FROM airports WHERE id = ?", [$fromId]);
|
||
$toAirport = $db->selectOne("SELECT * FROM airports WHERE id = ?", [$toId]);
|
||
|
||
if ($fromAirport && $toAirport) {
|
||
$distance = $db->calculateDistance(
|
||
$fromAirport['latitude'], $fromAirport['longitude'],
|
||
$toAirport['latitude'], $toAirport['longitude']
|
||
);
|
||
|
||
// Prüfen ob Route bereits existiert
|
||
$existing = $db->selectOne(
|
||
"SELECT id FROM routes WHERE user_id = ? AND from_airport_id = ? AND to_airport_id = ?",
|
||
[$userId, $fromId, $toId]
|
||
);
|
||
|
||
if ($existing) {
|
||
$message = 'Diese Route existiert bereits!';
|
||
} else {
|
||
$db->createRoute($userId, $fromId, $toId, $distance);
|
||
$message = 'Route erfolgreich erstellt!';
|
||
}
|
||
}
|
||
} else {
|
||
$message = 'Bitte wähle zwei verschiedene Flughäfen.';
|
||
}
|
||
}
|
||
}
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="de" data-theme="light">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<meta name="description" content="Airline Tycoon Weltkarte - Alle Flughäfen">
|
||
<meta name="csrf-token" content="<?= h(csrf_token()) ?>">
|
||
<title>Weltkarte - Airline Tycoon</title>
|
||
<link rel="stylesheet" href="<?= BASE_PATH ?>assets/css/style.css">
|
||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>✈️</text></svg>">
|
||
</head>
|
||
<body>
|
||
<!-- Navigation -->
|
||
<nav class="navbar">
|
||
<div class="navbar-container">
|
||
<a href="<?= BASE_PATH ?>dashboard.php" class="navbar-brand">✈️ <?= h($user['airline_name']) ?></a>
|
||
<button class="navbar-toggle" aria-label="Menü">☰</button>
|
||
<ul class="navbar-menu">
|
||
<li><a href="<?= BASE_PATH ?>dashboard.php" class="navbar-item">📊 Dashboard</a></li>
|
||
<li><a href="<?= BASE_PATH ?>airports.php" class="navbar-item active">🌍 Weltkarte</a></li>
|
||
<li><a href="<?= BASE_PATH ?>airports.php?action=fleet" class="navbar-item">✈️ Flotte</a></li>
|
||
<li><a href="<?= BASE_PATH ?>airports.php?action=routes" class="navbar-item">🛫 Routen</a></li>
|
||
<li>
|
||
<span class="navbar-item">
|
||
💰 <?= formatMoney($user['balance']) ?>
|
||
</span>
|
||
</li>
|
||
<li>
|
||
<button class="theme-toggle" id="themeToggle" aria-label="Design wechseln">🌙</button>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</nav>
|
||
|
||
<main class="container p-lg">
|
||
<?php if ($message): ?>
|
||
<div class="panel mb-lg" style="background: rgba(78, 205, 196, 0.2); border-color: var(--comic-blue);">
|
||
<p>ℹ️ <?= h($message) ?></p>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<!-- Tabs -->
|
||
<div class="d-flex gap-sm mb-lg">
|
||
<a href="<?= BASE_PATH ?>airports.php" class="btn <?= !isset($_GET['action']) ? 'btn-primary' : 'btn-outline' ?>">
|
||
🗺️ Weltkarte
|
||
</a>
|
||
<a href="<?= BASE_PATH ?>airports.php?action=fleet" class="btn <?= ($_GET['action'] ?? '') === 'fleet' ? 'btn-primary' : 'btn-outline' ?>">
|
||
✈️ Flotte
|
||
</a>
|
||
<a href="<?= BASE_PATH ?>airports.php?action=routes" class="btn <?= ($_GET['action'] ?? '') === 'routes' ? 'btn-primary' : 'btn-outline' ?>">
|
||
🛫 Routen
|
||
</a>
|
||
</div>
|
||
|
||
<?php if (!isset($_GET['action']) || $_GET['action'] === 'map'): ?>
|
||
<!-- Weltkarte -->
|
||
<div class="panel">
|
||
<h2 class="panel-header">🗺️ Interaktive Weltkarte</h2>
|
||
<p class="text-secondary mb-md">
|
||
Klicke oder tippe auf einen Flughafen um eine Route zu erstellen.
|
||
</p>
|
||
|
||
<div class="d-flex gap-lg">
|
||
<!-- Karte -->
|
||
<div id="mapContainer" style="flex: 2; min-height: 500px; position: relative;">
|
||
<!-- Map wird per JS initialisiert -->
|
||
</div>
|
||
|
||
<!-- Flughafen Info -->
|
||
<div id="airportInfo" class="card" style="flex: 1; min-width: 250px; display: none;">
|
||
<h3>Flughafen-Info</h3>
|
||
<p class="text-muted">Wähle einen Flughafen auf der Karte</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Routen erstellen Panel -->
|
||
<div class="panel mt-lg">
|
||
<h2 class="panel-header">🛫 Neue Route erstellen</h2>
|
||
|
||
<form method="POST" class="d-flex flex-wrap gap-md mt-md">
|
||
<input type="hidden" name="csrf_token" value="<?= h(csrf_token()) ?>">
|
||
<input type="hidden" name="action" value="create_route">
|
||
|
||
<div class="form-group" style="flex: 1; min-width: 200px;">
|
||
<label class="form-label" for="fromAirport">Von</label>
|
||
<select id="fromAirport" name="from_airport" class="form-select" required>
|
||
<option value="">Flughafen wählen...</option>
|
||
<?php foreach ($airports as $airport): ?>
|
||
<option value="<?= $airport['id'] ?>">
|
||
<?= h($airport['iata_code']) ?> - <?= h($airport['city']) ?>, <?= h($airport['country']) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="d-flex flex-center" style="padding-top: 24px;">
|
||
<span style="font-size: 2rem;">→</span>
|
||
</div>
|
||
|
||
<div class="form-group" style="flex: 1; min-width: 200px;">
|
||
<label class="form-label" for="toAirport">Nach</label>
|
||
<select id="toAirport" name="to_airport" class="form-select" required>
|
||
<option value="">Flughafen wählen...</option>
|
||
<?php foreach ($airports as $airport): ?>
|
||
<option value="<?= $airport['id'] ?>">
|
||
<?= h($airport['iata_code']) ?> - <?= h($airport['city']) ?>, <?= h($airport['country']) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="d-flex flex-center" style="padding-top: 24px;">
|
||
<button type="submit" class="btn btn-primary">
|
||
✈️ Route erstellen
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- Alle Flughäfen Liste -->
|
||
<div class="panel mt-lg">
|
||
<h2 class="panel-header">📋 Alle Flughäfen (<?= count($airports) ?>)</h2>
|
||
|
||
<div class="table-container">
|
||
<table class="table">
|
||
<thead>
|
||
<tr>
|
||
<th>IATA</th>
|
||
<th>Name</th>
|
||
<th>Stadt</th>
|
||
<th>Land</th>
|
||
<th>Kontinent</th>
|
||
<th>Passagiere/Jahr</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($airports as $airport): ?>
|
||
<tr onclick="selectAirportFromList(<?= $airport['id'] ?>)" style="cursor: pointer;">
|
||
<td><strong><?= h($airport['iata_code']) ?></strong></td>
|
||
<td><?= h($airport['name']) ?></td>
|
||
<td><?= h($airport['city']) ?></td>
|
||
<td><?= h($airport['country']) ?></td>
|
||
<td><?= h($airport['continent']) ?></td>
|
||
<td><?= formatNumber($airport['passenger_volume']) ?></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<?php elseif ($_GET['action'] === 'fleet'): ?>
|
||
<!-- Flottenverwaltung -->
|
||
<div class="panel">
|
||
<h2 class="panel-header">✈️ Meine Flotte</h2>
|
||
|
||
<?php if (empty($aircraft)): ?>
|
||
<div class="card text-center p-lg">
|
||
<p class="text-muted">Du hast noch keine Flugzeuge.</p>
|
||
<a href="<?= BASE_PATH ?>dashboard.php" class="btn btn-primary mt-md">
|
||
🛒 Flugzeug kaufen
|
||
</a>
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="d-grid" style="grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--space-md);">
|
||
<?php foreach ($aircraft as $plane): ?>
|
||
<div class="card">
|
||
<div class="d-flex gap-md">
|
||
<div class="card-icon">✈️</div>
|
||
<div>
|
||
<h3><?= h($plane['name']) ?></h3>
|
||
<p class="text-secondary"><?= h($plane['aircraft_type']) ?></p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="d-grid mt-md" style="grid-template-columns: 1fr 1fr; gap: var(--space-sm);">
|
||
<div>
|
||
<strong>Sitze:</strong> <?= $plane['seat_capacity'] ?>
|
||
</div>
|
||
<div>
|
||
<strong>Reichweite:</strong> <?= formatNumber($plane['range_km']) ?> km
|
||
</div>
|
||
<div>
|
||
<strong>Zustand:</strong>
|
||
<span class="badge <?= $plane['condition'] > 70 ? 'badge-success' : ($plane['condition'] > 30 ? 'badge-warning' : 'badge-danger') ?>">
|
||
<?= number_format($plane['condition'], 1, ',', '.') ?>%
|
||
</span>
|
||
</div>
|
||
<div>
|
||
<strong>Flüge:</strong> <?= formatNumber($plane['flights_count']) ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<?php elseif ($_GET['action'] === 'routes'): ?>
|
||
<!-- Routenverwaltung -->
|
||
<div class="panel">
|
||
<h2 class="panel-header">🛫 Meine Routen</h2>
|
||
|
||
<?php if (empty($routes)): ?>
|
||
<div class="card text-center p-lg">
|
||
<p class="text-muted">Du hast noch keine Routen.</p>
|
||
<a href="<?= BASE_PATH ?>airports.php" class="btn btn-primary mt-md">
|
||
🗺️ Route erstellen
|
||
</a>
|
||
</div>
|
||
<?php else: ?>
|
||
<div class="d-grid" style="grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--space-md);">
|
||
<?php foreach ($routes as $route): ?>
|
||
<div class="card">
|
||
<div class="d-flex flex-center gap-md">
|
||
<div class="text-center">
|
||
<strong><?= h($route['from_iata']) ?></strong><br>
|
||
<small><?= h($route['from_city']) ?></small>
|
||
</div>
|
||
<div style="font-size: 1.5rem;">✈️</div>
|
||
<div class="text-center">
|
||
<strong><?= h($route['to_iata']) ?></strong><br>
|
||
<small><?= h($route['to_city']) ?></small>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="d-flex flex-between mt-md">
|
||
<span>Distanz:</span>
|
||
<strong><?= formatNumber($route['distance_km']) ?> km</strong>
|
||
</div>
|
||
<div class="d-flex flex-between">
|
||
<span>Nachfrage:</span>
|
||
<div class="progress" style="width: 100px; height: 16px;">
|
||
<div class="progress-bar" style="width: <?= $route['demand_level'] ?>%">
|
||
<?= $route['demand_level'] ?>%
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</main>
|
||
|
||
<!-- Toast Container -->
|
||
<div id="toastContainer" class="toast-container"></div>
|
||
|
||
<script>
|
||
const AIRPORTS_DATA = <?= json_encode($airports) ?>;
|
||
const ROUTES_DATA = <?= json_encode($routes) ?>;
|
||
const AIRCRAFT_DATA = <?= json_encode($aircraft) ?>;
|
||
</script>
|
||
<script src="<?= BASE_PATH ?>assets/js/main.js"></script>
|
||
<script>
|
||
// Airport aus Liste auswählen
|
||
function selectAirportFromList(airportId) {
|
||
const airport = AIRPORTS_DATA.find(a => a.id == airportId);
|
||
if (airport && typeof selectAirport === 'function') {
|
||
selectAirport(airport);
|
||
// Scroll zur Karte
|
||
document.querySelector('#mapContainer')?.scrollIntoView({ behavior: 'smooth' });
|
||
}
|
||
}
|
||
|
||
// Event Listener für Airport-Auswahl
|
||
document.addEventListener('airportSelected', function(e) {
|
||
const airport = e.detail;
|
||
const infoPanel = document.getElementById('airportInfo');
|
||
|
||
if (infoPanel && airport) {
|
||
infoPanel.style.display = 'block';
|
||
infoPanel.innerHTML = `
|
||
<h3>✈️ ${airport.iata_code}</h3>
|
||
<p><strong>${airport.name}</strong></p>
|
||
<p>${airport.city}, ${airport.country}</p>
|
||
<hr>
|
||
<p><strong>Kontinent:</strong> ${airport.continent}</p>
|
||
<p><strong>Passagiere:</strong> ${formatNumber(airport.passenger_volume)}/Jahr</p>
|
||
<p><strong>Nachfrage:</strong> ${(airport.demand_multiplier * 100).toFixed(0)}%</p>
|
||
|
||
<div class="mt-md">
|
||
<p><strong>Von hier:</strong></p>
|
||
<select class="form-select" onchange="setFromAirport(${airport.id}, this.value)">
|
||
<option value="">Route von ${airport.iata_code} nach...</option>
|
||
${AIRPORTS_DATA.filter(a => a.id != airport.id).map(a =>
|
||
`<option value="${a.id}">${a.iata_code} - ${a.city}</option>`
|
||
).join('')}
|
||
</select>
|
||
</div>
|
||
`;
|
||
}
|
||
});
|
||
|
||
function setFromAirport(fromId, toId) {
|
||
if (toId) {
|
||
document.querySelector('select[name="from_airport"]').value = fromId;
|
||
document.querySelector('select[name="to_airport"]').value = toId;
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|