feat(phase1): complete base structure - landing page, auth, dashboard, airports, API, DB schema, 60 airports CSV

This commit is contained in:
2026-04-24 15:53:59 +02:00
parent 2960bd4c2f
commit ab5f97acbf
18 changed files with 4926 additions and 0 deletions

207
www/public/register.php Normal file
View File

@@ -0,0 +1,207 @@
<?php
/**
* Airline Tycoon - Registration Page
*/
require_once dirname(__DIR__) . '/src/bootstrap.php';
$error = '';
// Registration verarbeiten
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
$password_confirm = $_POST['password_confirm'] ?? '';
$airline_name = trim($_POST['airline_name'] ?? '');
if (!validate_csrf($_POST['csrf_token'] ?? '')) {
$error = 'Ungültige Anfrage. Bitte versuche es erneut.';
} elseif (empty($username) || empty($email) || empty($password)) {
$error = 'Bitte fülle alle Pflichtfelder aus.';
} elseif (strlen($username) < 3 || strlen($username) > 50) {
$error = 'Der Benutzername muss zwischen 3 und 50 Zeichen haben.';
} elseif (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
$error = 'Der Benutzername darf nur Buchstaben, Zahlen und Unterstriche enthalten.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$error = 'Bitte gib eine gültige E-Mail-Adresse ein.';
} elseif (strlen($password) < 8) {
$error = 'Das Passwort muss mindestens 8 Zeichen haben.';
} elseif ($password !== $password_confirm) {
$error = 'Die Passwörter stimmen nicht überein.';
} else {
// Prüfen ob Benutzer bereits existiert
if ($db->getUserByUsername($username)) {
$error = 'Dieser Benutzername ist bereits vergeben.';
} elseif ($db->getUserByEmail($email)) {
$error = 'Diese E-Mail-Adresse wird bereits verwendet.';
} else {
// Benutzer erstellen
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
$userId = $db->createUser($username, $email, $passwordHash);
// Airline Name setzen falls angegeben
if (!empty($airline_name)) {
$db->update('users', ['airline_name' => $airline_name], 'id = ?', [$userId]);
} else {
$db->update('users', ['airline_name' => $username . "'s Airlines"], 'id = ?', [$userId]);
}
// Airports aus CSV laden falls noch nicht vorhanden
$airportCount = $db->select("SELECT COUNT(*) as cnt FROM airports")[0]['cnt'] ?? 0;
if ($airportCount == 0) {
$db->loadAirportsFromCsv($config['paths']['data'] . '/airports.csv');
}
Session::success('Registrierung erfolgreich! Du kannst dich jetzt anmelden.');
redirect('/login.php');
}
}
}
// Redirect wenn bereits eingeloggt
if (Session::isLoggedIn()) {
redirect('/dashboard.php');
}
?>
<!DOCTYPE html>
<html lang="de" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registrieren - Airline Tycoon</title>
<meta name="csrf-token" content="<?= h(csrf_token()) ?>">
<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 ?>" class="navbar-brand">✈️ Airline Tycoon</a>
<ul class="navbar-menu">
<li><a href="<?= BASE_PATH ?>" class="navbar-item">Zurück zur Startseite</a></li>
</ul>
</div>
</nav>
<main class="container p-lg">
<div class="panel" style="max-width: 500px; margin: 0 auto;">
<h1 class="text-center mb-lg">📝 Registrieren</h1>
<?php if ($error): ?>
<div class="card mb-md" style="background: rgba(255, 107, 107, 0.2); border-color: var(--comic-red);">
<p class="text-danger">❌ <?= h($error) ?></p>
</div>
<?php endif; ?>
<form method="POST" action="<?= BASE_PATH ?>register.php" data-ajax>
<input type="hidden" name="csrf_token" value="<?= h(csrf_token()) ?>">
<div class="form-group">
<label class="form-label" for="username">Benutzername *</label>
<input
type="text"
id="username"
name="username"
class="form-input"
placeholder="Dein Benutzername"
required
minlength="3"
maxlength="50"
pattern="[a-zA-Z0-9_]+"
autocomplete="username"
value="<?= h($_POST['username'] ?? '') ?>"
>
<p class="form-help">3-50 Zeichen, nur Buchstaben, Zahlen und Unterstriche</p>
</div>
<div class="form-group">
<label class="form-label" for="email">E-Mail *</label>
<input
type="email"
id="email"
name="email"
class="form-input"
placeholder="deine@email.de"
required
autocomplete="email"
value="<?= h($_POST['email'] ?? '') ?>"
>
</div>
<div class="form-group">
<label class="form-label" for="airline_name">Airline-Name</label>
<input
type="text"
id="airline_name"
name="airline_name"
class="form-input"
placeholder="z.B. German Wings Express"
maxlength="100"
value="<?= h($_POST['airline_name'] ?? '') ?>"
>
<p class="form-help">Leer lassen für Standard-Name</p>
</div>
<div class="form-group">
<label class="form-label" for="password">Passwort *</label>
<input
type="password"
id="password"
name="password"
class="form-input"
placeholder="Mindestens 8 Zeichen"
required
minlength="8"
autocomplete="new-password"
>
</div>
<div class="form-group">
<label class="form-label" for="password_confirm">Passwort bestätigen *</label>
<input
type="password"
id="password_confirm"
name="password_confirm"
class="form-input"
placeholder="Passwort wiederholen"
required
autocomplete="new-password"
>
</div>
<div class="form-group">
<label class="d-flex flex-center gap-sm">
<input type="checkbox" name="terms" id="terms" required>
<span>Ich akzeptiere die <a href="#" target="_blank">Nutzungsbedingungen</a></span>
</label>
</div>
<button type="submit" class="btn btn-primary btn-block btn-lg">
✈️ Kostenlos registrieren
</button>
</form>
<div class="text-center mt-lg">
<p>Bereits ein Konto?</p>
<a href="<?= BASE_PATH ?>login.php" class="btn btn-secondary">
Jetzt anmelden
</a>
</div>
<!-- Comic Feature Box -->
<div class="comic-bubble mt-lg">
<p class="text-center">
🎁 <strong>Willkommensbonus:</strong> Starte mit 500.000 € und einem Dash 8-100 Flugzeug!
</p>
</div>
</div>
</main>
<!-- Toast Container -->
<div id="toastContainer" class="toast-container"></div>
<script src="<?= BASE_PATH ?>assets/js/main.js"></script>
</body>
</html>