Files
game1.shadow-land.de/www/public/aircraft.php
madgerm 12ddf5a185 feat(phase2): aircraft market, fleet management, finances, loans
- market.php: Buy new aircraft (6 types: Dash8 to A380)
- aircraft.php: Fleet management, crew assignment, route planning
- finances.php: Account balance, transactions, loans
- Database.php: Extended with loan/transaction/aircraft methods
- schema.sql: Aircraft types table, 10M starting balance, INSERT OR IGNORE
- dashboard.php: Updated with fleet/financial overview
- Fixed: duplicate function declarations in Database.php
- Fixed: initializeSchema() with idempotent error handling
2026-04-24 17:27:02 +02:00

372 lines
18 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Airline Tycoon - Flotten-Übersicht
* Zeigt alle Flugzeuge des Spielers mit Zustand und Wartungsstatus
*/
require_once __DIR__ . '/../src/bootstrap.php';
// Auth Check
if (!Session::isLoggedIn()) {
header('Location: login.php');
exit;
}
$userId = Session::getUserId();
$user = $db->getUserById($userId);
$aircraft = $db->getUserAircraft($userId);
$config = $db->getConfig();
// Wartungsstatus prüfen
$maintenanceDue = $db->checkMaintenanceDue($userId);
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flotte - <?= htmlspecialchars($user['airline_name']) ?> - <?= $config['app']['name'] ?></title>
<link rel="stylesheet" href="<?= $basePath ?>assets/css/style.css">
<link href="https://fonts.googleapis.com/css2?family=Bangers&family=Patrick+Hand&family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
</head>
<body data-theme="<?= $theme ?? 'light' ?>">
<!-- Navbar -->
<nav class="navbar">
<div class="navbar-brand">
<a href="<?= $basePath ?>dashboard.php" class="navbar-logo">✈️ <?= $config['app']['name'] ?></a>
</div>
<button class="navbar-toggle" aria-label="Menü">☰</button>
<div class="navbar-menu">
<a href="<?= $basePath ?>dashboard.php" class="navbar-item">Dashboard</a>
<a href="<?= $basePath ?>airports.php" class="navbar-item">Flughäfen</a>
<a href="<?= $basePath ?>aircraft.php" class="navbar-item active">Flotte</a>
<a href="<?= $basePath ?>finances.php" class="navbar-item">Finanzen</a>
<a href="<?= $basePath ?>market.php" class="navbar-item">Markt</a>
<button class="theme-toggle" id="themeToggle" title="Theme wechseln">🌙</button>
</div>
</nav>
<!-- Main Content -->
<main class="container">
<!-- Header -->
<section class="hero hero-sm">
<div class="hero-content">
<h1 class="hero-title">🛫 Deine Flotte</h1>
<p class="hero-subtitle">Verwalte deine Flugzeuge, prüfe den Zustand und buche Wartungen</p>
</div>
</section>
<!-- Wartungshinweis -->
<?php if (!empty($maintenanceDue)): ?>
<div class="alert alert-warning mb-lg">
<div class="alert-icon">⚠️</div>
<div class="alert-content">
<strong>Wartung fällig!</strong>
<p>Bei <?= count($maintenanceDue) ?> Flugzeug(en) ist die Wartung überfällig.</p>
</div>
</div>
<?php endif; ?>
<!-- Statistik-Grid -->
<div class="stats-grid mt-lg">
<div class="stat-card">
<div class="stat-icon">✈️</div>
<div class="stat-value"><?= count($aircraft) ?></div>
<div class="stat-label">Flugzeuge</div>
</div>
<div class="stat-card">
<div class="stat-icon">💺</div>
<div class="stat-value"><?= number_format(array_sum(array_column($aircraft, 'seat_capacity')), 0, ',', '.') ?></div>
<div class="stat-label">Gesamtkapazität</div>
</div>
<div class="stat-card">
<div class="stat-icon">🛡️</div>
<div class="stat-value"><?= count($maintenanceDue) ?></div>
<div class="stat-label">Wartung fällig</div>
</div>
<div class="stat-card">
<div class="stat-icon">📅</div>
<div class="stat-value"><?= $config['game']['maintenance_interval'] ?></div>
<div class="stat-label">Flüge bis Wartung</div>
</div>
</div>
<!-- Flugzeugliste -->
<section class="panel mt-xl">
<div class="panel-header">
<h2 class="panel-title">🛩️ Alle Flugzeuge</h2>
<a href="<?= $basePath ?>market.php" class="btn btn-primary">
Flugzeug kaufen
</a>
</div>
<?php if (empty($aircraft)): ?>
<div class="empty-state">
<div class="empty-icon">✈️</div>
<h3>Keine Flugzeuge vorhanden</h3>
<p>Du besitzt noch keine Flugzeuge. Kaufe dein erstes Flugzeug im Markt!</p>
<a href="<?= $basePath ?>market.php" class="btn btn-primary btn-lg mt-md">Zum Markt</a>
</div>
<?php else: ?>
<div class="table-container">
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Typ</th>
<th>Zustand</th>
<th>Flüge</th>
<th>Nächste Wartung</th>
<th>Reichweite</th>
<th>Kapazität</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody>
<?php foreach ($aircraft as $plane): ?>
<?php
$conditionClass = $plane['condition'] >= 80 ? 'text-success' : ($plane['condition'] >= 50 ? 'text-warning' : 'text-danger');
$maintenanceProgress = min(100, ($plane['flights_count'] / $config['game']['maintenance_interval']) * 100);
$needsMaintenance = $plane['flights_count'] >= $config['game']['maintenance_interval'];
?>
<tr>
<td>
<strong><?= htmlspecialchars($plane['name']) ?></strong>
</td>
<td>
<span class="badge"><?= htmlspecialchars($plane['aircraft_type']) ?></span>
</td>
<td>
<div class="d-flex flex-col align-start gap-sm">
<span class="<?= $conditionClass ?>">
<?= number_format($plane['condition'], 1, ',', '.') ?>%
</span>
<div class="progress" style="width: 80px;">
<div class="progress-bar" style="width: <?= $plane['condition'] ?>%"></div>
</div>
</div>
</td>
<td><?= number_format($plane['flights_count'], 0, ',', '.') ?></td>
<td>
<?php if ($needsMaintenance): ?>
<span class="badge badge-danger">⚠️ Jetzt!</span>
<?php else: ?>
<span class="text-secondary">
<?= number_format($config['game']['maintenance_interval'] - $plane['flights_count'], 0, ',', '.') ?> Flüge
</span>
<?php endif; ?>
</td>
<td><?= number_format($plane['range_km'], 0, ',', '.') ?> km</td>
<td><?= number_format($plane['seat_capacity'], 0, ',', '.') ?> Pax</td>
<td>
<div class="d-flex gap-sm">
<?php if ($needsMaintenance): ?>
<button class="btn btn-sm btn-warning"
onclick="performMaintenance(<?= $plane['id'] ?>)"
data-modal="maintenanceModal">
🔧 Wartung
</button>
<?php endif; ?>
<button class="btn btn-sm btn-secondary"
onclick="showAircraftDetails(<?= $plane['id'] ?>)">
📋 Details
</button>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</section>
<!-- Flugzeug-Typen Übersicht -->
<section class="panel mt-xl">
<h2 class="panel-title">📊 Flugzeugtypen</h2>
<div class="aircraft-types-grid mt-md">
<?php foreach ($config['aircraft_types'] as $type => $specs): ?>
<div class="aircraft-type-card">
<h3 class="aircraft-type-name"><?= htmlspecialchars($type) ?></h3>
<div class="aircraft-type-stats">
<div class="aircraft-type-stat">
<span class="stat-label">Preis:</span>
<span class="stat-value"><?= number_format($specs['purchase_price'], 0, ',', '.') ?> €</span>
</div>
<div class="aircraft-type-stat">
<span class="stat-label">Reichweite:</span>
<span class="stat-value"><?= number_format($specs['range_km'], 0, ',', '.') ?> km</span>
</div>
<div class="aircraft-type-stat">
<span class="stat-label">Kapazität:</span>
<span class="stat-value"><?= $specs['seat_capacity'] ?> Pax</span>
</div>
<div class="aircraft-type-stat">
<span class="stat-label">Crew-Kosten:</span>
<span class="stat-value"><?= $specs['crew_cost_per_tick'] ?? 500 ?> €/Tick</span>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</section>
</main>
<!-- Wartungs-Modal -->
<div class="modal-overlay" id="maintenanceModal">
<div class="modal">
<div class="modal-header">
<h3 class="modal-title">🔧 Wartung durchführen</h3>
<button class="modal-close" onclick="closeModal('maintenanceModal')">×</button>
</div>
<div class="modal-body">
<div id="maintenanceInfo">
<p>Flugzeug: <strong id="maintenanceAircraftName"></strong></p>
<p>Zustand: <span id="maintenanceCondition"></span></p>
<p>Geschätzte Kosten: <strong id="maintenanceCost"></strong></p>
</div>
<div class="alert alert-info mt-md">
<p>Nach der Wartung wird der Zustand auf 100% zurückgesetzt und der Flugzähler zurückgesetzt.</p>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" onclick="closeModal('maintenanceModal')">Abbrechen</button>
<button class="btn btn-warning" id="confirmMaintenanceBtn">Wartung durchführen</button>
</div>
</div>
</div>
<!-- Details-Modal -->
<div class="modal-overlay" id="detailsModal">
<div class="modal">
<div class="modal-header">
<h3 class="modal-title">📋 Flugzeug-Details</h3>
<button class="modal-close" onclick="closeModal('detailsModal')">×</button>
</div>
<div class="modal-body" id="aircraftDetails">
<!-- Dynamisch geladen -->
</div>
<div class="modal-footer">
<button class="btn btn-secondary" onclick="closeModal('detailsModal')">Schließen</button>
</div>
</div>
</div>
<!-- Toast Container -->
<div id="toastContainer" class="toast-container"></div>
<script src="<?= $basePath ?>assets/js/main.js"></script>
<script>
let selectedAircraftId = null;
async function performMaintenance(aircraftId) {
selectedAircraftId = aircraftId;
try {
const response = await fetch(`api/game.php?action=aircraft_details&id=${aircraftId}`);
const data = await response.json();
if (data.success) {
document.getElementById('maintenanceAircraftName').textContent = data.aircraft.name;
document.getElementById('maintenanceCondition').textContent = data.aircraft.condition.toFixed(1) + '%';
document.getElementById('maintenanceCost').textContent = formatMoney(data.maintenance_cost);
openModal('maintenanceModal');
}
} catch (error) {
showToast('Fehler beim Laden der Daten', 'error');
}
}
document.getElementById('confirmMaintenanceBtn').addEventListener('click', async () => {
if (!selectedAircraftId) return;
try {
const formData = new FormData();
formData.append('action', 'maintenance');
formData.append('aircraft_id', selectedAircraftId);
const response = await fetch('api/game.php', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
showToast('Wartung erfolgreich durchgeführt!', 'success');
closeModal('maintenanceModal');
setTimeout(() => location.reload(), 1000);
} else {
showToast(data.error || 'Wartung fehlgeschlagen', 'error');
}
} catch (error) {
showToast('Netzwerkfehler', 'error');
}
});
async function showAircraftDetails(aircraftId) {
try {
const response = await fetch(`api/game.php?action=aircraft_details&id=${aircraftId}`);
const data = await response.json();
if (data.success) {
const aircraft = data.aircraft;
const history = data.maintenance_history || [];
let html = `
<div class="aircraft-detail-header">
<h4>${aircraft.name}</h4>
<span class="badge">${aircraft.aircraft_type}</span>
</div>
<div class="aircraft-detail-grid">
<div class="detail-item">
<span class="detail-label">Zustand:</span>
<span class="detail-value ${aircraft.condition >= 80 ? 'text-success' : aircraft.condition >= 50 ? 'text-warning' : 'text-danger'}">
${aircraft.condition.toFixed(1)}%
</span>
</div>
<div class="detail-item">
<span class="detail-label">Flüge gesamt:</span>
<span class="detail-value">${aircraft.flights_count}</span>
</div>
<div class="detail-item">
<span class="detail-label">Reichweite:</span>
<span class="detail-value">${aircraft.range_km.toLocaleString()} km</span>
</div>
<div class="detail-item">
<span class="detail-label">Kapazität:</span>
<span class="detail-value">${aircraft.seat_capacity} Pax</span>
</div>
<div class="detail-item">
<span class="detail-label">Kaufpreis:</span>
<span class="detail-value">${formatMoney(aircraft.purchase_price)}</span>
</div>
<div class="detail-item">
<span class="detail-label">Nächste Wartung in:</span>
<span class="detail-value">${50 - (aircraft.flights_count % 50)} Flügen</span>
</div>
</div>
`;
if (history.length > 0) {
html += `<h4 class="mt-lg">Wartungshistorie</h4><ul class="maintenance-history">`;
history.forEach(h => {
html += `<li>${h.created_at}: ${h.maintenance_type} - ${formatMoney(h.cost)} (${h.condition_before}% → ${h.condition_after}%)</li>`;
});
html += `</ul>`;
}
document.getElementById('aircraftDetails').innerHTML = html;
openModal('detailsModal');
}
} catch (error) {
showToast('Fehler beim Laden der Details', 'error');
}
}
function formatMoney(amount) {
return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(amount);
}
</script>
</body>
</html>