352 lines
16 KiB
PHP
352 lines
16 KiB
PHP
<?php
|
|
// =====================================================================
|
|
// WebGIS Citizen Participation Portal — Main Page
|
|
// Loads Municipality Configuration from the Database and renders the
|
|
// Map Interface with Header, Sidebar, and Footer.
|
|
// =====================================================================
|
|
|
|
require_once __DIR__ . '/../api/db.php';
|
|
|
|
// -----------------------------------------------------------------
|
|
// Load Municipality Configuration
|
|
// ToDo: Make dynamic via URL Slug (e.g. /lohne) once multi-tenant
|
|
// Routing is implemented. Hardcoded to Slug 'lohne' for now.
|
|
// -----------------------------------------------------------------
|
|
$pdo = get_db();
|
|
$stmt = $pdo->prepare("SELECT * FROM municipalities WHERE slug = :slug");
|
|
$stmt->execute([':slug' => 'lohne']);
|
|
$municipality = $stmt->fetch();
|
|
|
|
if (!$municipality) {
|
|
die("Municipality not found.");
|
|
}
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Bürgerbeteiligung <?= htmlspecialchars($municipality['name']) ?></title>
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- CSS Dependencies -->
|
|
<!-- ============================================================= -->
|
|
|
|
<!-- Leaflet 1.9.4 -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css">
|
|
|
|
<!-- Geoman Drawing Tools -->
|
|
<link rel="stylesheet" href="https://unpkg.com/@geoman-io/leaflet-geoman-free@2.17.0/dist/leaflet-geoman.css">
|
|
|
|
<!-- Leaflet Sidebar v2 -->
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet-sidebar-v2@3.2.3/css/leaflet-sidebar.min.css">
|
|
|
|
<!-- Leaflet Fullscreen -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.fullscreen/3.0.2/Control.FullScreen.css">
|
|
|
|
<!-- Leaflet Geocoder (Address Search) -->
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet-control-geocoder@2.4.0/dist/Control.Geocoder.css">
|
|
|
|
<!-- Leaflet PolylineMeasure -->
|
|
<link rel="stylesheet" href="https://ppete2.github.io/Leaflet.PolylineMeasure/Leaflet.PolylineMeasure.css">
|
|
|
|
<!-- SweetAlert2 (Confirmation Dialogs) -->
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
|
|
|
<!-- Font Awesome 6 (Icons) -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
|
|
|
<!-- Application Styles -->
|
|
<link rel="stylesheet" href="styles.css">
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- Municipality Theme (loaded from Database) -->
|
|
<!-- ============================================================= -->
|
|
<style>
|
|
:root {
|
|
--color-primary: <?= htmlspecialchars($municipality['primary_color']) ?>;
|
|
--color-primary-light: <?= htmlspecialchars($municipality['primary_color']) ?>22;
|
|
--color-primary-dark: <?= htmlspecialchars($municipality['primary_color']) ?>;
|
|
--map-center-lat: <?= $municipality['center_lat'] ?>;
|
|
--map-center-lng: <?= $municipality['center_lng'] ?>;
|
|
--map-default-zoom: <?= $municipality['default_zoom'] ?>;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- Header -->
|
|
<!-- ============================================================= -->
|
|
<header id="app-header">
|
|
<div class="header-left">
|
|
<img src="assets/logo-municipality.png" alt="<?= htmlspecialchars($municipality['name']) ?>" class="header-logo" onerror="this.style.display='none'">
|
|
<h1 class="header-title">Bürgerbeteiligung <?= htmlspecialchars($municipality['name']) ?></h1>
|
|
</div>
|
|
|
|
<nav class="header-nav">
|
|
<button class="nav-btn" onclick="showInfoModal()">
|
|
<i class="fa-solid fa-circle-info"></i>
|
|
<span class="nav-label">Info</span>
|
|
</button>
|
|
<button class="nav-btn" onclick="showPrivacyModal()">
|
|
<i class="fa-solid fa-shield-halved"></i>
|
|
<span class="nav-label">Datenschutz</span>
|
|
</button>
|
|
<button class="nav-btn" onclick="showImprintModal()">
|
|
<i class="fa-solid fa-scale-balanced"></i>
|
|
<span class="nav-label">Impressum</span>
|
|
</button>
|
|
</nav>
|
|
|
|
<!-- Mobile Hamburger Menu -->
|
|
<button class="header-menu-toggle" onclick="toggleMobileNav()">
|
|
<i class="fa-solid fa-bars"></i>
|
|
</button>
|
|
</header>
|
|
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- Map Container with Sidebar -->
|
|
<!-- ============================================================= -->
|
|
<main id="app-main">
|
|
|
|
<!-- Leaflet Sidebar v2 -->
|
|
<div id="sidebar" class="leaflet-sidebar collapsed">
|
|
|
|
<!-- Sidebar Tab Icons -->
|
|
<div class="leaflet-sidebar-tabs">
|
|
<ul role="tablist">
|
|
<li><a href="#tab-home" role="tab"><i class="fa-solid fa-house"></i></a></li>
|
|
<li><a href="#tab-list" role="tab"><i class="fa-solid fa-list"></i></a></li>
|
|
<li><a href="#tab-help" role="tab"><i class="fa-solid fa-circle-question"></i></a></li>
|
|
<li><a href="#tab-news" role="tab"><i class="fa-solid fa-newspaper"></i></a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Sidebar Tab Content -->
|
|
<div class="leaflet-sidebar-content">
|
|
|
|
<!-- Home Tab -->
|
|
<div class="leaflet-sidebar-pane" id="tab-home">
|
|
<h2 class="leaflet-sidebar-header">
|
|
Übersicht
|
|
<span class="leaflet-sidebar-close"><i class="fa-solid fa-xmark"></i></span>
|
|
</h2>
|
|
<div class="sidebar-body">
|
|
<p>Willkommen beim Bürgerbeteiligungsportal <strong><?= htmlspecialchars($municipality['name']) ?></strong>.</p>
|
|
<p>Nutzen Sie die Karte, um Hinweise und Aufgaben zu erstellen oder bestehende Beiträge einzusehen.</p>
|
|
|
|
<h3>Kategorien</h3>
|
|
<div id="category-filter">
|
|
<!-- Category Filter Checkboxes — populated by app.js -->
|
|
</div>
|
|
|
|
<h3>Statistik</h3>
|
|
<div id="stats-container">
|
|
<!-- Contribution Statistics — populated by app.js -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- List Tab -->
|
|
<div class="leaflet-sidebar-pane" id="tab-list">
|
|
<h2 class="leaflet-sidebar-header">
|
|
Beiträge
|
|
<span class="leaflet-sidebar-close"><i class="fa-solid fa-xmark"></i></span>
|
|
</h2>
|
|
<div class="sidebar-body">
|
|
<div class="list-search">
|
|
<input type="text" id="list-search-input" placeholder="Beiträge durchsuchen..." class="form-input">
|
|
</div>
|
|
<div id="contributions-list">
|
|
<!-- Contribution Cards — populated by app.js -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Help Tab -->
|
|
<div class="leaflet-sidebar-pane" id="tab-help">
|
|
<h2 class="leaflet-sidebar-header">
|
|
Hilfe
|
|
<span class="leaflet-sidebar-close"><i class="fa-solid fa-xmark"></i></span>
|
|
</h2>
|
|
<div class="sidebar-body">
|
|
<h3><i class="fa-solid fa-map-location-dot"></i> Karte bedienen</h3>
|
|
<p>Verschieben Sie die Karte per Mausklick und Ziehen. Zoomen Sie mit dem Mausrad oder den Zoom-Buttons.</p>
|
|
|
|
<h3><i class="fa-solid fa-plus"></i> Beitrag erstellen</h3>
|
|
<p>Nutzen Sie die Zeichenwerkzeuge rechts auf der Karte, um einen Punkt, eine Linie oder eine Fläche zu zeichnen. Anschließend können Sie Kategorie und Beschreibung eingeben.</p>
|
|
|
|
<h3><i class="fa-solid fa-thumbs-up"></i> Abstimmen</h3>
|
|
<p>Klicken Sie auf einen bestehenden Beitrag und nutzen Sie die Like/Dislike-Buttons, um Ihre Meinung zu äußern.</p>
|
|
|
|
<h3><i class="fa-solid fa-magnifying-glass"></i> Suchen</h3>
|
|
<p>Nutzen Sie die Adresssuche oben rechts auf der Karte, um einen bestimmten Ort zu finden.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- News Tab -->
|
|
<div class="leaflet-sidebar-pane" id="tab-news">
|
|
<h2 class="leaflet-sidebar-header">
|
|
Neuigkeiten
|
|
<span class="leaflet-sidebar-close"><i class="fa-solid fa-xmark"></i></span>
|
|
</h2>
|
|
<div class="sidebar-body">
|
|
<div class="news-item">
|
|
<span class="news-date">April 2026</span>
|
|
<h3>Portal gestartet</h3>
|
|
<p>Das Bürgerbeteiligungsportal für <?= htmlspecialchars($municipality['name']) ?> ist online. Wir freuen uns auf Ihre Hinweise und Vorschläge!</p>
|
|
</div>
|
|
<!-- More News Items can be added here or loaded from Database -->
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Map -->
|
|
<div id="map"></div>
|
|
|
|
</main>
|
|
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- Footer -->
|
|
<!-- ============================================================= -->
|
|
<footer id="app-footer">
|
|
<div class="footer-content">
|
|
<img src="assets/logo-company.png" alt="Company Logo" class="footer-logo" onerror="this.style.display='none'">
|
|
<span class="footer-text">© <?= date('Y') ?> <?= htmlspecialchars($municipality['name']) ?> — Bürgerbeteiligungsportal</span>
|
|
</div>
|
|
</footer>
|
|
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- Welcome Modal (shown on first Visit) -->
|
|
<!-- ============================================================= -->
|
|
<div id="welcome-modal" class="modal-overlay" style="display:none;">
|
|
<div class="modal-content">
|
|
<h2><i class="fa-solid fa-hand-wave"></i> Willkommen!</h2>
|
|
<p>Herzlich willkommen beim Bürgerbeteiligungsportal <strong><?= htmlspecialchars($municipality['name']) ?></strong>.</p>
|
|
<p>Hier können Sie:</p>
|
|
<ul>
|
|
<li>Hinweise und Verbesserungsvorschläge auf der Karte eintragen</li>
|
|
<li>Bestehende Beiträge einsehen und bewerten</li>
|
|
<li>Aufgaben der Stadtverwaltung unterstützen</li>
|
|
</ul>
|
|
<p>Zum Erstellen von Beiträgen geben Sie bitte zunächst Ihren Namen ein.</p>
|
|
<div class="modal-actions">
|
|
<button class="btn btn-primary" onclick="closeWelcomeAndShowLogin()">Loslegen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- Login Modal (Name Entry — later: full Authentication) -->
|
|
<!-- ============================================================= -->
|
|
<div id="login-modal" class="modal-overlay" style="display:none;">
|
|
<div class="modal-content modal-small">
|
|
<h2><i class="fa-solid fa-user"></i> Anmelden</h2>
|
|
<p>Bitte geben Sie Ihren Namen ein, um Beiträge erstellen und abstimmen zu können.</p>
|
|
<div class="form-group">
|
|
<label for="user-name-input">Ihr Name</label>
|
|
<input type="text" id="user-name-input" class="form-input" placeholder="Vor- und Nachname">
|
|
</div>
|
|
<div class="modal-actions">
|
|
<button class="btn btn-secondary" onclick="skipLogin()">Nur ansehen</button>
|
|
<button class="btn btn-primary" onclick="submitLogin()">Anmelden</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- Create Contribution Modal -->
|
|
<!-- ============================================================= -->
|
|
<div id="create-modal" class="modal-overlay" style="display:none;">
|
|
<div class="modal-content">
|
|
<h2><i class="fa-solid fa-plus-circle"></i> Neuer Beitrag</h2>
|
|
|
|
<div class="form-group">
|
|
<label for="create-category">Kategorie</label>
|
|
<select id="create-category" class="form-input">
|
|
<option value="">— Bitte wählen —</option>
|
|
<option value="mobility">🚲 Mobilität</option>
|
|
<option value="building">🏗️ Bauen</option>
|
|
<option value="energy">⚡ Energie</option>
|
|
<option value="environment">🌳 Umwelt</option>
|
|
<option value="industry">🏭 Industrie</option>
|
|
<option value="consumption">🛒 Konsum</option>
|
|
<option value="other">📌 Sonstiges</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="create-title">Titel</label>
|
|
<input type="text" id="create-title" class="form-input" placeholder="Kurze Beschreibung des Anliegens">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="create-description">Beschreibung</label>
|
|
<textarea id="create-description" class="form-input" rows="4" placeholder="Detaillierte Beschreibung (optional)"></textarea>
|
|
</div>
|
|
|
|
<input type="hidden" id="create-geom">
|
|
<input type="hidden" id="create-geom-type">
|
|
|
|
<div class="modal-actions">
|
|
<button class="btn btn-secondary" onclick="cancelCreate()">Abbrechen</button>
|
|
<button class="btn btn-primary" onclick="submitCreate()">Beitrag einreichen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- JavaScript Dependencies -->
|
|
<!-- ============================================================= -->
|
|
|
|
<!-- Leaflet 1.9.4 -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js"></script>
|
|
|
|
<!-- Geoman Drawing Tools -->
|
|
<script src="https://unpkg.com/@geoman-io/leaflet-geoman-free@2.17.0/dist/leaflet-geoman.min.js"></script>
|
|
|
|
<!-- Leaflet Sidebar v2 -->
|
|
<script src="https://unpkg.com/leaflet-sidebar-v2@3.2.3/js/leaflet-sidebar.min.js"></script>
|
|
|
|
<!-- Leaflet Fullscreen -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.fullscreen/3.0.2/Control.FullScreen.min.js"></script>
|
|
|
|
<!-- Leaflet Geocoder (Address Search) -->
|
|
<script src="https://unpkg.com/leaflet-control-geocoder@2.4.0/dist/Control.Geocoder.min.js"></script>
|
|
|
|
<!-- Leaflet PolylineMeasure -->
|
|
<script src="https://ppete2.github.io/Leaflet.PolylineMeasure/Leaflet.PolylineMeasure.js"></script>
|
|
|
|
<!-- SweetAlert2 -->
|
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.all.min.js"></script>
|
|
|
|
<!-- ============================================================= -->
|
|
<!-- Municipality Configuration (passed to JavaScript) -->
|
|
<!-- ============================================================= -->
|
|
<script>
|
|
// Municipality Configuration from Database — used by app.js
|
|
var MUNICIPALITY = {
|
|
id: <?= $municipality['municipality_id'] ?>,
|
|
name: "<?= htmlspecialchars($municipality['name'], ENT_QUOTES) ?>",
|
|
slug: "<?= htmlspecialchars($municipality['slug'], ENT_QUOTES) ?>",
|
|
center: [<?= $municipality['center_lat'] ?>, <?= $municipality['center_lng'] ?>],
|
|
zoom: <?= $municipality['default_zoom'] ?>,
|
|
primaryColor: "<?= htmlspecialchars($municipality['primary_color'], ENT_QUOTES) ?>"
|
|
};
|
|
</script>
|
|
|
|
<!-- Application Logic -->
|
|
<script src="js/app.js"></script>
|
|
|
|
</body>
|
|
</html>
|