Bläddra i källkod

initial upload ... somewhat cleaned up and "less" swearing included

UMTS at Teleco 9 månader sedan
incheckning
f402e0c96a
100 ändrade filer med 4813 tillägg och 0 borttagningar
  1. BIN
      .DS_Store
  2. 142 0
      README.md
  3. BIN
      admin/.DS_Store
  4. BIN
      admin/assets/.DS_Store
  5. BIN
      admin/assets/svg/.DS_Store
  6. 16 0
      admin/assets/svg/teleco.svg
  7. 37 0
      admin/backup_database.php
  8. 110 0
      admin/index.php
  9. 361 0
      admin/tools/edit_database.php
  10. 80 0
      admin/tools/edit_row.php
  11. 222 0
      admin/tools/manage_files.php
  12. 171 0
      common/functions.php
  13. 98 0
      common/navbar.php
  14. 151 0
      common/navbarjs.php
  15. 48 0
      config.php
  16. BIN
      website/.DS_Store
  17. BIN
      website/content.db
  18. BIN
      website/public/assets/.DS_Store
  19. 452 0
      website/public/assets/css/tc.css
  20. BIN
      website/public/assets/img/.DS_Store
  21. BIN
      website/public/assets/img/code-is-ass.jpeg
  22. BIN
      website/public/assets/img/dialon.png
  23. BIN
      website/public/assets/img/force.png
  24. BIN
      website/public/assets/img/fuck-main.jpeg
  25. BIN
      website/public/assets/img/fuckjs.jpeg
  26. BIN
      website/public/assets/img/jsmomentom.jpg
  27. BIN
      website/public/assets/img/router1.jpg
  28. BIN
      website/public/assets/img/router2.jpg
  29. BIN
      website/public/assets/img/rover.png
  30. BIN
      website/public/assets/img/ssc.jpg
  31. BIN
      website/public/assets/img/wrong.png
  32. 16 0
      website/public/assets/svg/teleco.svg
  33. 121 0
      website/public/index.php
  34. BIN
      website2/.DS_Store
  35. BIN
      website2/content2.db
  36. BIN
      website2/public/assets/.DS_Store
  37. 452 0
      website2/public/assets/css/tc.css
  38. BIN
      website2/public/assets/img/.DS_Store
  39. BIN
      website2/public/assets/img/code-is-ass.jpeg
  40. BIN
      website2/public/assets/img/dialon.png
  41. BIN
      website2/public/assets/img/force.png
  42. BIN
      website2/public/assets/img/fuck-main.jpeg
  43. BIN
      website2/public/assets/img/fuckjs.jpeg
  44. BIN
      website2/public/assets/img/jsmomentom.jpg
  45. BIN
      website2/public/assets/img/router1.jpg
  46. BIN
      website2/public/assets/img/router2.jpg
  47. BIN
      website2/public/assets/img/rover.png
  48. BIN
      website2/public/assets/img/ssc.jpg
  49. BIN
      website2/public/assets/img/wrong.png
  50. 16 0
      website2/public/assets/svg/teleco.svg
  51. 120 0
      website2/public/index.php
  52. BIN
      website3/.DS_Store
  53. BIN
      website3/content3.db
  54. BIN
      website3/public/assets/.DS_Store
  55. 313 0
      website3/public/assets/css/dialon.css
  56. 180 0
      website3/public/assets/css/extras.css
  57. 138 0
      website3/public/assets/css/hamburger.css
  58. 224 0
      website3/public/assets/css/navbar.css
  59. BIN
      website3/public/assets/fonts/.DS_Store
  60. BIN
      website3/public/assets/fonts/default.ttf
  61. BIN
      website3/public/assets/img/.DS_Store
  62. BIN
      website3/public/assets/img/code-is-ass.jpeg
  63. BIN
      website3/public/assets/img/dialon.png
  64. BIN
      website3/public/assets/img/force.png
  65. BIN
      website3/public/assets/img/fuck-main.jpeg
  66. BIN
      website3/public/assets/img/fuckjs.jpeg
  67. BIN
      website3/public/assets/img/jsmomentom.jpg
  68. BIN
      website3/public/assets/img/router1.jpg
  69. BIN
      website3/public/assets/img/router2.jpg
  70. BIN
      website3/public/assets/img/rover.png
  71. BIN
      website3/public/assets/img/ssc.jpg
  72. BIN
      website3/public/assets/img/wrong.png
  73. 94 0
      website3/public/assets/js/chat.js
  74. 40 0
      website3/public/assets/js/menu.js
  75. 16 0
      website3/public/assets/svg/teleco.svg
  76. 190 0
      website3/public/index.php
  77. BIN
      website4/.DS_Store
  78. BIN
      website4/content4.db
  79. BIN
      website4/public/assets/.DS_Store
  80. 313 0
      website4/public/assets/css/dialon.css
  81. 180 0
      website4/public/assets/css/extras.css
  82. 138 0
      website4/public/assets/css/hamburger.css
  83. 224 0
      website4/public/assets/css/navbar.css
  84. BIN
      website4/public/assets/fonts/.DS_Store
  85. BIN
      website4/public/assets/fonts/default.ttf
  86. BIN
      website4/public/assets/img/.DS_Store
  87. BIN
      website4/public/assets/img/code-is-ass.jpeg
  88. BIN
      website4/public/assets/img/dialon.png
  89. BIN
      website4/public/assets/img/force.png
  90. BIN
      website4/public/assets/img/fuck-main.jpeg
  91. BIN
      website4/public/assets/img/fuckjs.jpeg
  92. BIN
      website4/public/assets/img/jsmomentom.jpg
  93. BIN
      website4/public/assets/img/router1.jpg
  94. BIN
      website4/public/assets/img/router2.jpg
  95. BIN
      website4/public/assets/img/rover.png
  96. BIN
      website4/public/assets/img/ssc.jpg
  97. BIN
      website4/public/assets/img/wrong.png
  98. 94 0
      website4/public/assets/js/chat.js
  99. 40 0
      website4/public/assets/js/menu.js
  100. 16 0
      website4/public/assets/svg/teleco.svg

BIN
.DS_Store


+ 142 - 0
README.md

@@ -0,0 +1,142 @@
+# TC-C-CMS
+
+Welcome to **TC-C-CMS** (Teleco's Crappy Content Management System)!
+This project consists mostly of some loose and very basic code that helps you manage content for your websites and make them (to some degree) usable!
+
+## Project "Structure"
+(i included this because this is what "professionals" are supposed to do ... i am not a professional however)
+
+### **adminier folder (no login system because that's your job)**
+Contains the admin welcome panel, backup database function, and links to edit the database (**very very very fragile**).
+Please, if you dare use this in production, make many database backups becaus I wrote this entire thing from the ground up myself.
+
+It also contains a **file manager** that can back up the entire website folder along with the database, as well as upload and manage files (also written by me, poorly).
+
+- **admin/**: Contains the admin panel for managing the CMS.
+  - **tools/**: Includes various tools described above.
+  - **index.php**: The main entry point for the admin panel.
+  - **backup_databases.php**: Makes database backups and stuff.
+
+### **Common rendering utilities**
+Contains common things needed to render websites with beautiful PHP. Mmm yes, I love PHP ❤️❤️❤️. **JS bad!**
+
+- **common/**: Shared resources and functions used across different websites.
+  - **functions.php**: Common functions and variables used throughout the CMS.
+  - **navbar.php**: Functions for rendering the standard PURE HTML NO JS navbar.
+  - **navbarjs.php**: Functions for rendering the JavaScript kinda required navbar.
+---
+
+## **Included Website Templates**
+
+### **Website 1**
+- Sidebars only, no navbar, no JS at all.
+- Semi-mobile optimized.
+- **Template name:** *einfach geil*
+
+- **website/**: Contains the public-facing code for the first template.
+  - **public/**: The public directory for the first website.
+    - **index.php**: The main entry point.
+
+### **Website 2**
+- Navbar only, no sidebars.
+- You can mix and match stuff, but I haven't (yet).
+- **Template name:** *fick geil jaman*
+
+- **website2/**: Contains the public-facing code for the second template.
+  - **public/**:
+    - **index.php**: The main entry point.
+
+### **Website 3**
+- Sidebars only, no navbar.
+- Some small, goofy JS (ew, I know).
+- Has **cat virtual support**.
+- **Template name:** *Ich hasse JS number 1 geh kotzen*
+
+- **website3/**:
+  - **public/**:
+    - **index.php**
+
+### **Website 4**
+- Navbar only, no sidebars.
+- Some small, goofy JS (ew, I know).
+- Has **cat virtual support**.
+- **Template name:** *Ich hasse JS nummer 2 flatterschiss*
+
+- **website4/**:
+  - **public/**:
+    - **index.php**
+---
+
+## **Getting Started**
+
+### **Cool, I don’t care. What can it do and how do I use it?**
+You can make basic **goofy ahh sites** and dynamically change things from the admin panel.
+This includes creating pages and posts, adding navbar/sidebar entries, and uploading files.
+It's like... *wow, so super premium* (irony).
+
+### **TL;DR**
+It’s so simple to run that I could do it in my sleep, blindfolded, and without any sense of touch.
+There are **4 basic website templates** in this repo, based on actual sites I run (or plan to run soon with this tool).
+---
+
+### **What do you need to get started?**
+- Install SQLite and PHP on whatever potato PC you have lying around.
+- How you install PHP on your potato machine? IDK. (Add description for Mac, Debian, and Linux but **omit Windows** because we hate Windows. If someone opens an issue asking how to run this on Windows, I will not answer it.)
+
+Unlike normal CMSs that go *brrrrrr* with a million Composer dependencies, this one **doesn't**.
+Honestly, you could even run this **without a web server** if you run two PHP dev servers and set folder permissions so that the user-exposed PHP dev server can’t access admin parts (but the admin one can).
+I **do not endorse or recommend this**, it’s just a *"yeah, you can do this"* kind of thing.
+
+### **Run it in 2 steps**
+1. Run:
+   `php -S localhost:8000`
+   in the root directory.
+2. Open in your browser:
+   [http://localhost:8000/website4/public/](http://localhost:8000/website4/public/)
+
+And *voilà*! You have a pretty website! 🎉
+---
+
+### **Editing Content**
+If you want to edit its content:
+
+1. Go to **[http://localhost:8000/admin/](http://localhost:8000/admin/)**
+2. Click **edit database** to mess with it (and pray).
+
+⚠ **Warning:** Don’t be shocked when you see **literally no CSS** after the initial admin panel.
+This is a *design choice* I made because **f*** bloat and JS**.
+
+I *could* explain how to do things in the admin panel, but it should be **self-explanatory** if you look at the database examples.
+
+### **Navbar vs Sidebar**
+There are **two main layouts**:
+- **Navbar only** → Website 2 (pure HTML, no JS at all) and Website 4 (some JS, ewww).
+- **Sidebars only** → Website 1 and Website 3.
+---
+
+## **Features**
+- **Multi-site support**: Manage multiple websites from a single CMS.
+- **Customizable navigation**: Easily configure and render navigation bars.
+- **Admin panel**: Manage content, files, and databases via a purposely painful UI.
+- **Responsive design**: Ensures your websites *kind of* work on mobile.
+---
+
+## **Contributing**
+You **can** contribute if you want…
+…but I doubt anyone will.
+
+💀 **ashdoiasjhdkljahspdoisfopiud fpoisdamupfn oiseupnf98i** 💀  
+---
+
+## **License**
+This project is licensed under the **MIT License**.
+See the [LICENSE](LICENSE) file for details. 
+
+Basically:  
+- **No warranty.**
+- **No responsibility.**
+- **I barely know how to code.**
+---
+
+### **Made with love for PHP and pure hatred for JavaScript by T.B.** ❤️ 🚀
+*ps if you want to know why theres no real commit history as of now 2025-02-14 its because of my tendency to swear in them and I wanted to not spoil this project too much with that yet...*

BIN
admin/.DS_Store


BIN
admin/assets/.DS_Store


BIN
admin/assets/svg/.DS_Store


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 16 - 0
admin/assets/svg/teleco.svg


+ 37 - 0
admin/backup_database.php

@@ -0,0 +1,37 @@
+<?php
+session_start();
+
+// Config lade
+$config = include(__DIR__ . '/../config.php');
+
+// WebsiteID us der URL hole
+$websiteId = isset($_GET['websiteId']) ? (int)$_GET['websiteId'] : 1;
+
+// Website config ider config finde
+$websiteConfig = array_filter($config, function($site) use ($websiteId) {
+    return isset($site['id']) && $site['id'] === $websiteId;
+});
+$websiteConfig = reset($websiteConfig);
+
+// omg en request mache zum backup erstelle und so wie bin ich so tüüf gfalle 😭
+$source = $websiteConfig['database'];
+$backupDir = __DIR__ . '/../' . $websiteConfig['backup_folder'];
+$timestamp = date('Y-m-d-H-i-s');
+$destination = $backupDir . '/' . $timestamp . '.db';
+
+// stell der vor es git kei backup folder 😱 denn meun mer de mache 
+if (!is_dir($backupDir)) {
+    mkdir($backupDir, 0755, true);
+}
+
+// und jetzt stell der vor mer kopieret die datei deht ineh 😱
+if (copy($source, $destination)) {
+    $backupMessage = "Database backup created successfully: " . htmlspecialchars($destination);
+} else {
+    $backupMessage = "Failed to create database backup.";
+}
+
+// zrug zum sexxi admin panel mit de message mir sind so guet und sexi , ich wird niemals eh frau ha im lebe ich bin single af
+header("Location: index.php?backupMessage=" . urlencode($backupMessage));
+exit();
+?>

+ 110 - 0
admin/index.php

@@ -0,0 +1,110 @@
+<?php
+// Start session und so
+session_start();
+
+// Config lade
+$config = include(__DIR__ . '/../config.php');
+
+// Sqlite 
+$db = new SQLite3(__DIR__ . '/../content.db');
+?>
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Admin Panel</title>
+    <link rel="stylesheet" href="../assets/css/tc.css">
+    <style> /* nachher gihts denne keis styling meh im adminier panel will das blaot oder so isch*/
+        body {
+            font-family: Arial, sans-serif;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            padding: 20px;
+        }
+        .header-content {
+            display: flex;
+            align-items: center;
+            margin-bottom: 20px;
+        }
+        .header-content img {
+            margin-right: 10px;
+            width: 50px; 
+            height: auto; 
+        }
+        .container {
+            display: flex;
+            width: 100%;
+            max-width: 1200px;
+        }
+        .sidebar {
+            width: 200px;
+            background-color: #f4f4f4;
+            padding: 15px;
+            box-shadow: 2px 0 5px rgba(0,0,0,0.1);
+        }
+        .sidebar a {
+            display: block;
+            padding: 10px;
+            margin: 5px 0;
+            color: #333;
+            text-decoration: none;
+        }
+        .sidebar a:hover {
+            background-color: #ddd;
+        }
+        .content {
+            flex-grow: 1;
+            padding: 20px;
+            background-color: #fff;
+            box-shadow: 0 0 10px rgba(0,0,0,0.1);
+        }
+        .content h1 {
+            margin-top: 0;
+        }
+        .content p {
+            margin-bottom: 20px;
+        }
+        .content form {
+            margin-bottom: 20px;
+        }
+
+    </style>
+</head>
+<body>
+    <div class="header-content">
+        <img src="assets/svg/teleco.svg" alt="Teleco Logo" class="logo">
+        <h1>Adminier Panel</h1>
+    </div>
+    <div class="container">
+        <div class="sidebar">
+            <h2>Adminier Panel</h2>
+            <form method="GET" action="index.php">
+                <label for="websiteId">Select Website:</label>
+                <select name="websiteId" id="websiteId" onchange="this.form.submit()">
+                    <?php foreach ($config as $site): ?>
+                        <?php if (isset($site['id'])): ?>
+                            <option value="<?php echo $site['id']; ?>" <?php echo (isset($_GET['websiteId']) && $_GET['websiteId'] == $site['id']) ? 'selected' : ''; ?>>
+                                <?php echo htmlspecialchars($site['name']); ?>
+                            </option>
+                        <?php endif; ?>
+                    <?php endforeach; ?>
+                </select>
+            </form>
+            <a href="backup_database.php?websiteId=<?php echo isset($_GET['websiteId']) ? (int)$_GET['websiteId'] : 1; ?>">Backup Database</a>
+            <a href="tools/edit_database.php">Edit das Database</a>
+            <a href="tools/manage_files.php">Manger das Filet</a>
+        </div>
+        <div class="content">
+            <h1>Welcome to the TC-C-CMS admin Panel</h1>
+            <p>Feast your eyes! This is the last time you will see properish CSS in the admin panel.</p>
+            <p>Made with lots of love for PHP and pure hatred against JavaScript (has none) by T.B <br> TC-C-CMS means Teleco's Crappy Content Management System btw lol hahahaha ich chan das alles nümmeh!  </p>
+            <?php if (isset($_GET['backupMessage'])): ?>
+                <p><?php echo htmlspecialchars($_GET['backupMessage']); ?></p>
+            <?php endif; ?>
+        </div>
+    </div>
+</body>
+</html>

+ 361 - 0
admin/tools/edit_database.php

@@ -0,0 +1,361 @@
+<?php
+session_start();
+
+// Config lade
+$config = include(__DIR__ . '/../../config.php');
+
+// WebsiteID us der URL oder session hole 
+$websiteId = isset($_GET['websiteId']) ? (int)$_GET['websiteId'] : (isset($_SESSION['websiteId']) ? (int)$_SESSION['websiteId'] : 1);
+$_SESSION['websiteId'] = $websiteId;
+
+// Website config ider config finde
+$websiteConfig = array_filter($config, function($site) use ($websiteId) {
+    return isset($site['id']) && $site['id'] === $websiteId;
+});
+$websiteConfig = reset($websiteConfig);
+
+// Sqlite datenbank ahfigge
+$db = new SQLite3($websiteConfig['database']);
+
+// Backup erstelle oder ganzi datehbank lôsche *evil laugh* 😈 jk mer propbieret sehr schlecht IDs wieder sekuentiel zmache
+if (isset($_POST['backup']) || isset($_POST['delete_row']) || isset($_POST['reassign_ids'])) {
+    $source = $websiteConfig['database'];
+    $backupDir = __DIR__ . '/../../' . $websiteConfig['backup_folder'];
+    $timestamp = date('Y-m-d-H-i-s');
+    $destination = $backupDir . '/' . $timestamp . '.db';
+
+    // machen das backup directory wenns nid git
+    if (!is_dir($backupDir)) {
+        mkdir($backupDir, 0755, true);
+    }
+
+    // omg file deht ineh kopiere 😱
+    if (copy($source, $destination)) {
+        $backupMessage = "Database backup created successfully: " . htmlspecialchars($destination);
+    } else {
+        $backupMessage = "Failed to create database backup.";
+    }
+}
+
+$selectedTable = $_POST['table'] ?? $_SESSION['selectedTable'] ?? '';
+$columns = [];
+$rows = [];
+$sortOrder = $_GET['sortOrder'] ?? 'ASC';
+
+$tablesResult = $db->query("SELECT name FROM sqlite_master WHERE type='table' AND name != 'sqlite_sequence'");
+$tables = [];
+while ($row = $tablesResult->fetchArray(SQLITE3_ASSOC)) {
+    $tables[] = $row['name'];
+}
+
+if ($selectedTable && in_array($selectedTable, $tables)) {
+    $_SESSION['selectedTable'] = $selectedTable;
+    $columnsResult = $db->query("PRAGMA table_info($selectedTable)");
+    while ($row = $columnsResult->fetchArray(SQLITE3_ASSOC)) {
+        $columns[] = $row['name'];
+    }
+    if ($selectedTable == 'content' && in_array('date', $columns)) {
+        $orderBy = "ORDER BY date DESC"; // das hier machen default sorting nach datum und ziiht de neuschti row zerscht will susch isch das unmanagebar
+    } else {
+        $orderBy = in_array('date', $columns) ? "ORDER BY date $sortOrder" : "ORDER BY id ASC";
+    }
+    $rowsResult = $db->query("SELECT * FROM $selectedTable $orderBy");
+    while ($row = $rowsResult->fetchArray(SQLITE3_ASSOC)) {
+        $rows[] = $row;
+    }
+} else {
+    $selectedTable = '';
+    $_SESSION['selectedTable'] = '';
+}
+
+if (isset($_POST['edit_row'])) {
+    header("Location: edit_row.php?table=$selectedTable&id=" . $_POST['id']);
+    exit();
+}
+
+if (isset($_POST['delete_row'])) {
+    $idsToDelete = $_POST['ids'] ?? [];
+    foreach ($idsToDelete as $id) {
+        $stmt = $db->prepare("DELETE FROM $selectedTable WHERE id = :id");
+        $stmt->bindValue(':id', $id, SQLITE3_INTEGER);
+        $stmt->execute();
+    }
+    $message = "Selected rows deleted successfully (most likely).";
+}
+
+if (isset($_POST['insert_row'])) {
+    $values = $_POST['values'];
+    $highestIdResult = $db->querySingle("SELECT MAX(id) as max_id FROM $selectedTable");
+    $highestId = $highestIdResult ? $highestIdResult : 0;
+    $values['id'] = $highestId + 1;
+    if ($selectedTable == 'content') {
+        if (empty($values['date'])) {
+            $values['date'] = date('Y-m-d H:i:s');
+        }
+    }
+    $columnsString = implode(", ", array_keys($values));
+    $placeholders = implode(", ", array_fill(0, count($values), "?"));
+    $stmt = $db->prepare("INSERT INTO $selectedTable ($columnsString) VALUES ($placeholders)");
+    $index = 1;
+    foreach ($values as $value) {
+        $stmt->bindValue($index, $value ?: null, SQLITE3_TEXT);
+        $index++;
+    }
+    $stmt->execute();
+    $message = "Row inserted successfully. (maybe)";
+}
+
+if (isset($_POST['swap_row'])) {
+    $id = $_POST['id'];
+    $targetId = $_POST['target_id'];
+    $db->exec("BEGIN TRANSACTION");
+    $db->exec("UPDATE $selectedTable SET id = -1 WHERE id = $id");
+    $db->exec("UPDATE $selectedTable SET id = $id WHERE id = $targetId");
+    $db->exec("UPDATE $selectedTable SET id = $targetId WHERE id = -1");
+    $db->exec("COMMIT");
+    $message = "Row swapped successfully for sure.";
+}
+
+if (isset($_POST['push_row'])) {
+    $id = $_POST['id'];
+    $targetId = $_POST['target_id'];
+    $tempTable = $selectedTable . '_temp';
+    $db->exec("BEGIN TRANSACTION");
+    $db->exec("CREATE TEMPORARY TABLE $tempTable AS SELECT * FROM $selectedTable");
+    $db->exec("UPDATE $tempTable SET id = -1 WHERE id = $id");
+    if ($id < $targetId) {
+        $db->exec("UPDATE $tempTable SET id = id - 1 WHERE id > $id AND id <= $targetId");
+    } else {
+        $db->exec("UPDATE $tempTable SET id = id + 1 WHERE id < $id AND id >= $targetId");
+    }
+    $db->exec("UPDATE $tempTable SET id = $targetId WHERE id = -1");
+    $db->exec("DELETE FROM $selectedTable");
+    $db->exec("INSERT INTO $selectedTable SELECT * FROM $tempTable");
+    $db->exec("DROP TABLE $tempTable");
+    $db->exec("COMMIT");
+    $message = "Row pushed successfully (perhaps).";
+}
+
+if (isset($_POST['reassign_ids'])) {
+    $tempBackup = $backupDir . '/' . $timestamp . '_temp.db';
+    copy($source, $tempBackup);
+
+    try {
+        $db->exec("BEGIN TRANSACTION");
+        $tempTable = $selectedTable . '_temp';
+        $db->exec("CREATE TEMPORARY TABLE $tempTable AS SELECT * FROM $selectedTable");
+        $db->exec("DELETE FROM $selectedTable");
+
+        if (in_array('date', $columns)) {
+            $orderBy = "ORDER BY date ASC";
+        } else {
+            $orderBy = "ORDER BY id ASC";
+        }
+
+        $rowsResult = $db->query("SELECT * FROM $tempTable $orderBy");
+        $newId = 1;
+        while ($row = $rowsResult->fetchArray(SQLITE3_ASSOC)) {
+            $row['id'] = $newId++;
+            $columnsString = implode(", ", array_keys($row));
+            $placeholders = implode(", ", array_fill(0, count($row), "?"));
+            $stmt = $db->prepare("INSERT INTO $selectedTable ($columnsString) VALUES ($placeholders)");
+            $index = 1;
+            foreach ($row as $value) {
+                $stmt->bindValue($index, $value ?: null, SQLITE3_TEXT);
+                $index++;
+            }
+            $stmt->execute();
+        }
+
+        $db->exec("DROP TABLE $tempTable");
+        $db->exec("COMMIT");
+        $message = "IDs reassigned successfully.";
+    } catch (Exception $e) {
+        copy($tempBackup, $source);
+        $message = "Failed to reassign IDs. Database restored from backup. (probably)";
+    } finally {
+        unlink($tempBackup);
+    }
+}
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Edit Database</title>
+</head>
+<body>
+    <form method="post" action="../index.php">
+        <button type="submit">Back to Admin Panel</button>
+    </form>
+    <h1>Edit Database</h1>
+    <form method="get" action="edit_database.php">
+        <label for="websiteId">Select Website:</label>
+        <select name="websiteId" id="websiteId" onchange="this.form.submit()">
+            <?php foreach ($config as $site): ?>
+                <?php if (isset($site['id'])): ?>
+                    <option value="<?php echo $site['id']; ?>" <?php echo ($websiteId == $site['id']) ? 'selected' : ''; ?>>
+                        <?php echo htmlspecialchars($site['name']); ?>
+                    </option>
+                <?php endif; ?>
+            <?php endforeach; ?>
+        </select>
+    </form>
+    <form method="post">
+        <button type="submit" name="backup">Backup das Database</button>
+    </form>
+    <?php if (isset($backupMessage)): ?>
+        <p><?php echo $backupMessage; ?></p>
+    <?php endif; ?>
+    <form method="post">
+        <label for="table">Select das Table:</label>
+        <select id="table" name="table" onchange="this.form.submit()">
+            <option value="">-- Select a table --</option>
+            <?php foreach ($tables as $table): ?>
+                <option value="<?php echo htmlspecialchars($table); ?>" <?php echo ($selectedTable == $table) ? 'selected' : ''; ?>><?php echo htmlspecialchars($table); ?></option>
+            <?php endforeach; ?>
+        </select>
+    </form>
+    <form method="post">
+        <button type="submit" name="refresh">Refresh</button>
+    </form>
+    <?php if ($selectedTable): ?>
+        <h2>Editing Table: <?php echo htmlspecialchars($selectedTable); ?></h2>
+        <?php if ($selectedTable == 'content'): ?>
+            <form method="post">
+                <input type="hidden" name="table" value="<?php echo htmlspecialchars($selectedTable); ?>">
+                <table border="1">
+                    <thead>
+                        <tr>
+                            <th>Select</th>
+                            <?php foreach ($columns as $column): ?>
+                                <th>
+                                    <?php echo htmlspecialchars($column); ?>
+                                    <?php if ($column == 'date'): ?>
+                                        <a href="?table=<?php echo htmlspecialchars($selectedTable); ?>&sortOrder=<?php echo $sortOrder == 'ASC' ? 'DESC' : 'ASC'; ?>">Sort by Date</a>
+                                    <?php endif; ?>
+                                </th>
+                            <?php endforeach; ?>
+                            <th>Actions</th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        <tr>
+                            <td></td>
+                            <?php foreach ($columns as $column): ?>
+                                <td>
+                                    <?php if ($column == 'id'): ?>
+                                        <input type="text" name="values[<?php echo htmlspecialchars($column); ?>]" disabled>
+                                    <?php elseif ($column == 'date'): ?>
+                                        <input type="text" name="values[<?php echo htmlspecialchars($column); ?>]" value="<?php echo date('Y-m-d H:i:s'); ?>" disabled>
+                                        <input type="text" name="values[<?php echo htmlspecialchars($column); ?>]">
+                                    <?php endif; ?>
+                                </td>
+                            <?php endforeach; ?>
+                            <td>
+                                <button type="submit" name="insert_row">Add Row</button>
+                            </td>
+                        </tr>
+                        <?php foreach ($rows as $row): ?>
+                            <tr>
+                                <td><input type="checkbox" name="ids[]" value="<?php echo $row['id']; ?>"></td>
+                                <?php foreach ($columns as $column): ?>
+                                    <td><?php echo htmlspecialchars($row[$column] ?? ''); ?></td>
+                                <?php endforeach; ?>
+                                <td>
+                                    <form method="post" style="display:inline;">
+                                        <input type="hidden" name="id" value="<?php echo $row['id']; ?>">
+                                        <button type="submit" name="edit_row">Edit</button>
+                                    </form>
+                                    <form method="post" style="display:inline;">
+                                        <input type="hidden" name="id" value="<?php echo $row['id']; ?>">
+                                        <button type="submit" name="delete_row">Delete</button>
+                                    </form>
+                                    <form method="post" style="display:inline;">
+                                        <input type="hidden" name="id" value="<?php echo $row['id']; ?>">
+                                        <input type="text" name="target_id" placeholder="Target ID">
+                                        <button type="submit" name="swap_row">Swap</button>
+                                        <button type="submit" name="push_row">Push</button>
+                                    </form>
+                                </td>
+                            </tr>
+                        <?php endforeach; ?>
+                    </tbody>
+                </table>
+                <button type="submit" name="delete_row">Maybe Delete Selected Rows</button>
+                <button type="submit" name="reassign_ids">Maybe Reassign IDs</button>
+            </form>
+        <?php else: ?>
+            <form method="post">
+                <input type="hidden" name="table" value="<?php echo htmlspecialchars($selectedTable); ?>">
+                <table border="1">
+                    <thead>
+                        <tr>
+                            <th>Select</th>
+                            <?php foreach ($columns as $column): ?>
+                                <th>
+                                    <?php echo htmlspecialchars($column); ?>
+                                    <?php if ($column == 'date'): ?>
+                                        <a href="?table=<?php echo htmlspecialchars($selectedTable); ?>&sortOrder=<?php echo $sortOrder == 'ASC' ? 'DESC' : 'ASC'; ?>">Sort by Datum</a>
+                                    <?php endif; ?>
+                                </th>
+                            <?php endforeach; ?>
+                            <th>Actions</th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        <?php foreach ($rows as $row): ?>
+                            <tr>
+                                <td><input type="checkbox" name="ids[]" value="<?php echo $row['id']; ?>"></td>
+                                <?php foreach ($columns as $column): ?>
+                                    <td><?php echo htmlspecialchars($row[$column] ?? ''); ?></td>
+                                <?php endforeach; ?>
+                                <td>
+                                    <form method="post" style="display:inline;">
+                                        <input type="hidden" name="id" value="<?php echo $row['id']; ?>">
+                                        <button type="submit" name="edit_row">Edit</button>
+                                    </form>
+                                    <form method="post" style="display:inline;">
+                                        <input type="hidden" name="id" value="<?php echo $row['id']; ?>">
+                                        <button type="submit" name="delete_row">Bye</button>
+                                    </form>
+                                    <form method="post" style="display:inline;">
+                                        <input type="hidden" name="id" value="<?php echo $row['id']; ?>">
+                                        <input type="text" name="target_id" placeholder="Target ID">
+                                        <button type="submit" name="swap_row">Swap</button>
+                                        <button type="submit" name="push_row">Push</button>
+                                    </form>
+                                </td>
+                            </tr>
+                        <?php endforeach; ?>
+                        <tr>
+                            <td></td>
+                            <?php foreach ($columns as $column): ?>
+                                <td>
+                                    <?php if ($column == 'id'): ?>
+                                        <input type="text" name="values[<?php echo htmlspecialchars($column); ?>]" disabled>
+                                    <?php elseif ($column == 'date'): ?>
+                                        <input type="text" name="values[<?php echo htmlspecialchars($column); ?>]" value="<?php echo date('Y-m-d H:i:s'); ?>" disabled>
+                                    <?php elseif ($selectedTable == 'content' && $column == 'custom_html'): ?>
+                                        <input type="text" name="values[<?php echo htmlspecialchars($column); ?>]" value="0">
+                                    <?php else: ?>
+                                        <input type="text" name="values[<?php echo htmlspecialchars($column); ?>]">
+                                    <?php endif; ?>
+                                </td>
+                            <?php endforeach; ?>
+                            <td>
+                                <button type="submit" name="insert_row">Add Row</button>
+                            </td>
+                        </tr>
+                    </tbody>
+                </table>
+                <button type="submit" name="delete_row">Delete Selected Rows</button>
+                <button type="submit" name="reassign_ids">Reassign IDs</button>
+            </form>
+        <?php endif; ?>
+    <?php else: ?>
+        <p>No das table selected. Please select das table to editieren.</p>
+    <?php endif; ?>
+</body>
+</html>

+ 80 - 0
admin/tools/edit_row.php

@@ -0,0 +1,80 @@
+<?php
+session_start();
+
+// Load configuration
+$config = include(__DIR__ . '/../../config.php');
+
+// Get the website ID from the session
+$websiteId = $_SESSION['websiteId'] ?? 1;
+
+// Find the website configuration
+$websiteConfig = array_filter($config, function($site) use ($websiteId) {
+    return isset($site['id']) && $site['id'] === $websiteId;
+});
+$websiteConfig = reset($websiteConfig);
+
+// Connect to SQLite database
+$db = new SQLite3($websiteConfig['database']);
+
+// Get the table and ID from the request
+$table = $_GET['table'] ?? '';
+$id = $_GET['id'] ?? 0;
+
+$columns = [];
+$columnsResult = $db->query("PRAGMA table_info($table)");
+while ($row = $columnsResult->fetchArray(SQLITE3_ASSOC)) {
+    $columns[] = $row['name'];
+}
+
+$stmt = $db->prepare("SELECT * FROM $table WHERE id = :id");
+$stmt->bindValue(':id', $id, SQLITE3_INTEGER);
+$result = $stmt->execute();
+
+if ($result) {
+    $row = $result->fetchArray(SQLITE3_ASSOC);
+} else {
+    $row = null;
+}
+
+if (isset($_POST['save_changes'])) {
+    foreach ($columns as $column) {
+        $value = $_POST[$column] ?: null;
+        if ($column == 'date' && empty($value)) {
+            $value = date('Y-m-d H:i:s');
+        }
+        if ($table == 'content' && $column == 'custom_html') {
+            $value = $value ? 1 : 0;
+        }
+        $stmt = $db->prepare("UPDATE $table SET $column = :value WHERE id = :id");
+        $stmt->bindValue(':value', $value, SQLITE3_TEXT);
+        $stmt->bindValue(':id', $id, SQLITE3_INTEGER);
+        $stmt->execute();
+    }
+    header("Location: edit_database.php?table=$table");
+    exit();
+}
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Edit Row</title>
+</head>
+<body>
+    <h1>Edit Row in Table: <?php echo htmlspecialchars($table); ?></h1>
+    <form method="post">
+        <?php foreach ($columns as $column): ?>
+            <label for="<?php echo htmlspecialchars($column); ?>"><?php echo htmlspecialchars($column); ?>:</label>
+            <?php if ($table == 'content' && $column == 'content'): ?>
+                <textarea id="<?php echo htmlspecialchars($column); ?>" name="<?php echo htmlspecialchars($column); ?>" style="resize: both;"><?php echo htmlspecialchars($row[$column] ?? ''); ?></textarea>
+            <?php else: ?>
+                <input type="text" id="<?php echo htmlspecialchars($column); ?>" name="<?php echo htmlspecialchars($column); ?>" value="<?php echo htmlspecialchars($row[$column] ?? ''); ?>">
+            <?php endif; ?>
+            <br>
+        <?php endforeach; ?>
+        <button type="submit" name="save_changes">Save Changes</button>
+    </form>
+    <a href="edit_database.php?table=<?php echo htmlspecialchars($table); ?>">Back to Table</a>
+</body>
+</html>

+ 222 - 0
admin/tools/manage_files.php

@@ -0,0 +1,222 @@
+<?php
+session_start();
+
+// Load configuration
+$config = include(__DIR__ . '/../../config.php');
+
+// Get the website ID from the request or session
+$websiteId = isset($_GET['websiteId']) ? (int)$_GET['websiteId'] : (isset($_SESSION['websiteId']) ? (int)$_SESSION['websiteId'] : 1);
+$_SESSION['websiteId'] = $websiteId;
+
+// Find the website configuration
+$websiteConfig = array_filter($config, function($site) use ($websiteId) {
+    return isset($site['id']) && $site['id'] === $websiteId;
+});
+$websiteConfig = reset($websiteConfig);
+
+// Enable error reporting
+error_reporting(E_ALL);
+ini_set('display_errors', 1);
+
+$rootDir = realpath(__DIR__ . '/../../' . $websiteConfig['folder']);
+$currentDir = isset($_GET['dir']) ? realpath($rootDir . '/' . $_GET['dir']) : $rootDir;
+
+// Ensure the current directory is within the root directory
+if (strpos($currentDir, $rootDir) !== 0) {
+    $currentDir = $rootDir;
+}
+
+// Handle file upload
+if (isset($_POST['upload'])) {
+    $targetFile = $currentDir . '/' . basename($_FILES['file']['name']);
+    if (move_uploaded_file($_FILES['file']['tmp_name'], $targetFile)) {
+        $message = "File uploaded successfully.";
+    } else {
+        $message = "Failed to upload file.";
+    }
+}
+
+// Handle file deletion
+if (isset($_POST['delete'])) {
+    $fileToDelete = $currentDir . '/' . $_POST['filename'];
+    if (unlink($fileToDelete)) {
+        $message = "File deleted successfully.";
+    } else {
+        $message = "Failed to delete file.";
+    }
+}
+
+// Handle file renaming
+if (isset($_POST['rename'])) {
+    $oldName = $currentDir . '/' . $_POST['oldname'];
+    $newName = $currentDir . '/' . $_POST['newname'];
+    if (rename($oldName, $newName)) {
+        $message = "File renamed successfully.";
+    } else {
+        $message = "Failed to rename file.";
+    }
+}
+
+// Handle folder creation
+if (isset($_POST['create_folder'])) {
+    $newFolder = $currentDir . '/' . $_POST['foldername'];
+    if (mkdir($newFolder, 0755, true)) {
+        $message = "Folder created successfully.";
+    } else {
+        $message = "Failed to create folder.";
+    }
+}
+
+// Handle folder deletion
+if (isset($_POST['delete_folder'])) {
+    $folderToDelete = $currentDir . '/' . $_POST['foldername'];
+    if (rmdir($folderToDelete)) {
+        $message = "Folder deleted successfully.";
+    } else {
+        $message = "Failed to delete folder.";
+    }
+}
+
+// Handle folder backup
+if (isset($_POST['backup_folder'])) {
+    $backupDir = realpath(__DIR__ . '/../../' . $websiteConfig['backup_folder']);
+    $backupFile = $backupDir . '/' . basename($currentDir) . '_' . date('Ymd_His') . '.tar';
+    $command = "tar -cf $backupFile -C " . escapeshellarg($currentDir) . " .";
+    exec($command, $output, $returnVar);
+    if ($returnVar === 0) {
+        $message = "Folder backed up successfully.";
+    } else {
+        $message = "Failed to back up folder.";
+    }
+}
+
+// Get list of files and directories
+$items = scandir($currentDir);
+
+// Get relative path for display
+$relativePath = str_replace($rootDir, '', $currentDir);
+if ($relativePath === '') {
+    $relativePath = '/';
+}
+?>
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Manage Files</title>
+</head>
+<body>
+    <div class="container">
+        <form method="post" action="../index.php">
+            <button type="submit">Back to Admin Panel</button>
+        </form>
+        <h1>File Manager</h1>
+        <form method="get" action="manage_files.php">
+            <label for="websiteId">Select Website:</label>
+            <select name="websiteId" id="websiteId" onchange="this.form.submit()">
+                <?php foreach ($config as $site): ?>
+                    <?php if (isset($site['id'])): ?>
+                        <option value="<?php echo $site['id']; ?>" <?php echo ($websiteId == $site['id']) ? 'selected' : ''; ?>>
+                            <?php echo htmlspecialchars($site['name']); ?>
+                        </option>
+                    <?php endif; ?>
+                <?php endforeach; ?>
+            </select>
+        </form>
+        <?php if (isset($message)): ?>
+            <p class="message"><?php echo $message; ?></p>
+        <?php endif; ?>
+        <h2>Current Directory: <?php echo htmlspecialchars($relativePath); ?></h2>
+        <form method="post">
+            <button type="submit" name="refresh">Refresh</button>
+        </form>
+        <table border="1">
+            <thead>
+                <tr>
+                    <th colspan="2"></th>
+                </tr>
+            </thead>
+            <tbody>
+                <?php if ($currentDir !== $rootDir): ?>
+                    <tr>
+                        <td colspan="2"><a href="?dir=<?php echo urlencode(dirname($relativePath)); ?>&websiteId=<?php echo $websiteId; ?>">.. (Parent Directory)</a></td>
+                    </tr>
+                <?php endif; ?>
+                <tr>
+                    <td colspan="2" style="text-align: center; background-color: yellow;"><strong>Folders</strong></td>
+                </tr>
+                <?php foreach ($items as $item): ?>
+                    <?php if ($item === '.' || $item === '..') continue; ?>
+                    <?php if (is_dir($currentDir . '/' . $item)): ?>
+                        <tr>
+                            <td><a href="?dir=<?php echo urlencode(ltrim($relativePath . '/' . $item, '/')); ?>&websiteId=<?php echo $websiteId; ?>"><?php echo htmlspecialchars($item); ?></a></td>
+                            <td class="actions">
+                                <form method="post" style="display:inline;">
+                                    <input type="hidden" name="foldername" value="<?php echo htmlspecialchars($item); ?>">
+                                    <button type="submit" name="delete_folder">Delete</button>
+                                </form>
+                                <form method="post" style="display:inline;">
+                                    <input type="hidden" name="oldname" value="<?php echo htmlspecialchars($item); ?>">
+                                    <input type="text" name="newname" placeholder="New name">
+                                    <button type="submit" name="rename">Rename</button>
+                                </form>
+                            </td>
+                        </tr>
+                    <?php endif; ?>
+                <?php endforeach; ?>
+                <tr>
+                    <td colspan="2" style="text-align: center; background-color: orange;"><strong>Files</strong></td>
+                </tr>
+                <?php foreach ($items as $item): ?>
+                    <?php if ($item === '.' || $item === '..') continue; ?>
+                    <?php if (!is_dir($currentDir . '/' . $item)): ?>
+                        <tr>
+                            <td><?php echo htmlspecialchars($item); ?></td>
+                            <td class="actions">
+                                <form method="post" style="display:inline;">
+                                    <input type="hidden" name="filename" value="<?php echo htmlspecialchars($item); ?>">
+                                    <button type="submit" name="delete">Delete</button>
+                                </form>
+                                <form method="post" style="display:inline;">
+                                    <input type="hidden" name="oldname" value="<?php echo htmlspecialchars($item); ?>">
+                                    <input type="text" name="newname" placeholder="New name">
+                                    <button type="submit" name="rename">Rename</button>
+                                </form>
+                                <a href="../../<?php echo htmlspecialchars($websiteConfig['folder'] . '/' . $relativePath . '/' . $item); ?>" download>Download</a>
+                            </td>
+                        </tr>
+                    <?php endif; ?>
+                <?php endforeach; ?>
+                <tr>
+                    <td colspan="2">
+                        <h2>Upload File</h2>
+                        <form method="post" enctype="multipart/form-data">
+                            <input type="file" name="file">
+                            <button type="submit" name="upload">Upload</button>
+                        </form>
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan="2">
+                        <h2>Create Folder</h2>
+                        <form method="post">
+                            <input type="text" name="foldername" placeholder="Folder name">
+                            <button type="submit" name="create_folder">Create</button>
+                        </form>
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan="2">
+                        <h2>Backup Folder</h2>
+                        <form method="post">
+                            <button type="submit" name="backup_folder">Backup Folder</button>
+                        </form>
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
+</body>
+</html>

+ 171 - 0
common/functions.php

@@ -0,0 +1,171 @@
+<?php
+// sqlite datehbank ahfigge
+$db = new SQLite3($websiteConfig['database']);
+
+// so luegele ob mer navbar sache mache oder ob d'websihte wahrschiinlich so sidebar style wird
+$navbarTableExists = $db->querySingle("SELECT name FROM sqlite_master WHERE type='table' AND name='navbar'");
+$navbarHasEntries = $db->querySingle("SELECT COUNT(*) FROM navbar") > 0;
+
+// mis wunderschöne url handling ✨
+$page = isset($_GET['page']) ? htmlspecialchars($_GET['page']) : 'index';
+$sub = isset($_GET['sub']) ? htmlspecialchars($_GET['sub']) : null;
+$offset = isset($_GET['offset']) ? (int)$_GET['offset'] : 0;
+$limit = 10; // Number of posts per load
+$menuExpanded = isset($_GET['menu']) ? (bool)$_GET['menu'] : false;
+
+// overflow protection oder so cha kei cybersecurity
+if ($offset < 0) {
+    $offset = 0;
+}
+
+// schlimmste funktion eveer für breadcrumbs aber es funktioniert leider
+function get_full_path($db, $page, $sub = null) {
+    $path = [];
+    $current_page = $sub ?: $page; // If sub is set of posts benutzen sub suscht halt page
+
+    while ($current_page) {
+        $query = $db->prepare('SELECT parent, title, page FROM pages WHERE page = :page');
+        $query->bindValue(':page', $current_page, SQLITE3_TEXT);
+        $result = $query->execute()->fetchArray(SQLITE3_ASSOC);
+
+        if ($result) {
+            array_unshift($path, [
+                'title' => $result['title'], 
+                'page' => $result['page']
+            ]);
+            $current_page = $result['parent']; // eltere vor d'füess schiebe
+        } else {
+            break;
+        }
+    }
+    return $path;
+}
+
+$breadcrumbs = get_full_path($db, $page, $sub);
+
+// siihte metadata mache und so
+$metaQuery = $db->prepare('SELECT meta_description, parent FROM pages WHERE page = :page AND (parent IS NULL OR parent = :parent)');
+$metaQuery->bindValue(':page', $page, SQLITE3_TEXT);
+$metaQuery->bindValue(':parent', $sub, SQLITE3_TEXT);
+$metaResult = $metaQuery->execute()->fetchArray(SQLITE3_ASSOC);
+$metaDescription = $metaResult ? htmlspecialchars($metaResult['meta_description'] ?? '', ENT_QUOTES, 'UTF-8') : 'Default description of the website.';
+
+// mal gügsle wiviel posts es git hmmm 🤔 lol
+$countQuery = $db->prepare('SELECT COUNT(*) as total FROM content WHERE page = :page AND (parent IS NULL OR parent = :sub)');
+$countQuery->bindValue(':page', $page, SQLITE3_TEXT);
+$countQuery->bindValue(':sub', $sub, SQLITE3_TEXT);
+$totalPosts = $countQuery->execute()->fetchArray(SQLITE3_ASSOC)['total'];
+
+// offset dörf nid grösser sii als total posts will susch depressione
+if ($offset > $totalPosts) {
+    $offset = $totalPosts - ($totalPosts % $limit);
+}
+
+// ALLI POSTS ABRÜefe bitte ned ahlange susch hühl ich
+$query = $db->prepare('SELECT title, content, date FROM content WHERE page = :page ORDER BY date DESC LIMIT :limit OFFSET :offset');
+$query->bindValue(':page', $sub ? $sub : $page, SQLITE3_TEXT);
+$query->bindValue(':limit', $offset + $limit, SQLITE3_INTEGER);
+$query->bindValue(':offset', 0, SQLITE3_INTEGER); // immer alli posts holeh will was isch normali site pagination
+$result = $query->execute();
+
+// het page überhaupt was drufeh oder so ?
+$hasContent = $result->fetchArray() !== false;
+if ($hasContent) {
+    // Reset the result pointer
+    $result->reset();
+}
+
+// haben das linke sidebar sache?
+$leftSidebarHasItems = $db->querySingle("SELECT COUNT(*) FROM sidebar WHERE position='left'") > 0;
+
+// haben das rechte sidebar sache?
+$rightSidebarHasItems = $db->querySingle("SELECT COUNT(*) FROM sidebar WHERE position='right'") > 0;
+
+// das isch fett schaisse und ich ha kein plan ki het gseit das fixts und so ich ha kei lust meh gha ha nach 2 stund 😭
+function sameQueryParams(string $url1, string $url2): bool {
+    $parsed1 = parse_url($url1);
+    $parsed2 = parse_url($url2);
+
+    $params1 = [];
+    $params2 = [];
+    if (!empty($parsed1['query'])) {
+        parse_str($parsed1['query'], $params1);
+    }
+    if (!empty($parsed2['query'])) {
+        parse_str($parsed2['query'], $params2);
+    }
+
+    return $params1 == $params2;
+}
+
+// isch das total behindert und komplett losti ahgangs wiihs ? ja ... aber es funktioniert leider echt kei bock meh fr fr die grüene sind schuld
+function get_sidebar($db, $position, $page, $sub) {
+    $query = $db->prepare('
+        SELECT title, link, link_text
+        FROM sidebar
+        WHERE position = :position
+        ORDER BY id
+    ');
+    $query->bindValue(':position', $position, SQLITE3_TEXT);
+    $result = $query->execute();
+
+    if (!$result || !$result->fetchArray(SQLITE3_ASSOC)) {
+        return; // effizienz versuech will die ganz funktion müll isch ach mannn 😭
+    }
+    $result->reset();
+    $lastTitle = "";
+    // Bob der baumeister spileh und $activeLink zemme bastle
+    $queryString = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY) ?? ''; // luege das ned null isch will susch motzts
+    parse_str($queryString, $queryParams);
+
+    $activeParts = ["?page=" . ($queryParams['page'] ?? '')];
+    if (!empty($queryParams['sub'])) {
+        if (is_array($queryParams['sub'])) {
+            foreach ($queryParams['sub'] as $subParam) {
+                $activeParts[] = "sub=" . $subParam;
+            }
+        } else {
+            $activeParts[] = "sub=" . $queryParams['sub'];
+        }
+    }
+    $activeLink = implode("&", $activeParts);
+
+    $foundActive = false;
+
+    while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
+        // new post oh mein gott so spannend mached mer grad neue title
+        if ($row['title'] !== $lastTitle) {
+            if ($lastTitle !== "") {
+                echo '</div>';
+            }
+            echo '<div class="box"><h3>' . htmlspecialchars($row['title']) . '</h3>';
+            $lastTitle = $row['title'];
+        }
+
+        // externi links z'erchäne wär inteligent schickiert
+        if (filter_var($row['link'], FILTER_VALIDATE_URL)) {
+            echo '<p><a href="'
+                 . htmlspecialchars($row['link'])
+                 . '" target="_blank">'
+                 . htmlspecialchars($row['link_text'])
+                 . '</a></p>';
+        } else {
+            // robuster mache und so lönd mich ihn rueh
+            $activeClass = '';
+            if (!$foundActive && sameQueryParams($row['link'], $activeLink)) {
+                $activeClass = 'active';
+                $foundActive = true;
+            }
+
+            echo '<p><a href="'
+                 . htmlspecialchars($row['link'], ENT_QUOTES, 'UTF-8')
+                 . '" class="' . $activeClass . '">'
+                 . htmlspecialchars($row['link_text'])
+                 . '</a></p>';
+        }
+    }
+    if ($lastTitle !== "") {
+        echo '</div>';
+    }
+}
+?>

+ 98 - 0
common/navbar.php

@@ -0,0 +1,98 @@
+<?php
+if ($navbarTableExists && $navbarHasEntries) {
+    // Fetch navbar items from the database and render them for nicht behindertes navbar ohni js <3
+    $navbarItems = [];
+    $navbarResult = $db->query("SELECT * FROM navbar ORDER BY id");
+    while ($row = $navbarResult->fetchArray(SQLITE3_ASSOC)) {
+        $navbarItems[] = $row;
+    }
+
+    // Function to render the navbar items im grosse navbar für normali mensche
+    function render_navbar($items, $currentPage) {
+        $leftItems = array_filter($items, fn($item) => $item['align'] === 'left');
+        $centerItems = array_filter($items, fn($item) => $item['align'] === 'center');
+        $rightItems = array_filter($items, fn($item) => $item['align'] === 'right');
+
+        echo '<div class="navbar-left">';
+        render_navbar_items($leftItems, $currentPage);
+        echo '</div>';
+        echo '<div class="navbar-center">';
+        render_navbar_items($centerItems, $currentPage);
+        echo '</div>';
+        echo '<div class="navbar-right">';
+        render_navbar_items($rightItems, $currentPage);
+        echo '</div>';
+    }
+
+    function render_navbar_items($items, $currentPage) {
+        foreach ($items as $item) {
+            $activeClass = ($item['link'] == "?page=$currentPage") ? ' class="active"' : '';
+            switch ($item['type']) {
+                case 'title':
+                    echo '<span class="navbar-title">' . htmlspecialchars($item['name']) . '</span>';
+                    break;
+                case 'link':
+                    echo '<a href="' . htmlspecialchars($item['link']) . '"' . $activeClass . '>' . htmlspecialchars($item['name']) . '</a>';
+                    break;
+                case 'drop down':
+                    echo '<div class="navbar-dropdown">';
+                    echo '<a class="navbar-dropbtn" href="#">' . htmlspecialchars($item['name']) . '</a>';
+                    echo '<div class="navbar-dropdown-content">';
+                    foreach ($items as $dropdownItem) {
+                        if ($dropdownItem['type'] === 'drop down entry' && $dropdownItem['name'] === $item['name']) {
+                            echo '<a href="' . htmlspecialchars($dropdownItem['link']) . '">' . htmlspecialchars($dropdownItem['link_text']) . '</a>';
+                        }
+                    }
+                    echo '</div>';
+                    echo '</div>';
+                    break;
+                case 'text field':
+                    echo '<input type="text" placeholder="' . htmlspecialchars($item['name']) . '">';
+                    break;
+                case 'button':
+                    echo '<button onclick="location.href=\'' . htmlspecialchars($item['link']) . '\'">' . htmlspecialchars($item['name']) . '</button>';
+                    break;
+                case 'custom':
+                    echo $item['link_text'];
+                    break;
+                case 'logo':
+                    echo '<img src="' . htmlspecialchars($item['link']) . '" alt="' . htmlspecialchars($item['name']) . '" class="navbar-logo">';
+                    break;
+                case 'search':
+                    echo '<input type="search" placeholder="' . htmlspecialchars($item['name']) . '">';
+                    break;
+            }
+        }
+    }
+
+    // Function to render the mobile navbar für behindertes hamburger menu
+    function render_mobile_navbar($items, $menuExpanded) {
+        echo '<div class="mobile-navbar-panel">';
+        echo '<div class="navbar-header">';
+
+        foreach ($items as $item) {
+            if ($item['type'] === 'logo') {
+                echo '<img src="' . htmlspecialchars($item['link']) . '" alt="' . htmlspecialchars($item['name']) . '" class="navbar-logo">';
+            }
+            if ($item['type'] === 'title') {
+                echo '<span class="navbar-title">' . htmlspecialchars($item['name']) . '</span>';
+            }
+        }
+
+        $toggleState = $menuExpanded ? 0 : 1;
+        echo '<form method="get" action="" style="display:inline;">';
+        echo '<input type="hidden" name="menu" value="' . $toggleState . '">';
+        echo '<button type="submit" class="navbar-toggle">' . ($menuExpanded ? 'Collapse' : 'Expand') . '</button>';
+        echo '</form>';
+        echo '</div>';
+        echo '</div>';
+
+        // Separate the menu from the navbar panel will mir ned ganz normali mensche sind und euses menu mit post uf und zue gaht
+        if ($menuExpanded) {
+            echo '<div class="mobile-navbar-menu">';
+            render_navbar_items(array_filter($items, fn($item) => $item['type'] !== 'logo' && $item['type'] !== 'title'), '');
+            echo '</div>';
+        }
+    }
+}
+?>

+ 151 - 0
common/navbarjs.php

@@ -0,0 +1,151 @@
+<?php
+function render_navbar_js($db) {
+    // Fetch navbar items from the database and render them for behindertes dreckiges js navbar ... ich bin mal fullstack php dev gsi vor 5 jahr und jetzt machi das hier... 🤡
+    $navbarQuery = $db->query("SELECT * FROM navbar ORDER BY id");
+    $navbarItems = [];
+    while ($row = $navbarQuery->fetchArray(SQLITE3_ASSOC)) {
+        $navbarItems[] = $row;
+    }
+
+    echo '<nav class="navbar">';
+    echo '<div class="navbar-container">';
+    echo '<div class="navbar-left">';
+    foreach ($navbarItems as $item) {
+        $link = htmlspecialchars($item['link'] ?? '', ENT_QUOTES, 'UTF-8');
+        $name = htmlspecialchars($item['name'] ?? '', ENT_QUOTES, 'UTF-8');
+
+        if ($item['type'] === 'logo') {
+            echo '<img class="navbar-logo" src="' . $link . '" alt="' . $name . '">';
+        } elseif ($item['type'] === 'title') {
+            echo '<a href="index.php" class="navbar-title">' . $name . '</a>';
+        } elseif ($item['align'] === 'left' && $item['type'] === 'link') {
+            echo '<a class="navbar-link" href="' . $link . '">' . $name . '</a>';
+        } elseif ($item['align'] === 'left' && $item['type'] === 'button') {
+            echo '<button class="buttonify" onclick="location.href=\'' . $link . '\'">' . $name . '</button>';
+        } elseif ($item['align'] === 'left' && $item['type'] === 'text field') {
+            echo '<input type="text" placeholder="' . $name . '">';
+        } elseif ($item['align'] === 'left' && $item['type'] === 'search') {
+            echo '<input type="search" placeholder="' . $name . '">';
+        } elseif ($item['align'] === 'left' && $item['type'] === 'drop down') {
+            echo '<div class="navbar-dropdown">';
+            echo '<button class="navbar-dropbtn" onclick="location.href=\'' . $link . '\'">' . $name . '</button>';
+            echo '<div class="navbar-dropdown-content">';
+            foreach ($navbarItems as $dropdownItem) {
+                if ($dropdownItem['type'] === 'drop down entry' && $dropdownItem['name'] === $item['name']) {
+                    $dropdownLink = htmlspecialchars($dropdownItem['link'] ?? '', ENT_QUOTES, 'UTF-8');
+                    $dropdownLinkText = htmlspecialchars($dropdownItem['link_text'] ?? '', ENT_QUOTES, 'UTF-8');
+                    echo '<a class="dropdown-link" href="' . $dropdownLink . '">' . $dropdownLinkText . '</a>';
+                }
+            }
+            echo '</div>';
+            echo '</div>';
+        }
+    }
+    echo '</div>';
+
+    echo '<div class="navbar-center">';
+    foreach ($navbarItems as $item) {
+        $link = htmlspecialchars($item['link'] ?? '', ENT_QUOTES, 'UTF-8');
+        $name = htmlspecialchars($item['name'] ?? '', ENT_QUOTES, 'UTF-8');
+
+        if ($item['align'] === 'center') {
+            if ($item['type'] === 'link') {
+                echo '<a class="navbar-link" href="' . $link . '">' . $name . '</a>';
+            } elseif ($item['type'] === 'button') {
+                echo '<button class="buttonify" onclick="location.href=\'' . $link . '\'">' . $name . '</button>';
+            } elseif ($item['type'] === 'text field') {
+                echo '<input type="text" placeholder="' . $name . '">';
+            } elseif ($item['type'] === 'search') {
+                echo '<input type="search" placeholder="' . $name . '">';
+            } elseif ($item['type'] === 'drop down') {
+                echo '<div class="navbar-dropdown">';
+                echo '<button class="navbar-dropbtn" onclick="location.href=\'' . $link . '\'">' . $name . '</button>';
+                echo '<div class="navbar-dropdown-content">';
+                foreach ($navbarItems as $dropdownItem) {
+                    if ($dropdownItem['type'] === 'drop down entry' && $dropdownItem['name'] === $item['name']) {
+                        $dropdownLink = htmlspecialchars($dropdownItem['link'] ?? '', ENT_QUOTES, 'UTF-8');
+                        $dropdownLinkText = htmlspecialchars($dropdownItem['link_text'] ?? '', ENT_QUOTES, 'UTF-8');
+                        echo '<a class="dropdown-link" href="' . $dropdownLink . '">' . $dropdownLinkText . '</a>';
+                    }
+                }
+                echo '</div>';
+                echo '</div>';
+            }
+        }
+    }
+    echo '</div>';
+
+    echo '<div class="navbar-right">';
+    foreach ($navbarItems as $item) {
+        $link = htmlspecialchars($item['link'] ?? '', ENT_QUOTES, 'UTF-8');
+        $name = htmlspecialchars($item['name'] ?? '', ENT_QUOTES, 'UTF-8');
+
+        if ($item['align'] === 'right') {
+            if ($item['type'] === 'link') {
+                echo '<a class="navbar-link" href="' . $link . '">' . $name . '</a>';
+            } elseif ($item['type'] === 'button') {
+                echo '<button class="buttonify" onclick="location.href=\'' . $link . '\'">' . $name . '</button>';
+            } elseif ($item['type'] === 'text field') {
+                echo '<input type="text" placeholder="' . $name . '">';
+            } elseif ($item['type'] === 'search') {
+                echo '<input type="search" placeholder="' . $name . '">';
+            } elseif ($item['type'] === 'drop down') {
+                echo '<div class="navbar-dropdown">';
+                echo '<button class="navbar-dropbtn" onclick="location.href=\'' . $link . '\'">' . $name . '</button>';
+                echo '<div class="navbar-dropdown-content">';
+                foreach ($navbarItems as $dropdownItem) {
+                    if ($dropdownItem['type'] === 'drop down entry' && $dropdownItem['name'] === $item['name']) {
+                        $dropdownLink = htmlspecialchars($dropdownItem['link'] ?? '', ENT_QUOTES, 'UTF-8');
+                        $dropdownLinkText = htmlspecialchars($dropdownItem['link_text'] ?? '', ENT_QUOTES, 'UTF-8');
+                        echo '<a class="dropdown-link" href="' . $dropdownLink . '">' . $dropdownLinkText . '</a>';
+                    }
+                }
+                echo '</div>';
+                echo '</div>';
+            }
+        }
+    }
+    echo '</div>';
+    echo '</div>';
+
+    echo '<div class="navbar-mobile">';
+    echo '<div class="navbar-left">';
+    foreach ($navbarItems as $item) {
+        $link = htmlspecialchars($item['link'] ?? '', ENT_QUOTES, 'UTF-8');
+        $name = htmlspecialchars($item['name'] ?? '', ENT_QUOTES, 'UTF-8');
+
+        if ($item['type'] === 'logo') {
+            echo '<img class="navbar-logo" src="' . $link . '" alt="' . $name . '">';
+        } elseif ($item['type'] === 'title') {
+            echo '<a href="index.php" class="navbar-title">' . $name . '</a>';
+        }
+    }
+    echo '</div>';
+    echo '<button class="navbar-toggle" onclick="toggleNavbar()">☰</button>';
+    echo '</div>';
+
+    echo '<div class="mobile-navbar-menu">';
+    foreach ($navbarItems as $item) {
+        $link = htmlspecialchars($item['link'] ?? '', ENT_QUOTES, 'UTF-8');
+        $name = htmlspecialchars($item['name'] ?? '', ENT_QUOTES, 'UTF-8');
+
+        if ($item['type'] === 'link') {
+            echo '<a class="navbar-link bruh-why" href="' . $link . '">' . $name . '</a>';
+        } elseif ($item['type'] === 'drop down') {
+            echo '<span class="mobile-navbar-dropdown" onclick="location.href=\'' . $link . '\'">' . $name . '</span>';
+        } elseif ($item['type'] === 'drop down entry') {
+            $dropdownLink = htmlspecialchars($item['link'] ?? '', ENT_QUOTES, 'UTF-8');
+            $dropdownLinkText = htmlspecialchars($item['link_text'] ?? '', ENT_QUOTES, 'UTF-8');
+            echo '<a class="dropdown-link" href="' . $dropdownLink . '" class="mobile-dropdown-entry">↳ ' . $dropdownLinkText . '</a>';
+        } elseif ($item['type'] === 'button') {
+            echo '<button class="buttonify" onclick="location.href=\'' . $link . '\'">' . $name . '</button>';
+        } elseif ($item['type'] === 'text field') {
+            echo '<input type="text" placeholder="' . $name . '">';
+        } elseif ($item['type'] === 'search') {
+            echo '<input type="search" placeholder="' . $name . '">';
+        }
+    }
+    echo '</div>';
+    echo '</nav>';
+}
+?>

+ 48 - 0
config.php

@@ -0,0 +1,48 @@
+<?php
+return [
+    [
+        'id' => 1,
+        'name' => 'Demo Site 1 Sidebar : einfach geil',
+        'database' => __DIR__ . '/website/content.db',
+        'folder' => 'website',
+        'backup_folder' => 'dbbackups/website',
+        'components' => [
+            __DIR__ . '/common/functions.php',
+            __DIR__ . '/common/navbar.php',
+        ],
+    ],
+    [
+        'id' => 2,
+        'name' => 'Dome Site 2 Navbar : fick geil jaman"',
+        'database' => __DIR__ . '/website2/content2.db',
+        'folder' => 'website2',
+        'backup_folder' => 'dbbackups/website2',
+        'components' => [
+            __DIR__ . '/common/functions.php',
+            __DIR__ . '/common/navbar.php',
+        ],
+    ],    
+    [
+        'id' => 3,
+        'name' => 'Dome Site 3 Navbar w JS : geh kotzen',
+        'database' => __DIR__ . '/website3/content3.db',
+        'folder' => 'website3',
+        'backup_folder' => 'dbbackups/website3',
+        'components' => [
+            __DIR__ . '/common/functions.php',
+            __DIR__ . '/common/navbarjs.php',
+        ],
+    ],
+    [
+        'id' => 4,
+        'name' => 'Demo Site 4 Sidebar w JS flatterschiss',
+        'database' => __DIR__ . '/website4/content4.db',
+        'folder' => 'website4',
+        'backup_folder' => 'dbbackups/website4',
+        'components' => [
+            __DIR__ . '/common/functions.php',
+            __DIR__ . '/common/navbarjs.php',
+        ],
+    ]
+];
+?>

BIN
website/.DS_Store


BIN
website/content.db


BIN
website/public/assets/.DS_Store


+ 452 - 0
website/public/assets/css/tc.css

@@ -0,0 +1,452 @@
+html, body {
+    height: 100%;
+    margin: 0;
+    padding: 0;
+    font-family: Arial, sans-serif;
+    background-color: #FFFFFF;
+    color: #000000;
+    display: flex;
+    flex-direction: column;
+    overflow-x: hidden;
+}
+
+header {
+    text-align: center;
+    background-color: #FFFFFF;
+    color: #FFFFFF;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.header-content {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: #FFFFFF;
+    padding: 10px 20px;
+    padding-top: 15px;
+}
+
+header h1 {
+    margin: 0;
+    font-size: 24px;
+    margin-left: 10px;
+    color: #D22627;
+}
+
+header h2 {
+    margin: 5px 0 0 0;
+    font-size: 16px;
+    text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.6);
+}
+
+.logo {
+    height: 40px;
+    width: auto;
+}
+
+.container {
+    flex: 1;
+    display: flex;
+    width: 100%;
+    min-width: 300px;
+    align-items: flex-start;
+    flex-wrap: wrap;
+    margin: 20px auto;
+    margin-top: 0px;
+    margin-bottom: 0px;
+    max-width: 1200px;
+}
+
+.sidebar, .sidebar-right {
+    width: 20%; min-width: 200px; max-width: 250px;
+    padding: 10px;
+    padding-bottom: 0px;
+    background-color: #FFEEEE;
+    border: 1px solid #D22627;
+    box-sizing: border-box;
+    display: block; align-self: flex-start;
+}
+
+.content {
+    width: 60%;
+    flex-grow: 1;
+    padding: 10px;
+    box-sizing: border-box;
+}
+
+.box {
+    margin-bottom: 10px;
+    padding: 10px;
+    border: 1px solid #D22627;
+    background-color: #FFFFFF;
+}
+
+.box-last {
+    margin-bottom: 0px;
+}
+
+.box h3 {
+    margin: 0 0 10px 0;
+    font-size: 16px;
+    color: #D22627;
+}
+
+.box p, .box a {
+    margin: 5px 0;
+    font-size: 14px;
+    color: #000000;
+}
+
+.box a {
+    color: #D22627;
+    text-decoration: none;
+}
+
+.box a:hover {
+    text-decoration: underline;
+}
+
+footer {
+    background-color: #D22627;
+    color: #FFFFFF;
+    text-align: center;
+    padding: 10px 0;
+    font-size: 14px;
+    width: 100%;
+    flex-shrink: 0;
+}
+
+.navbar {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    background-color: #D22627;
+    padding: 10px;
+    color: #FFFFFF;
+}
+
+.navbar-left, .navbar-center, .navbar-right {
+    display: flex;
+    align-items: center;
+}
+
+.navbar-left {
+    justify-content: flex-start;
+    flex: 1; 
+}
+
+.navbar-center {
+    justify-content: center;
+    flex-grow: 1;
+    flex: 2; 
+}
+
+.navbar-right {
+    justify-content: flex-end;
+    flex: 1; 
+}
+
+.navbar a, .navbar span, .navbar input, .navbar img {
+    margin: 0 10px;
+    color: #FFFFFF;
+    text-decoration: none;
+}
+
+.navbar button {
+    margin: 0 10px;
+    color: #000000;
+    text-decoration: none;
+}
+
+.navbar a:hover, .navbar button:hover {
+    text-decoration: underline;
+}
+
+.navbar-logo {
+    height: 40px;
+    width: auto;
+}
+
+.navbar-dropdown {
+    position: relative;
+    color: #ffffff;
+    display: inline-block;
+}
+
+.navbar-dropbtn {
+    background-color: #D22627;
+    color: white;
+    border: none;
+    cursor: pointer;
+}
+
+.navbar-dropdown-content {
+    display: none;
+    position: absolute;
+    background-color: #f9f9f9;
+    min-width: 160px;
+    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
+    z-index: 1;
+}
+
+.navbar-dropdown-content a {
+    color: black;
+    padding: 12px 16px;
+    text-decoration: none;
+    display: block;
+}
+
+.navbar-dropdown-content a:hover {
+    background-color: #f1f1f1;
+}
+
+.navbar-dropdown:hover .navbar-dropdown-content {
+    display: block;
+}
+
+.navbar-dropdown:hover .navbar-dropbtn {
+    background-color: #a10000;
+}
+
+.mobile-navbar {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    background-color: #D22627;
+    color: #FFFFFF;
+    width: 100%;
+    padding: 10px;
+}
+
+.mobile-navbar-panel {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+    background-color: #D22627;
+    color: #FFFFFF;
+    width: 100%;
+    padding: 10px;
+    gap: 10px;
+}
+
+.mobile-navbar-panel .navbar-header {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+    width: 100%;
+}
+
+.mobile-navbar-panel .navbar-logo, .mobile-navbar-panel .navbar-title {
+    display: inline-block;
+    vertical-align: middle;
+}
+
+.mobile-navbar-panel .navbar-toggle {
+    display: inline-block;
+    cursor: pointer;
+}
+
+.mobile-navbar-panel .navbar-toggle::after {
+    content: ' ▼';
+}
+
+.mobile-navbar-menu {
+    display: flex;
+    flex-direction: column;
+    width: 100%;
+    background-color: #D22627;
+    text-align: center;
+    align-items: center;
+    padding: 10px;
+    box-sizing: border-box;
+}
+
+.mobile-navbar-menu a, 
+.mobile-navbar-menu span, 
+.mobile-navbar-menu input, 
+.mobile-navbar-menu button {
+    display: block;
+    padding: 10px;
+    border-bottom: 1px solid #FFFFFF;
+    text-align: center;
+    width: 80vw;
+    box-sizing: border-box;
+    margin: 0;
+}
+
+.mobile-navbar-menu a:hover, 
+.mobile-navbar-menu button:hover {
+    background-color: #a10000;
+}
+
+.mobile-navbar-menu button {
+    text-align: center;
+    width: 80vw;
+    margin: 0 auto;
+    display: block;
+}
+
+input[type="checkbox"] {
+    display: none;
+}
+
+input[type="checkbox"]:checked ~ .mobile-navbar-items {
+    display: block;
+}
+
+@media screen and (max-width: 1279px) {
+    .container {
+        flex-direction: column;
+        padding: 10px;
+        padding-top: 0px;
+        padding-bottom: 0px;
+        width: 100%;
+        min-width: auto;
+        box-sizing: border-box;
+    }
+
+    .sidebar, .sidebar-right, .content {
+        width: 100%;
+        min-width: auto;
+        max-width: none;
+        flex-grow: 0;
+        margin-bottom: 20px;
+    }
+
+    .header-content {
+        padding-top: 10px;
+    }
+
+    header h1 {
+        font-size: 20px;
+    }
+
+    header h2 {
+        font-size: 14px;
+    }
+
+    .box h3 {
+        font-size: 16px;
+    }
+
+    .box p, .box a {
+        font-size: 12px;
+    }
+
+    footer {
+        font-size: 12px;
+        padding: 5px;
+    }
+
+    .navbar {
+        display: none;
+    }
+
+    .mobile-navbar {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        background-color: #D22627;
+        padding: 10px;
+        color: #FFFFFF;
+        width: 100%;
+    }
+
+    .mobile-navbar .navbar-header {
+        display: flex;
+        justify-content: space-between;
+        width: 100%;
+        align-items: center;
+    }
+
+    .mobile-navbar .navbar-logo, .mobile-navbar .navbar-title {
+        display: inline-block;
+        vertical-align: middle;
+    }
+
+    .mobile-navbar .navbar-toggle {
+        display: inline-block;
+        cursor: pointer;
+    }
+
+    .mobile-navbar .navbar-toggle::after {
+        content: ' ▼';
+    }
+
+    .mobile-navbar-items {
+        display: flex;
+        flex-direction: column;
+        width: 100%;
+        background-color: #D22627;
+        text-align: center;
+        align-items: center;
+    }
+
+    .mobile-navbar-items a, 
+    .mobile-navbar-items span, 
+    .mobile-navbar-items input, 
+    .mobile-navbar-items button {
+        display: block;
+        padding: 10px;
+        border-bottom: 1px solid #FFFFFF;
+        text-align: center;
+        width: 80vw;
+        box-sizing: border-box;
+        margin: 0;
+    }
+
+    .mobile-navbar-items a:hover, 
+    .mobile-navbar-items button:hover {
+        background-color: #3e8e41;
+    }
+
+    .mobile-navbar-items button {
+        text-align: center;
+        width: 80vw;
+        margin: 0 auto;
+        display: block;
+    }
+
+    input[type="checkbox"] {
+        display: none;
+    }
+
+    input[type="checkbox"]:checked ~ .mobile-navbar-items {
+        display: block;
+    }
+}
+
+@media screen and (min-width: 1280px) {
+    .container {
+        width: 100%;
+        min-width: 300px;
+    }
+
+    .sidebar, .sidebar-right {
+        width: 20%;
+        min-width: 200px;
+        max-width: 250px;
+    }
+
+    .content {
+        width: 60%;
+        flex-grow: 1;
+    }
+
+    .mobile-navbar, .mobile-navbar-panel, .mobile-navbar-menu {
+        display: none;
+    }
+}
+
+.breadcrumbs {
+    margin-bottom: 10px;
+    padding: 10px;
+    border: 1px solid #D22627;
+    background-color: #FFFFFF;
+}
+
+.sidebar a.active, .sidebar-right a.active {
+    text-decoration: underline;
+}

BIN
website/public/assets/img/.DS_Store


BIN
website/public/assets/img/code-is-ass.jpeg


BIN
website/public/assets/img/dialon.png


BIN
website/public/assets/img/force.png


BIN
website/public/assets/img/fuck-main.jpeg


BIN
website/public/assets/img/fuckjs.jpeg


BIN
website/public/assets/img/jsmomentom.jpg


BIN
website/public/assets/img/router1.jpg


BIN
website/public/assets/img/router2.jpg


BIN
website/public/assets/img/rover.png


BIN
website/public/assets/img/ssc.jpg


BIN
website/public/assets/img/wrong.png


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 16 - 0
website/public/assets/svg/teleco.svg


+ 121 - 0
website/public/index.php

@@ -0,0 +1,121 @@
+<?php
+
+// Load configuration
+$config = include(__DIR__ . '/../../config.php');
+
+// Define the ID of this site
+$siteId = 1;
+
+// Find the website configuration
+$websiteConfig = array_filter($config, function($site) use ($siteId) {
+    return isset($site['id']) && $site['id'] === $siteId;
+});
+$websiteConfig = reset($websiteConfig);
+
+// Include components
+foreach ($websiteConfig['components'] as $component) {
+    include($component);
+}
+
+?>
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Teleco.ch - <?php echo ucfirst($page); ?></title>
+    <meta name="description" content="<?php echo $metaDescription; ?>">
+    <link rel="stylesheet" href="assets/css/tc.css">
+</head>
+<body>
+    <header>
+        <div class="header-content" <?php if ($navbarTableExists && $navbarHasEntries) echo 'style="display:none;"'; ?>>
+            <img src="assets/svg/teleco.svg" alt="Teleco Logo" class="logo">
+            <h1>Teleco.ch</h1>
+        </div>
+    </header>
+    
+    <?php if ($navbarTableExists && $navbarHasEntries): ?>
+        <nav class="navbar">
+            <?php render_navbar($navbarItems, $page); ?>
+        </nav>
+        <?php render_mobile_navbar($navbarItems, $menuExpanded); ?>
+    <?php endif; ?>
+    <hr>
+
+    <div class="container" style="<?php echo $leftSidebarHasItems || $rightSidebarHasItems ? '' : 'margin-left: 0px; margin-right: 0px; flex-wrap: nowrap; margin-top: 0px; margin-bottom: 0px; max-width: 100%; box-sizing: border-box; padding: 10px;'; ?>">
+        <!-- Left Sidebar -->
+        <?php if ($leftSidebarHasItems): ?>
+            <div class="sidebar">
+                <?php get_sidebar($db, 'left', $page, $sub); ?>
+            </div>
+        <?php endif; ?>
+
+        <!-- Main Content -->
+        <div class="content" id="content" style="<?php echo $leftSidebarHasItems || $rightSidebarHasItems ? '' : 'width: calc(100%);'; ?>">
+            <!-- Comment indicating if left elements were detected -->
+                 <!-- Breadcrumbs -->
+    <div class="breadcrumbs">
+        <?php
+foreach ($breadcrumbs as $index => $crumb) {
+    if ($index > 0) echo ' > ';
+    echo '<a href="?page=' . htmlspecialchars($crumb['page']) . '">';
+    echo htmlspecialchars($crumb['title']);
+    echo '</a>';
+}
+        ?>
+    </div>
+            <?php if ($leftSidebarHasItems): ?>
+                <!-- Left sidebar elements detected -->
+            <?php else: ?>
+                <!-- No left sidebar elements detected -->
+            <?php endif; ?>
+            <?php if ($hasContent): ?>
+                <?php
+                $result = $query->execute();
+                $lastPostId = 0;
+                while ($row = $result->fetchArray()):
+                    $lastPostId++;
+                ?>
+                    <div class="box" id="post-<?php echo $lastPostId; ?>">
+                        <h3><?php echo htmlspecialchars($row['title']); ?></h3>
+                        <p><?php echo $row['content']; ?></p> <!-- Always render content as HTML -->
+                        <hr>
+                        <p>Date: <?php echo $row['date']; ?></p>
+                    </div>
+                <?php endwhile; ?>
+            <?php else: ?>
+                <div class="box">
+                    <h3>404 - Page Not Found</h3>
+                    <p>Sorry, the page you are looking for does not exist.</p>
+                </div>
+            <?php endif; ?>
+
+            <div id="load-container">
+    <?php if ($hasContent && $offset + $limit < $totalPosts): ?>
+        <form method="get" action="index.php#post-<?php echo $lastPostId; ?>">
+            <input type="hidden" name="page" value="<?php echo htmlspecialchars($page); ?>">
+            <?php if ($sub): ?>
+                <input type="hidden" name="sub" value="<?php echo htmlspecialchars($sub); ?>">
+            <?php endif; ?>
+            <input type="hidden" name="offset" value="<?php echo $offset + $limit; ?>">
+            <button type="submit">Load More (<?php echo min($offset + $limit, $totalPosts) . " out of " . $totalPosts; ?>)</button>
+        </form>
+    <?php endif; ?>
+</div>
+        </div>
+        
+        <!-- Right Sidebar -->
+        <?php if ($rightSidebarHasItems): ?>
+            <div class="sidebar-right">
+                <?php get_sidebar($db, 'right', $page, $sub); ?>
+            </div>
+        <?php endif; ?>
+    </div>
+    
+    <footer>
+        &copy; 2025 Teleco.ch. All Rights Reserved.
+    </footer>
+</body>
+</html>

BIN
website2/.DS_Store


BIN
website2/content2.db


BIN
website2/public/assets/.DS_Store


+ 452 - 0
website2/public/assets/css/tc.css

@@ -0,0 +1,452 @@
+html, body {
+    height: 100%;
+    margin: 0;
+    padding: 0;
+    font-family: Arial, sans-serif;
+    background-color: #FFFFFF;
+    color: #000000;
+    display: flex;
+    flex-direction: column;
+    overflow-x: hidden;
+}
+
+header {
+    text-align: center;
+    background-color: #FFFFFF;
+    color: #FFFFFF;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.header-content {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: #FFFFFF;
+    padding: 10px 20px;
+    padding-top: 15px;
+}
+
+header h1 {
+    margin: 0;
+    font-size: 24px;
+    margin-left: 10px;
+    color: #D22627;
+}
+
+header h2 {
+    margin: 5px 0 0 0;
+    font-size: 16px;
+    text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.6);
+}
+
+.logo {
+    height: 40px;
+    width: auto;
+}
+
+.container {
+    flex: 1;
+    display: flex;
+    width: 100%;
+    min-width: 300px;
+    align-items: flex-start;
+    flex-wrap: wrap;
+    margin: 20px auto;
+    margin-top: 0px;
+    margin-bottom: 0px;
+    max-width: 1200px;
+}
+
+.sidebar, .sidebar-right {
+    width: 20%; min-width: 200px; max-width: 250px;
+    padding: 10px;
+    padding-bottom: 0px;
+    background-color: #FFEEEE;
+    border: 1px solid #D22627;
+    box-sizing: border-box;
+    display: block; align-self: flex-start;
+}
+
+.content {
+    width: 60%;
+    flex-grow: 1;
+    padding: 10px;
+    box-sizing: border-box;
+}
+
+.box {
+    margin-bottom: 10px;
+    padding: 10px;
+    border: 1px solid #D22627;
+    background-color: #FFFFFF;
+}
+
+.box-last {
+    margin-bottom: 0px;
+}
+
+.box h3 {
+    margin: 0 0 10px 0;
+    font-size: 16px;
+    color: #D22627;
+}
+
+.box p, .box a {
+    margin: 5px 0;
+    font-size: 14px;
+    color: #000000;
+}
+
+.box a {
+    color: #D22627;
+    text-decoration: none;
+}
+
+.box a:hover {
+    text-decoration: underline;
+}
+
+footer {
+    background-color: #D22627;
+    color: #FFFFFF;
+    text-align: center;
+    padding: 10px 0;
+    font-size: 14px;
+    width: 100%;
+    flex-shrink: 0;
+}
+
+.navbar {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    background-color: #D22627;
+    padding: 10px;
+    color: #FFFFFF;
+}
+
+.navbar-left, .navbar-center, .navbar-right {
+    display: flex;
+    align-items: center;
+}
+
+.navbar-left {
+    justify-content: flex-start;
+    flex: 1; 
+}
+
+.navbar-center {
+    justify-content: center;
+    flex-grow: 1;
+    flex: 2; 
+}
+
+.navbar-right {
+    justify-content: flex-end;
+    flex: 1; 
+}
+
+.navbar a, .navbar span, .navbar input, .navbar img {
+    margin: 0 10px;
+    color: #FFFFFF;
+    text-decoration: none;
+}
+
+.navbar button {
+    margin: 0 10px;
+    color: #000000;
+    text-decoration: none;
+}
+
+.navbar a:hover, .navbar button:hover {
+    text-decoration: underline;
+}
+
+.navbar-logo {
+    height: 40px;
+    width: auto;
+}
+
+.navbar-dropdown {
+    position: relative;
+    color: #ffffff;
+    display: inline-block;
+}
+
+.navbar-dropbtn {
+    background-color: #D22627;
+    color: white;
+    border: none;
+    cursor: pointer;
+}
+
+.navbar-dropdown-content {
+    display: none;
+    position: absolute;
+    background-color: #f9f9f9;
+    min-width: 160px;
+    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
+    z-index: 1;
+}
+
+.navbar-dropdown-content a {
+    color: black;
+    padding: 12px 16px;
+    text-decoration: none;
+    display: block;
+}
+
+.navbar-dropdown-content a:hover {
+    background-color: #f1f1f1;
+}
+
+.navbar-dropdown:hover .navbar-dropdown-content {
+    display: block;
+}
+
+.navbar-dropdown:hover .navbar-dropbtn {
+    background-color: #a10000;
+}
+
+.mobile-navbar {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    background-color: #D22627;
+    color: #FFFFFF;
+    width: 100%;
+    padding: 10px;
+}
+
+.mobile-navbar-panel {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+    background-color: #D22627;
+    color: #FFFFFF;
+    width: 100%;
+    padding: 10px;
+    gap: 10px;
+}
+
+.mobile-navbar-panel .navbar-header {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+    width: 100%;
+}
+
+.mobile-navbar-panel .navbar-logo, .mobile-navbar-panel .navbar-title {
+    display: inline-block;
+    vertical-align: middle;
+}
+
+.mobile-navbar-panel .navbar-toggle {
+    display: inline-block;
+    cursor: pointer;
+}
+
+.mobile-navbar-panel .navbar-toggle::after {
+    content: ' ▼';
+}
+
+.mobile-navbar-menu {
+    display: flex;
+    flex-direction: column;
+    width: 100%;
+    background-color: #D22627;
+    text-align: center;
+    align-items: center;
+    padding: 10px;
+    box-sizing: border-box;
+}
+
+.mobile-navbar-menu a, 
+.mobile-navbar-menu span, 
+.mobile-navbar-menu input, 
+.mobile-navbar-menu button {
+    display: block;
+    padding: 10px;
+    border-bottom: 1px solid #FFFFFF;
+    text-align: center;
+    width: 80vw;
+    box-sizing: border-box;
+    margin: 0;
+}
+
+.mobile-navbar-menu a:hover, 
+.mobile-navbar-menu button:hover {
+    background-color: #a10000;
+}
+
+.mobile-navbar-menu button {
+    text-align: center;
+    width: 80vw;
+    margin: 0 auto;
+    display: block;
+}
+
+input[type="checkbox"] {
+    display: none;
+}
+
+input[type="checkbox"]:checked ~ .mobile-navbar-items {
+    display: block;
+}
+
+@media screen and (max-width: 1279px) {
+    .container {
+        flex-direction: column;
+        padding: 10px;
+        padding-top: 0px;
+        padding-bottom: 0px;
+        width: 100%;
+        min-width: auto;
+        box-sizing: border-box;
+    }
+
+    .sidebar, .sidebar-right, .content {
+        width: 100%;
+        min-width: auto;
+        max-width: none;
+        flex-grow: 0;
+        margin-bottom: 20px;
+    }
+
+    .header-content {
+        padding-top: 10px;
+    }
+
+    header h1 {
+        font-size: 20px;
+    }
+
+    header h2 {
+        font-size: 14px;
+    }
+
+    .box h3 {
+        font-size: 16px;
+    }
+
+    .box p, .box a {
+        font-size: 12px;
+    }
+
+    footer {
+        font-size: 12px;
+        padding: 5px;
+    }
+
+    .navbar {
+        display: none;
+    }
+
+    .mobile-navbar {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        background-color: #D22627;
+        padding: 10px;
+        color: #FFFFFF;
+        width: 100%;
+    }
+
+    .mobile-navbar .navbar-header {
+        display: flex;
+        justify-content: space-between;
+        width: 100%;
+        align-items: center;
+    }
+
+    .mobile-navbar .navbar-logo, .mobile-navbar .navbar-title {
+        display: inline-block;
+        vertical-align: middle;
+    }
+
+    .mobile-navbar .navbar-toggle {
+        display: inline-block;
+        cursor: pointer;
+    }
+
+    .mobile-navbar .navbar-toggle::after {
+        content: ' ▼';
+    }
+
+    .mobile-navbar-items {
+        display: flex;
+        flex-direction: column;
+        width: 100%;
+        background-color: #D22627;
+        text-align: center;
+        align-items: center;
+    }
+
+    .mobile-navbar-items a, 
+    .mobile-navbar-items span, 
+    .mobile-navbar-items input, 
+    .mobile-navbar-items button {
+        display: block;
+        padding: 10px;
+        border-bottom: 1px solid #FFFFFF;
+        text-align: center;
+        width: 80vw;
+        box-sizing: border-box;
+        margin: 0;
+    }
+
+    .mobile-navbar-items a:hover, 
+    .mobile-navbar-items button:hover {
+        background-color: #3e8e41;
+    }
+
+    .mobile-navbar-items button {
+        text-align: center;
+        width: 80vw;
+        margin: 0 auto;
+        display: block;
+    }
+
+    input[type="checkbox"] {
+        display: none;
+    }
+
+    input[type="checkbox"]:checked ~ .mobile-navbar-items {
+        display: block;
+    }
+}
+
+@media screen and (min-width: 1280px) {
+    .container {
+        width: 100%;
+        min-width: 300px;
+    }
+
+    .sidebar, .sidebar-right {
+        width: 20%;
+        min-width: 200px;
+        max-width: 250px;
+    }
+
+    .content {
+        width: 60%;
+        flex-grow: 1;
+    }
+
+    .mobile-navbar, .mobile-navbar-panel, .mobile-navbar-menu {
+        display: none;
+    }
+}
+
+.breadcrumbs {
+    margin-bottom: 10px;
+    padding: 10px;
+    border: 1px solid #D22627;
+    background-color: #FFFFFF;
+}
+
+.sidebar a.active, .sidebar-right a.active {
+    text-decoration: underline;
+}

BIN
website2/public/assets/img/.DS_Store


BIN
website2/public/assets/img/code-is-ass.jpeg


BIN
website2/public/assets/img/dialon.png


BIN
website2/public/assets/img/force.png


BIN
website2/public/assets/img/fuck-main.jpeg


BIN
website2/public/assets/img/fuckjs.jpeg


BIN
website2/public/assets/img/jsmomentom.jpg


BIN
website2/public/assets/img/router1.jpg


BIN
website2/public/assets/img/router2.jpg


BIN
website2/public/assets/img/rover.png


BIN
website2/public/assets/img/ssc.jpg


BIN
website2/public/assets/img/wrong.png


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 16 - 0
website2/public/assets/svg/teleco.svg


+ 120 - 0
website2/public/index.php

@@ -0,0 +1,120 @@
+<?php
+// loads the config
+$config = include(__DIR__ . '/../../config.php');
+
+// go set your id here otehrwise ur site wont load the stuff it needs
+$siteId = 2;
+
+// website go search what stuffs it need to load
+$websiteConfig = array_filter($config, function($site) use ($siteId) {
+    return isset($site['id']) && $site['id'] === $siteId;
+});
+$websiteConfig = reset($websiteConfig);
+
+// include the components so the site actually gets rendered
+foreach ($websiteConfig['components'] as $component) {
+    include($component);
+}
+
+?>
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Teleco.ch - <?php echo ucfirst($page); ?></title>
+    <meta name="description" content="<?php echo $metaDescription; ?>">
+    <link rel="stylesheet" href="assets/css/tc.css">
+</head>
+<body>
+    <header>
+        <div class="header-content" <?php if ($navbarTableExists && $navbarHasEntries) echo 'style="display:none;"'; ?>>
+            <img src="assets/svg/teleco.svg" alt="Teleco Logo" class="logo">
+            <h1>Teleco.ch</h1>
+        </div>
+    </header>
+    
+    <?php if ($navbarTableExists && $navbarHasEntries): ?>
+        <nav class="navbar">
+            <?php render_navbar($navbarItems, $page); ?>
+        </nav>
+        <?php render_mobile_navbar($navbarItems, $menuExpanded); ?>
+    <?php endif; ?>
+    <hr>
+
+    <div class="container" style="<?php echo $leftSidebarHasItems || $rightSidebarHasItems ? '' : 'margin-left: 0px; margin-right: 0px; flex-wrap: nowrap; margin-top: 0px; margin-bottom: 0px; max-width: 100%; box-sizing: border-box; padding: 10px;'; ?>">
+        <!-- Left Sidebar -->
+        <?php if ($leftSidebarHasItems): ?>
+            <div class="sidebar">
+                <?php get_sidebar($db, 'left', $page, $sub); ?>
+            </div>
+        <?php endif; ?>
+
+        <!-- Main Content -->
+        <div class="content" id="content" style="<?php echo $leftSidebarHasItems || $rightSidebarHasItems ? '' : 'width: calc(100%);'; ?>">
+            <!-- Comment indicating if left elements were detected -->
+                 <!-- Breadcrumbs -->
+    <div class="breadcrumbs">
+        <?php
+foreach ($breadcrumbs as $index => $crumb) {
+    if ($index > 0) echo ' > ';
+    echo '<a href="?page=' . htmlspecialchars($crumb['page']) . '">';
+    echo htmlspecialchars($crumb['title']);
+    echo '</a>';
+}
+        ?>
+    </div>
+            <?php if ($leftSidebarHasItems): ?>
+                <!-- Left sidebar elements detected -->
+            <?php else: ?>
+                <!-- No left sidebar elements detected -->
+            <?php endif; ?>
+            <?php if ($hasContent): ?>
+                <?php
+                $result = $query->execute();
+                $lastPostId = 0;
+                while ($row = $result->fetchArray()):
+                    $lastPostId++;
+                ?>
+                    <div class="box" id="post-<?php echo $lastPostId; ?>">
+                        <h3><?php echo htmlspecialchars($row['title']); ?></h3>
+                        <p><?php echo $row['content']; ?></p> <!-- Always render content as HTML -->
+                        <hr>
+                        <p>Date: <?php echo $row['date']; ?></p>
+                    </div>
+                <?php endwhile; ?>
+            <?php else: ?>
+                <div class="box">
+                    <h3>404 - Page Not Found</h3>
+                    <p>Sorry, the page you are looking for does not exist.</p>
+                </div>
+            <?php endif; ?>
+
+            <div id="load-container">
+    <?php if ($hasContent && $offset + $limit < $totalPosts): ?>
+        <form method="get" action="index.php#post-<?php echo $lastPostId; ?>">
+            <input type="hidden" name="page" value="<?php echo htmlspecialchars($page); ?>">
+            <?php if ($sub): ?>
+                <input type="hidden" name="sub" value="<?php echo htmlspecialchars($sub); ?>">
+            <?php endif; ?>
+            <input type="hidden" name="offset" value="<?php echo $offset + $limit; ?>">
+            <button type="submit">Load More (<?php echo min($offset + $limit, $totalPosts) . " out of " . $totalPosts; ?>)</button>
+        </form>
+    <?php endif; ?>
+</div>
+        </div>
+        
+        <!-- Right Sidebar -->
+        <?php if ($rightSidebarHasItems): ?>
+            <div class="sidebar-right">
+                <?php get_sidebar($db, 'right', $page, $sub); ?>
+            </div>
+        <?php endif; ?>
+    </div>
+    
+    <footer>
+        &copy; 2025 Teleco.ch. All Rights Reserved.
+    </footer>
+</body>
+</html>

BIN
website3/.DS_Store


BIN
website3/content3.db


BIN
website3/public/assets/.DS_Store


+ 313 - 0
website3/public/assets/css/dialon.css

@@ -0,0 +1,313 @@
+/* Base Styles */
+:root {
+    --primary-color: #ff9900;
+    --secondary-color: #1a1a1a;
+    --background-color: #333;
+    --text-color: #e6e6e6;
+    --border-color: #444;
+    --navbar-color: #d88900;
+    --navbar-text-color: #fff;
+    --navbar-hover-color: #ffbb00;
+    --hover-color: #ffbb00;
+    --hover-text-color: #1a1a1a;
+}
+
+@font-face {
+    font-family: 'default-512';
+    font-style: normal;
+    font-weight: 400;
+    src: url('../fonts/default.ttf') format('truetype');
+}
+
+body {
+    background-color: var(--secondary-color);
+    color: var(--text-color);
+    margin: 0;
+    padding: 0;
+    font-family: Arial, comic-sans; /* ich bin so lustig */
+}
+
+header, .header-content {
+    background-color: var(--secondary-color);
+    color: var(--text-color);
+    text-align: center; /* Center the header content wenn mer kei bock uf navbar her */
+}
+
+header h1 {
+    color: var(--primary-color);
+    font-family: 'default-512', Arial, sans-serif; /* fonts sexi mache*/
+}
+
+h2 {
+    color: var(--primary-color);
+    font-family: 'default-512', Arial, sans-serif; /* nomal fonts sexi mache will us irgend nem grund die ganz site kappoot gaht wenn ich d'funt universal ahwände*/
+}
+
+.sidebar, .sidebar-right, .box, .chat-log, .chat-input .breadcrumbs {
+    background-color: var(--background-color);
+    border: 1px solid var(--border-color);
+    border-radius: 10px; /* mmmm rundi ecke damit mer sich ned ritzt */
+}
+
+.breadcrumbs {
+    background-color: var(--background-color);
+    border: 1px solid var(--border-color);
+    border-radius: 10px;
+    padding: 10px;
+    margin-bottom: 10px;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.breadcrumbs a {
+    color: var(--primary-color);
+    text-decoration: none;
+}
+
+.breadcrumbs a:hover {
+    text-decoration: underline;
+}
+
+.sidebar {
+    float: left;
+    width: 20%;
+    min-width: 200px;
+    max-width: 250px;
+    padding: 10px;
+    padding-bottom: 0px;
+    box-sizing: border-box;
+    padding-bottom: 0px;
+}
+
+.sidebar-right {
+    float: right;
+    width: 20%;
+    min-width: 200px;
+    max-width: 250px;
+    padding: 10px;
+    padding-bottom: 0px;
+    box-sizing: border-box;
+}
+
+.sidebar a, .sidebar-right a, .services a, .menu-overlay .menu-links a, .load-more-button, .mobile-navbar-menu button{
+    display: block;
+    background-color: var(--background-color);
+    color: var(--text-color);
+    padding: 12px 20px;
+    text-decoration: none;
+    border-radius: 10px; 
+    transition: background-color 0.3s ease;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    margin-bottom: 10px;
+    font-family: 'default-512', Arial, sans-serif; 
+    border: none;
+}
+
+.sidebar a:hover, .sidebar-right a:hover, .sidebar a.active, .sidebar-right a.active, .services a:hover, .menu-overlay .menu-links a:hover, .load-more-button:hover {
+    background-color: var(--hover-color);
+    color: var(--hover-text-color);
+}
+
+.container {
+    flex: 1;
+    display: flex;
+    width: 100%;
+    min-width: 300px;
+    align-items: flex-start;
+    flex-wrap: wrap;
+    margin: 20px auto 0;
+    max-width: 1200px;
+}
+
+.content {
+    width: 60%;
+    flex-grow: 1;
+    padding: 10px;
+    box-sizing: border-box;
+}
+
+.box {
+    margin-bottom: 10px;
+    padding: 10px;
+}
+
+.box h3 {
+    margin: 0 0 10px 0;
+    font-size: 16px;
+    color: var(--primary-color);
+    font-family: 'default-512', Arial, sans-serif; 
+
+}
+
+.box p, .box a {
+    margin: 5px 0;
+    font-size: 14px;
+    color: var(--text-color);
+    font-family: 'default-512', Arial, sans-serif; 
+}
+
+.box a {
+    color: var(--primary-color);
+    text-decoration: none;
+}
+
+.box a:hover {
+    text-decoration: underline;
+}
+
+footer {
+    background-color: var(--border-color);
+    color: var(--text-color);
+    text-align: center;
+    padding: 10px 0;
+    font-size: 14px;
+    width: 100%;
+    flex-shrink: 0;
+}
+
+hr {
+    border: 1px solid var(--border-color);
+    margin: 20px 0;
+}
+
+.left-aligned-title {
+    text-align: left;
+    font-size: 48px;
+    font-weight: bold;
+    color: var(--primary-color);
+    margin-bottom: 15px;
+    text-decoration: none;
+    font-family: 'default-512', Arial, sans-serif; 
+}
+
+.navbar-title {
+
+    text-decoration: none;
+}
+
+.no-top-m {
+    margin-top: 0 !important;
+}
+
+.ascii-box {
+    border: 2px solid #555;
+    border-radius: 10px;
+    padding: 20px;
+    color: var(--primary-color);
+    font-size: 18px;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.services {
+    display: flex;
+    justify-content: center;
+    flex-wrap: wrap;
+    gap: 20px;
+    margin: 20px 0;
+}.chat-container {
+    position: fixed;
+    bottom: 0;
+    right: 20px;
+    width: 90%;
+    max-width: 400px;
+    background-color: var(--secondary-color);
+    border: 2px solid var(--border-color);
+    border-radius: 10px; 
+    padding: 20px;
+    z-index: 1001;
+    transform: translateY(100%);
+    opacity: 0;
+    transition: transform 0.4s ease, opacity 0.4s ease, visibility 0.4s ease;
+    visibility: hidden;
+}
+
+.chat-container.open {
+    transform: translateY(0);
+    opacity: 1;
+    visibility: visible;
+}
+
+.chat-header {
+    font-size: 20px;
+    font-weight: bold;
+    color: var(--secondary-color);
+    text-align: center;
+    margin-bottom: 10px;
+    position: relative;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.audio-track {
+    margin: 20px 0;
+    text-align: center;
+}
+
+.complaints {
+    text-align: center;
+    margin-top: 40px;
+}
+
+.complaints a {
+    color: #ffbb00;
+    text-decoration: none;
+    transition: color 0.3s ease;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.complaints a:hover {
+    color: #ff99cc;
+}
+
+.mobile-only {
+    display: none;
+}
+
+ul {
+    list-style-type: none;
+    padding: 0;
+}
+
+ul li {
+    padding: 10px 15px;
+    margin-bottom: 10px;
+    border-radius: 10px; 
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    font-family: 'default-512', Arial, sans-serif; 
+}
+
+ul li::before {
+    content: "•";
+    color: var(--primary-color);
+    padding-right: 10px;
+}
+
+ul li span {
+    font-weight: bold;
+    color: var(--primary-color);
+}
+
+
+
+h4 {
+    text-decoration: underline;
+    size: 12px;
+    color: var(--primary-color);
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+@media screen and (max-width: 1280px) {
+    .sidebar, .sidebar-right {
+        display: none;
+    }
+}
+
+@media screen and (min-width: 1281px) {
+    .hamburger-menu {
+        display: none;
+    }
+
+    .chat-toggle-btn {
+        bottom: 20px;
+    }
+}
+

+ 180 - 0
website3/public/assets/css/extras.css

@@ -0,0 +1,180 @@
+.send-btn {
+    background-color: var(--primary-color);
+    color: var(--secondary-color);
+}
+
+.send-btn:hover {
+    background-color: #ffbb00;
+}
+
+.chat-toggle-btn {
+    position: fixed;
+    bottom: 20px;
+    right: 20px;
+    width: 50px;
+    height: 50px;
+    border: none;
+    border-radius: 50%;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    cursor: pointer;
+    z-index: 1000;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0;
+    transition: background-color 0.3s ease;
+    background-color: var(--background-color);
+    color: var(--primary-color);
+}
+
+.chat-toggle-btn svg {
+    width: 24px;
+    height: 24px;
+    fill: var(--primary-color);
+    transition: fill 0.3s ease;
+}
+
+.chat-toggle-btn:hover,
+.chat-toggle-btn.open {
+    background-color: var(--primary-color);
+}
+
+.chat-toggle-btn:hover svg,
+.chat-toggle-btn.open svg {
+    fill: var(--secondary-color);
+}
+
+.chat-close-btn {
+    color: var(--primary-color);
+}
+
+.chat-close-btn:hover {
+    color: var(--secondary-color);
+}
+
+.chat-close-btn {
+    position: absolute;
+    top: 0;
+    right: 0;
+    font-size: 18px;
+    background: none;
+    border: none;
+    cursor: pointer;
+}
+
+.chat-log {
+    height: 300px;
+    overflow-y: auto;
+    padding: 10px;
+    border-radius: 10px;
+    margin-bottom: 10px;
+    font-family: 'Courier New', Courier, monospace;
+}
+
+.chat-message {
+    margin: 5px 0;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.chat-message .sender {
+    font-weight: bold;
+}
+
+.chat-message .virtual-assistant {
+    color: red;
+}
+
+.chat-message .user {
+    color: blue;
+}
+
+.chat-input-container {
+    display: flex;
+    gap: 10px;
+}
+
+.chat-input {
+    flex: 1;
+    padding: 10px;
+    border-radius: 10px;
+    font-family: 'default-512', Arial, sans-serif;
+    color: var(--primary-color);
+    background-color: var(--secondary-color);
+    border: 1px solid var(--border-color);
+}
+
+.chat-input:focus {
+    outline: none;
+    border-color: var(--primary-color);
+}
+
+.send-btn {
+    padding: 10px;
+    border: none;
+    cursor: pointer;
+    border-radius: 10px;
+}
+
+.chat-container {
+    position: fixed;
+    bottom: 0;
+    right: 0;
+    margin-right: 20px;
+    max-width: 400px;
+    background-color: var(--secondary-color);
+    border: 2px solid var(--border-color);
+    border-radius: 10px;
+    padding: 20px;
+    z-index: 1001;
+    transform: translateY(100%);
+    opacity: 0;
+    transition: transform 0.4s ease, opacity 0.4s ease, visibility 0.4s ease;
+    visibility: hidden;
+}
+
+.chat-container.open {
+    transform: translateY(0);
+    opacity: 1;
+    visibility: visible;
+}
+
+.chat-header {
+    font-size: 20px;
+    font-weight: bold;
+    color: var(--primary-color);
+    text-align: center;
+    margin-bottom: 10px;
+    position: relative;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+@media (max-width: 600px) {
+    .chat-container {
+        width: 100%;
+        margin: 0px;
+        padding: 20px;
+        box-sizing: border-box;
+    }
+}
+
+@media (min-width: 1280px) {
+    .sidebar, .sidebar-right {
+        display: block;
+    }
+
+    .chat-toggle-btn {
+        bottom: 20px;
+        right: 20px;
+    }
+}
+
+@media (max-width: 1279px) {
+    .sidebar, .sidebar-right {
+        display: none;
+    }
+
+    .chat-toggle-btn {
+        bottom: 100px;
+        right: 20px;
+    }
+}

+ 138 - 0
website3/public/assets/css/hamburger.css

@@ -0,0 +1,138 @@
+.hamburger-menu {
+    display: none;
+    position: fixed;
+    bottom: 20px;
+    right: 20px;
+    width: 50px;
+    height: 50px;
+    background-color: var(--background-color);
+    color: var(--primary-color);
+    border: none;
+    border-radius: 50%;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    cursor: pointer;
+    z-index: 1001;
+    transition: background-color 0.3s ease;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0;
+}
+
+.hamburger-menu svg {
+    width: 24px;
+    height: 24px;
+    fill: var(--primary-color);
+    transition: fill 0.3s ease;
+}
+
+.hamburger-menu:hover,
+.hamburger-menu.open {
+    background-color: var(--primary-color);
+}
+
+.hamburger-menu:hover svg,
+.hamburger-menu.open svg {
+    fill: var(--secondary-color);
+}
+
+.menu-overlay {
+    position: fixed;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    width: 100%;
+    background-color: var(--secondary-color);
+    color: white;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    transition: transform 0.3s ease-in-out;
+    z-index: 1000;
+    transform: translateY(100%);
+    overflow-y: auto;
+}
+
+.menu-overlay.open {
+    transform: translateY(0);
+}
+
+.menu-content {
+    text-align: center;
+    width: 100%;
+    padding: 20px;
+    box-sizing: border-box;
+}
+
+.menu-content .box {
+    background-color: var(--background-color);
+    margin: 10px 0;
+    padding: 10px;
+    border: 1px solid var(--border-color);
+    border-radius: 10px;
+    box-sizing: border-box;
+}
+
+.menu-content .box a {
+    display: block;
+    background-color: var(--background-color);
+    color: var(--text-color);
+    padding: 12px 20px;
+    text-decoration: none;
+    border-radius: 10px;
+    transition: background-color 0.3s ease;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    margin-bottom: 10px;
+}
+
+.menu-content .box a:hover, .menu-content .box a.active {
+    background-color: var(--primary-color);
+    color: var(--secondary-color);
+}
+
+.menu-close-btn {
+    position: absolute;
+    top: 20px;
+    right: 20px;
+    background: none;
+    border: none;
+    color: var(--primary-color);
+    font-size: 24px;
+    cursor: pointer;
+}
+
+.menu-close-btn:hover {
+    color: var(--secondary-color);
+}
+
+@media screen and (max-width: 1280px) {
+    .sidebar, .sidebar-right {
+        display: none;
+    }
+
+    .hamburger-menu {
+        display: flex;
+    }
+
+    .menu-overlay {
+        display: block;
+    }
+}
+
+@media screen and (max-width: 600px) {
+    .menu-content {
+        padding: 10px;
+    }
+
+    .menu-content .box a {
+        padding: 10px;
+        font-size: 14px;
+    }
+}
+
+@media screen and (min-width: 1281px) {
+    .hamburger-menu {
+        display: none;
+    }
+}

+ 224 - 0
website3/public/assets/css/navbar.css

@@ -0,0 +1,224 @@
+.navbar {
+    background-color: var(--secondary-color);
+    padding: 10px;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    font-family: 'default-512', Arial, sans-serif;
+    position: relative;
+}
+
+.navbar-container {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.navbar-left, .navbar-center, .navbar-right {
+    display: flex;
+    align-items: center;
+}
+
+.navbar-center {
+    justify-content: center;
+    flex-grow: 1;
+}
+
+.navbar-mobile {
+    display: none;
+    justify-content: space-between;
+    align-items: center;
+    width: 100%;
+    background-color: var(--secondary-color);
+    padding: 10px;
+}
+
+.navbar-mobile .navbar-left {
+    display: flex;
+    align-items: center;
+}
+
+.navbar-logo {
+    height: 40px;
+    margin-right: 10px;
+}
+
+.navbar-title {
+    font-size: 20px;
+    font-weight: bold;
+    color: var(--primary-color);
+    padding-right: 20px;
+}
+
+.navbar, .navbar button, .navbar input[type="text"], .navbar input[type="search"] {
+    color: var(--navbar-text-color);
+    text-decoration: none;
+    padding-inline: 10px;
+    margin: 0 5px;
+    border: none;
+    background: none;
+    cursor: pointer;
+    transition: color 0.3s ease;
+    font-family: 'default-512', Arial, sans-serif;
+    font-size: 18px;
+}
+
+.navbar-link {
+    color: var(--navbar-text-color);
+    text-decoration: none;
+    border: none;
+    background: none;
+    cursor: pointer;
+    transition: color 0.3s ease;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.dropdown-link {
+    color: var(--navbar-text-color);
+    text-decoration: none;
+    transition: color 0.3s ease;
+    font-family: 'default-512', Arial, sans-serif;
+    padding-top: 5px;
+}
+
+.navbar a:hover, .navbar button:hover {
+    color: var(--navbar-hover-color);
+}
+
+.navbar-dropdown {
+    position: relative;
+    display: inline-block;
+}
+
+.navbar-dropbtn {
+    background-color: var(--navbar-color);
+    color: var(--navbar-text-color);
+    padding: 10px;
+    font-size: 16px;
+    border: none;
+    cursor: pointer;
+    border-radius: 10px;
+}
+
+.navbar-dropdown-content {
+    display: none;
+    position: absolute;
+    background-color: var(--background-color);
+    min-width: 160px;
+    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
+    z-index: 1;
+    border-radius: 10px;
+}
+
+.navbar-dropdown:hover .navbar-dropdown-content {
+    display: block;
+}
+
+.navbar-dropdown-content a {
+    color: var(--text-color);
+    padding: 12px 16px;
+    text-decoration: none;
+    display: block;
+    border-bottom: 1px solid var(--border-color);
+}
+
+.navbar-dropdown-content a:last-child {
+    border-bottom: none;
+}
+
+.bruh-why {
+    padding-inline: 0px;
+}
+
+.mobile-navbar-dropdown {
+    padding-top: 5px;
+}
+
+.mobile-navbar-dropdown:hover {
+    color: var(--navbar-hover-color);
+}
+
+.navbar-toggle {
+    display: none;
+    background: none;
+    border: none;
+    color: var(--primary-color);
+    cursor: pointer;
+    font-size: 24px;
+}
+
+.mobile-navbar-menu {
+    display: flex;
+    flex-direction: column;
+    width: 100%;
+    background-color: var(--secondary-color);
+    border-radius: 10px;
+    max-height: 0;
+    overflow: hidden;
+    transition: max-height 0.4s ease-out, padding 0.4s ease-out;
+    padding-top: 0;
+    padding-bottom: 0;
+}
+
+.mobile-navbar-menu.open {
+    padding-top: 10px;
+    padding-bottom: 10px;
+}
+
+.mobile-navbar-menu input[type="text"],
+.mobile-navbar-menu input[type="search"] {
+    padding: 10px;
+    margin: 5px 0;
+    border: none;
+    background: none;
+    cursor: pointer;
+    transition: color 0.3s ease;
+    font-family: 'default-512', Arial, sans-serif;
+    color: var(--navbar-text-color);
+    text-decoration: none;
+    display: block;
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.mobile-navbar-menu input[type="text"]:hover,
+.mobile-navbar-menu input[type="search"]:hover,
+.mobile-navbar-menu button:hover {
+    color: var(--navbar-hover-color);
+}
+
+@media screen and (max-width: 768px) {
+    .navbar-container {
+        display: none;
+    }
+    
+    .navbar-mobile {
+        display: flex;
+    }
+
+    .navbar-toggle {
+        display: block;
+    }
+}
+
+@media screen and (min-width: 769px) {
+    .mobile-navbar-menu {
+        display: none !important;
+    }
+}
+
+.navbar .buttonify{
+    display: block;
+    background-color: var(--background-color); /* penis haha lol  ja das isch psychose klass will buttons nei segged abunzdue*/
+    color: var(--text-color);
+    padding: 12px 20px;
+    text-decoration: none;
+    border-radius: 10px;
+    transition: background-color 0.3s ease;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    font-family: 'default-512', Arial, sans-serif;
+    border: none;
+}
+
+.navbar .buttonify:hover {
+    background-color: var(--hover-color);
+    color: var(--hover-text-color);
+}

BIN
website3/public/assets/fonts/.DS_Store


BIN
website3/public/assets/fonts/default.ttf


BIN
website3/public/assets/img/.DS_Store


BIN
website3/public/assets/img/code-is-ass.jpeg


BIN
website3/public/assets/img/dialon.png


BIN
website3/public/assets/img/force.png


BIN
website3/public/assets/img/fuck-main.jpeg


BIN
website3/public/assets/img/fuckjs.jpeg


BIN
website3/public/assets/img/jsmomentom.jpg


BIN
website3/public/assets/img/router1.jpg


BIN
website3/public/assets/img/router2.jpg


BIN
website3/public/assets/img/rover.png


BIN
website3/public/assets/img/ssc.jpg


BIN
website3/public/assets/img/wrong.png


+ 94 - 0
website3/public/assets/js/chat.js

@@ -0,0 +1,94 @@
+// chat container setup for maximum verwirrung weil ich kann das alles langsam nicht mehr junge die sprach macht kei sinn
+const chatContainer = document.getElementById('chat-container');
+const chatLog = document.getElementById('chat-log');
+const userInput = document.getElementById('user-input');
+let hasGreeted = false; // flag so we only say grǔtzi eimal und ned sächzgs mal junge das wäri fett weird
+
+// toggle chat open and closed again ????????????? i dont remember what i haben gesoffen hier
+function toggleChat() {
+    if (chatContainer.classList.contains('open')) {
+        chatContainer.classList.remove('open');
+        setTimeout(() => {
+            chatContainer.style.visibility = 'hidden';
+        }, 400); // match delay with css so it doesnt look wie abfall
+    } else {
+        chatContainer.style.visibility = 'visible';
+        chatContainer.classList.add('open');
+        
+        // the actuall saying grǔtzi miternaand gugus
+        if (!hasGreeted) {
+            displayMessage('Virtual Assistant', "Grǔtzi 🇨🇭 ! I'm your virtual assistant! Please tell me about your problem or what you need help with.");
+            hasGreeted = true;
+        }
+    }
+}
+
+// send message when enter key is pressed because who will press a button to send a message ???? are you a psychopat ?
+userInput.addEventListener('keypress', function(event) {
+    if (event.key === 'Enter') {
+        sendMessage();
+    }
+});
+
+// handle sending messages
+function sendMessage() {
+    const userMessage = userInput.value.trim();
+    if (userMessage) {
+        displayMessage('You', userMessage);
+        userInput.value = '';
+        setTimeout(() => catReply(userMessage), 1000); // delay for realism so the "assistant" can "think" about the reply
+    }
+}
+
+// put a message in the chat log will chat funktioniert ned ohni message history und so lol
+function displayMessage(sender, message) {
+    const messageElement = document.createElement('div');
+    messageElement.classList.add('chat-message');
+
+    const senderSpan = document.createElement('span');
+    senderSpan.classList.add('sender');
+    senderSpan.classList.add(sender === 'You' ? 'user' : 'virtual-assistant');
+    senderSpan.textContent = sender + ': ';
+    
+    const messageSpan = document.createElement('span');
+    messageSpan.textContent = message;
+    
+    messageElement.appendChild(senderSpan);
+    messageElement.appendChild(messageSpan);
+    chatLog.appendChild(messageElement);
+    chatLog.scrollTop = chatLog.scrollHeight;
+}
+
+// cat assistant category based matched replies
+function catReply(userMessage) {
+    const keywords = {
+        "help": ["meeeooow...? figure it out yourself! because that sounds like a you problem bahahahasdjkasadlkj 💀", "meeooww! welp too bad. help yourself bahasjdhaskjdhaskjdh", "mrrrow! idk either lol. go ask yourself maybe your smart if you use your brain instread of relying on a virtual assistant cat"],
+        "problem": ["meeooow, eh thats normal here, should've chosen someone else to host your stuff ngl lol", "mrow, contact sysadminier maybe idk? i am just cat or a teaput ???? idk what i am help aaaaaaa", "mreeow, tell me more ig... if you want idc lol"],
+        "default": ["meow", "meeooow!", "mew.", "mrow!", "meeow...", "meow, meow.", "mroww", "mlem"]
+    };
+
+    // generate a bs reply to fool user into thinking the cat assistant is actually doing something
+    function generateScrambledReply() {
+        const phrases = keywords["default"];
+        let scrambled = [];
+        const length = Math.floor(Math.random() * 3) + 3; // random length of reply 3-5 words
+        
+        for (let i = 0; i < length; i++) {
+            const randomPhrase = phrases[Math.floor(Math.random() * phrases.length)];
+            scrambled.push(randomPhrase);
+        }
+        return scrambled.join(" ");
+    }
+
+    // check for keywords in user message and decide what kind of blödsinn to say zu the schafseckel using the chat
+    let reply;
+    if (userMessage.toLowerCase().includes("help")) {
+        reply = keywords["help"][Math.floor(Math.random() * keywords["help"].length)];
+    } else if (userMessage.toLowerCase().includes("problem")) {
+        reply = keywords["problem"][Math.floor(Math.random() * keywords["problem"].length)];
+    } else {
+        reply = generateScrambledReply(); // generate scrambled reply for "default" case
+    }
+
+    displayMessage('Virtual Assistant', reply);
+}

+ 40 - 0
website3/public/assets/js/menu.js

@@ -0,0 +1,40 @@
+document.addEventListener('DOMContentLoaded', function () {
+    // menu overlay so we can open and close it bruh
+    const overlay = document.querySelector('.menu-overlay');
+    const hamburger = document.querySelector('.hamburger-menu');
+    
+    function toggleMenu() {
+        if (overlay.classList.contains('open')) {
+            overlay.classList.remove('open');
+            setTimeout(() => {
+                overlay.style.visibility = 'hidden';
+            }, 400); // match this delay with the css transition duration because ja isch halt so
+        } else {
+            overlay.style.visibility = 'visible';
+            overlay.classList.add('open');
+        }
+        hamburger.classList.toggle('open');
+        document.body.style.overflow = overlay.classList.contains('open') ? 'hidden' : ''; // no scrolling on the main page while menu is open
+    }
+
+    // if burger king menu button exists, hook it up to toggle the menu
+    if (hamburger) {
+        hamburger.addEventListener('click', function () {
+            toggleMenu();
+        });
+    }
+
+    // close menu when clicking a link inside it because so funktioniert das halt, pech gha wenns der nid passt lol 
+    if (overlay) {
+        overlay.querySelectorAll('a').forEach(link => {
+            link.addEventListener('click', () => {
+                overlay.classList.remove('open');
+                setTimeout(() => {
+                    overlay.style.visibility = 'hidden';
+                    hamburger.classList.remove('open');
+                    document.body.style.overflow = ''; // kei ahnig was das macht aber es het mis problem emol glöst
+                }, 400); // match transition duration ... again no clue what this actually does but it works so i'm not touching it
+            });
+        });
+    }
+});

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 16 - 0
website3/public/assets/svg/teleco.svg


+ 190 - 0
website3/public/index.php

@@ -0,0 +1,190 @@
+<?php
+// loads the config
+$config = include(__DIR__ . '/../../config.php');
+
+// go set your id here otehrwise ur site wont load the stuff it needs
+$siteId = 4;
+
+// website go search what stuffs it need to load
+$websiteConfig = array_filter($config, function($site) use ($siteId) {
+    return isset($site['id']) && $site['id'] === $siteId;
+});
+$websiteConfig = reset($websiteConfig);
+
+// include the components so the site actually gets rendered
+foreach ($websiteConfig['components'] as $component) {
+    include($component);
+}
+
+?>
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Dialon - <?php echo ucfirst($page); ?></title>
+    <meta name="description" content="<?php echo $metaDescription; ?>">
+    <link rel="stylesheet" href="assets/css/dialon.css">
+    <?php if (!$navbarTableExists || $navbarHasEntries): ?>
+        <link rel="stylesheet" href="assets/css/navbar.css">
+    <?php endif; ?>
+    <?php if (!$navbarTableExists || !$navbarHasEntries): ?>
+        <link rel="stylesheet" href="assets/css/hamburger.css">
+    <?php endif; ?>
+    <link rel="stylesheet" href="assets/css/extras.css">
+
+    <style>
+    <?php if ($navbarTableExists && $navbarHasEntries): ?>
+    .chat-toggle-btn {
+        bottom: 20px;
+    }
+    <?php endif; ?>
+    </style>
+</head>
+
+<body>
+    <header>
+        <div class="header-content" <?php if ($navbarTableExists && $navbarHasEntries) echo 'style="display:none;"'; ?>>
+            <img src="assets/img/dialon.png" alt="Teleco Logo" class="logo">
+            <h1>dialon.ch</h1>
+        </div>
+    </header>
+    
+    <?php if ($navbarTableExists && $navbarHasEntries): ?>
+        <?php render_navbar_js($db); ?>
+    <?php endif; ?>
+
+    <?php if (!$navbarTableExists || !$navbarHasEntries): ?>
+    <!-- burger king chnopf -->
+    <button class="hamburger-menu" onclick="toggleMenu()">
+        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" width="24" height="24" aria-hidden="true">
+            <path d="M0 88C0 74.7 10.7 64 24 64H424c13.3 0 24 10.7 24 24s-10.7 24-24 24H24C10.7 112 0 101.3 0 88zM0 248C0 234.7 10.7 224 24 224H424c13.3 0 24 10.7 24 24s-10.7 24-24 24H24C10.7 272 0 261.3 0 248zM424 448H24c-13.3 0-24-10.7-24-24s10.7-24 24-24H424c13.3 0 24 10.7 24 24s-10.7 24-24 24z"/>
+        </svg>
+    </button>
+    <!-- burger king -->
+    <div class="menu-overlay">
+        <div class="menu-content">
+            <h2>Navigation</h2>
+            <?php get_sidebar($db, 'left', $page, $sub); ?>
+            <?php get_sidebar($db, 'right', $page, $sub); ?>
+        </div>
+    </div>
+<?php endif; ?>
+
+    <div class="container" style="<?php echo $leftSidebarHasItems || $rightSidebarHasItems ? '' : 'margin-left: 0px; margin-right: 0px; flex-wrap: nowrap; margin-top: 0px; margin-bottom: 0px; max-width: 100%; box-sizing: border-box; padding: 10px;'; ?>">
+        <!-- dis da left sidebar -->
+        <?php if ($leftSidebarHasItems): ?>
+            <div class="sidebar">
+                <?php get_sidebar($db, 'left', $page, $sub); ?>
+            </div>
+        <?php endif; ?>
+
+        <!-- dis da main content row down the middle -->
+        <div class="content" id="content" style="<?php echo $leftSidebarHasItems || $rightSidebarHasItems ? '' : 'width: calc(100%);'; ?>">
+            <!-- my terrible way of doing breadcrumbs -->
+            <div class="breadcrumbs">
+                <?php
+                foreach ($breadcrumbs as $index => $crumb) {
+                    if ($index > 0) echo ' > ';
+                    echo '<a href="?page=' . htmlspecialchars($crumb['page']) . '">';
+                    echo htmlspecialchars($crumb['title']);
+                    echo '</a>';
+                }
+                ?>
+            </div>
+            <?php if ($hasContent): ?>
+                <?php
+                $result = $query->execute();
+                $lastPostId = 0;
+                while ($row = $result->fetchArray()):
+                    $lastPostId++;
+                ?>
+                    <div class="box" id="post-<?php echo $lastPostId; ?>">
+                        <h3><?php echo htmlspecialchars($row['title']); ?></h3>
+                        <p><?php echo $row['content']; ?></p> <!-- used to have a function to disable and enable rendering html in post, got very annoyed with its db not doing what its supposed to do so now it loads html eitherway and html_custom is nolonger a thing im das datenbank -->
+                        <hr>
+                        <p>Date: <?php echo $row['date']; ?></p>
+                    </div>
+                <?php endwhile; ?>
+            <?php else: ?>
+                <div class="box">
+                    <h3>404 - Page Not Found</h3>
+                    <p>Sorry, the page you are looking for does not exist.</p>
+                </div>
+            <?php endif; ?>
+
+            <div id="load-container">
+                <?php if ($hasContent && $offset + $limit < $totalPosts): ?>
+                    <form method="get" action="index.php#post-<?php echo $lastPostId; ?>">
+                        <input type="hidden" name="page" value="<?php echo htmlspecialchars($page); ?>">
+                        <?php if ($sub): ?>
+                            <input type="hidden" name="sub" value="<?php echo htmlspecialchars($sub); ?>">
+                        <?php endif; ?>
+                        <input type="hidden" name="offset" value="<?php echo $offset + $limit; ?>">
+                        <button class="load-more-button" type="submit">Load More (<?php echo min($offset + $limit, $totalPosts) . " out of " . $totalPosts; ?>)</button>
+                    </form>
+                <?php endif; ?>
+            </div>
+        </div>
+
+        <!-- dis da right seitenleisteh! -->
+        <?php if ($rightSidebarHasItems): ?>
+            <div class="sidebar-right">
+                <?php get_sidebar($db, 'right', $page, $sub); ?>
+            </div>
+        <?php endif; ?>
+    </div>
+
+    <!-- cat support meow meow meow meow -->
+    <button class="chat-toggle-btn" onclick="toggleChat()">
+        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="24" height="24" aria-hidden="true">
+            <path d="M192 208c0-17.7-14.3-32-32-32h-16c-35.4 0-64 28.7-64 64v48c0 35.4 28.7 64 64 64h16c17.7 0 32-14.3 32-32V208zm176 144c35.4 0 64-28.7 64-64v-48c0-35.4-28.7-64-64-64h-16c-17.7 0-32 14.3-32 32v112c0 17.7 14.3 32 32 32h16zM256 0C113.2 0 4.6 118.8 0 256v16c0 8.8 7.2 16 16 16h16c8.8 0 16-7.2 16-16v-16c0-114.7 93.3-208 208-208s208 93.3 208 208h-.1c.1 2.4 .1 165.7 .1 165.7 0 23.4-18.9 42.3-42.3 42.3H320c0-26.5-21.5-48-48-48h-32c-26.5 0-48 21.5-48 48s21.5 48 48 48h181.7c49.9 0 90.3-40.4 90.3-90.3V256C507.4 118.8 398.8 0 256 0z"/>
+        </svg>
+    </button>
+
+    <!-- mau mau support dumpster -->
+    <div class="chat-container" id="chat-container">
+        <div class="chat-header">
+            Virtual Assistant Chat
+            <button class="chat-close-btn" onclick="toggleChat()">✖</button> <!-- mau mau tschau -->
+        </div>
+        <div class="chat-log" id="chat-log"></div>
+        <div class="chat-input-container">
+            <input type="text" id="user-input" class="chat-input" style="background-color: var(--secondary-color);" placeholder="Type your message here...">
+            <button class="send-btn" onclick="sendMessage()">Send</button>
+        </div>
+    </div>
+
+    <!-- js sache sind hier und so  -->
+    <script src="assets/js/chat.js"></script>
+    <script src="assets/js/menu.js"></script>
+
+    <script>
+document.addEventListener('DOMContentLoaded', function() {
+    const mobileMenu = document.querySelector('.mobile-navbar-menu');
+    const toggleButton = document.querySelector('.navbar-toggle');
+
+    window.toggleNavbar = function() {
+        if (!mobileMenu) return;
+
+        if (mobileMenu.classList.contains('open')) {
+            mobileMenu.style.maxHeight = "0px";
+            mobileMenu.classList.remove('open');
+        } else {
+            mobileMenu.style.maxHeight = mobileMenu.scrollHeight + "px";
+            mobileMenu.classList.add('open');
+        }
+    };
+
+    window.addEventListener('resize', function() {
+        if (window.innerWidth > 768 && mobileMenu.classList.contains('open')) {
+            mobileMenu.classList.remove('open');
+            mobileMenu.style.maxHeight = "0px";
+        }
+    });
+});
+</script>
+
+</body>
+</html>

BIN
website4/.DS_Store


BIN
website4/content4.db


BIN
website4/public/assets/.DS_Store


+ 313 - 0
website4/public/assets/css/dialon.css

@@ -0,0 +1,313 @@
+/* Base Styles */
+:root {
+    --primary-color: #ff9900;
+    --secondary-color: #1a1a1a;
+    --background-color: #333;
+    --text-color: #e6e6e6;
+    --border-color: #444;
+    --navbar-color: #d88900;
+    --navbar-text-color: #fff;
+    --navbar-hover-color: #ffbb00;
+    --hover-color: #ffbb00;
+    --hover-text-color: #1a1a1a;
+}
+
+@font-face {
+    font-family: 'default-512';
+    font-style: normal;
+    font-weight: 400;
+    src: url('../fonts/default.ttf') format('truetype');
+}
+
+body {
+    background-color: var(--secondary-color);
+    color: var(--text-color);
+    margin: 0;
+    padding: 0;
+    font-family: Arial, comic-sans; /* ich bin so lustig */
+}
+
+header, .header-content {
+    background-color: var(--secondary-color);
+    color: var(--text-color);
+    text-align: center; /* Center the header content wenn mer kei bock uf navbar her */
+}
+
+header h1 {
+    color: var(--primary-color);
+    font-family: 'default-512', Arial, sans-serif; /* fonts sexi mache*/
+}
+
+h2 {
+    color: var(--primary-color);
+    font-family: 'default-512', Arial, sans-serif; /* nomal fonts sexi mache will us irgend nem grund die ganz site kappoot gaht wenn ich d'funt universal ahwände*/
+}
+
+.sidebar, .sidebar-right, .box, .chat-log, .chat-input .breadcrumbs {
+    background-color: var(--background-color);
+    border: 1px solid var(--border-color);
+    border-radius: 10px; /* mmmm rundi ecke damit mer sich ned ritzt */
+}
+
+.breadcrumbs {
+    background-color: var(--background-color);
+    border: 1px solid var(--border-color);
+    border-radius: 10px;
+    padding: 10px;
+    margin-bottom: 10px;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.breadcrumbs a {
+    color: var(--primary-color);
+    text-decoration: none;
+}
+
+.breadcrumbs a:hover {
+    text-decoration: underline;
+}
+
+.sidebar {
+    float: left;
+    width: 20%;
+    min-width: 200px;
+    max-width: 250px;
+    padding: 10px;
+    padding-bottom: 0px;
+    box-sizing: border-box;
+    padding-bottom: 0px;
+}
+
+.sidebar-right {
+    float: right;
+    width: 20%;
+    min-width: 200px;
+    max-width: 250px;
+    padding: 10px;
+    padding-bottom: 0px;
+    box-sizing: border-box;
+}
+
+.sidebar a, .sidebar-right a, .services a, .menu-overlay .menu-links a, .load-more-button, .mobile-navbar-menu button{
+    display: block;
+    background-color: var(--background-color);
+    color: var(--text-color);
+    padding: 12px 20px;
+    text-decoration: none;
+    border-radius: 10px; 
+    transition: background-color 0.3s ease;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    margin-bottom: 10px;
+    font-family: 'default-512', Arial, sans-serif; 
+    border: none;
+}
+
+.sidebar a:hover, .sidebar-right a:hover, .sidebar a.active, .sidebar-right a.active, .services a:hover, .menu-overlay .menu-links a:hover, .load-more-button:hover {
+    background-color: var(--hover-color);
+    color: var(--hover-text-color);
+}
+
+.container {
+    flex: 1;
+    display: flex;
+    width: 100%;
+    min-width: 300px;
+    align-items: flex-start;
+    flex-wrap: wrap;
+    margin: 20px auto 0;
+    max-width: 1200px;
+}
+
+.content {
+    width: 60%;
+    flex-grow: 1;
+    padding: 10px;
+    box-sizing: border-box;
+}
+
+.box {
+    margin-bottom: 10px;
+    padding: 10px;
+}
+
+.box h3 {
+    margin: 0 0 10px 0;
+    font-size: 16px;
+    color: var(--primary-color);
+    font-family: 'default-512', Arial, sans-serif; 
+
+}
+
+.box p, .box a {
+    margin: 5px 0;
+    font-size: 14px;
+    color: var(--text-color);
+    font-family: 'default-512', Arial, sans-serif; 
+}
+
+.box a {
+    color: var(--primary-color);
+    text-decoration: none;
+}
+
+.box a:hover {
+    text-decoration: underline;
+}
+
+footer {
+    background-color: var(--border-color);
+    color: var(--text-color);
+    text-align: center;
+    padding: 10px 0;
+    font-size: 14px;
+    width: 100%;
+    flex-shrink: 0;
+}
+
+hr {
+    border: 1px solid var(--border-color);
+    margin: 20px 0;
+}
+
+.left-aligned-title {
+    text-align: left;
+    font-size: 48px;
+    font-weight: bold;
+    color: var(--primary-color);
+    margin-bottom: 15px;
+    text-decoration: none;
+    font-family: 'default-512', Arial, sans-serif; 
+}
+
+.navbar-title {
+
+    text-decoration: none;
+}
+
+.no-top-m {
+    margin-top: 0 !important;
+}
+
+.ascii-box {
+    border: 2px solid #555;
+    border-radius: 10px;
+    padding: 20px;
+    color: var(--primary-color);
+    font-size: 18px;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.services {
+    display: flex;
+    justify-content: center;
+    flex-wrap: wrap;
+    gap: 20px;
+    margin: 20px 0;
+}.chat-container {
+    position: fixed;
+    bottom: 0;
+    right: 20px;
+    width: 90%;
+    max-width: 400px;
+    background-color: var(--secondary-color);
+    border: 2px solid var(--border-color);
+    border-radius: 10px; 
+    padding: 20px;
+    z-index: 1001;
+    transform: translateY(100%);
+    opacity: 0;
+    transition: transform 0.4s ease, opacity 0.4s ease, visibility 0.4s ease;
+    visibility: hidden;
+}
+
+.chat-container.open {
+    transform: translateY(0);
+    opacity: 1;
+    visibility: visible;
+}
+
+.chat-header {
+    font-size: 20px;
+    font-weight: bold;
+    color: var(--secondary-color);
+    text-align: center;
+    margin-bottom: 10px;
+    position: relative;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.audio-track {
+    margin: 20px 0;
+    text-align: center;
+}
+
+.complaints {
+    text-align: center;
+    margin-top: 40px;
+}
+
+.complaints a {
+    color: #ffbb00;
+    text-decoration: none;
+    transition: color 0.3s ease;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.complaints a:hover {
+    color: #ff99cc;
+}
+
+.mobile-only {
+    display: none;
+}
+
+ul {
+    list-style-type: none;
+    padding: 0;
+}
+
+ul li {
+    padding: 10px 15px;
+    margin-bottom: 10px;
+    border-radius: 10px; 
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    font-family: 'default-512', Arial, sans-serif; 
+}
+
+ul li::before {
+    content: "•";
+    color: var(--primary-color);
+    padding-right: 10px;
+}
+
+ul li span {
+    font-weight: bold;
+    color: var(--primary-color);
+}
+
+
+
+h4 {
+    text-decoration: underline;
+    size: 12px;
+    color: var(--primary-color);
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+@media screen and (max-width: 1280px) {
+    .sidebar, .sidebar-right {
+        display: none;
+    }
+}
+
+@media screen and (min-width: 1281px) {
+    .hamburger-menu {
+        display: none;
+    }
+
+    .chat-toggle-btn {
+        bottom: 20px;
+    }
+}
+

+ 180 - 0
website4/public/assets/css/extras.css

@@ -0,0 +1,180 @@
+.send-btn {
+    background-color: var(--primary-color);
+    color: var(--secondary-color);
+}
+
+.send-btn:hover {
+    background-color: #ffbb00;
+}
+
+.chat-toggle-btn {
+    position: fixed;
+    bottom: 20px;
+    right: 20px;
+    width: 50px;
+    height: 50px;
+    border: none;
+    border-radius: 50%;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    cursor: pointer;
+    z-index: 1000;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0;
+    transition: background-color 0.3s ease;
+    background-color: var(--background-color);
+    color: var(--primary-color);
+}
+
+.chat-toggle-btn svg {
+    width: 24px;
+    height: 24px;
+    fill: var(--primary-color);
+    transition: fill 0.3s ease;
+}
+
+.chat-toggle-btn:hover,
+.chat-toggle-btn.open {
+    background-color: var(--primary-color);
+}
+
+.chat-toggle-btn:hover svg,
+.chat-toggle-btn.open svg {
+    fill: var(--secondary-color);
+}
+
+.chat-close-btn {
+    color: var(--primary-color);
+}
+
+.chat-close-btn:hover {
+    color: var(--secondary-color);
+}
+
+.chat-close-btn {
+    position: absolute;
+    top: 0;
+    right: 0;
+    font-size: 18px;
+    background: none;
+    border: none;
+    cursor: pointer;
+}
+
+.chat-log {
+    height: 300px;
+    overflow-y: auto;
+    padding: 10px;
+    border-radius: 10px;
+    margin-bottom: 10px;
+    font-family: 'Courier New', Courier, monospace;
+}
+
+.chat-message {
+    margin: 5px 0;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.chat-message .sender {
+    font-weight: bold;
+}
+
+.chat-message .virtual-assistant {
+    color: red;
+}
+
+.chat-message .user {
+    color: blue;
+}
+
+.chat-input-container {
+    display: flex;
+    gap: 10px;
+}
+
+.chat-input {
+    flex: 1;
+    padding: 10px;
+    border-radius: 10px;
+    font-family: 'default-512', Arial, sans-serif;
+    color: var(--primary-color);
+    background-color: var(--secondary-color);
+    border: 1px solid var(--border-color);
+}
+
+.chat-input:focus {
+    outline: none;
+    border-color: var(--primary-color);
+}
+
+.send-btn {
+    padding: 10px;
+    border: none;
+    cursor: pointer;
+    border-radius: 10px;
+}
+
+.chat-container {
+    position: fixed;
+    bottom: 0;
+    right: 0;
+    margin-right: 20px;
+    max-width: 400px;
+    background-color: var(--secondary-color);
+    border: 2px solid var(--border-color);
+    border-radius: 10px;
+    padding: 20px;
+    z-index: 1001;
+    transform: translateY(100%);
+    opacity: 0;
+    transition: transform 0.4s ease, opacity 0.4s ease, visibility 0.4s ease;
+    visibility: hidden;
+}
+
+.chat-container.open {
+    transform: translateY(0);
+    opacity: 1;
+    visibility: visible;
+}
+
+.chat-header {
+    font-size: 20px;
+    font-weight: bold;
+    color: var(--primary-color);
+    text-align: center;
+    margin-bottom: 10px;
+    position: relative;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+@media (max-width: 600px) {
+    .chat-container {
+        width: 100%;
+        margin: 0px;
+        padding: 20px;
+        box-sizing: border-box;
+    }
+}
+
+@media (min-width: 1280px) {
+    .sidebar, .sidebar-right {
+        display: block;
+    }
+
+    .chat-toggle-btn {
+        bottom: 20px;
+        right: 20px;
+    }
+}
+
+@media (max-width: 1279px) {
+    .sidebar, .sidebar-right {
+        display: none;
+    }
+
+    .chat-toggle-btn {
+        bottom: 100px;
+        right: 20px;
+    }
+}

+ 138 - 0
website4/public/assets/css/hamburger.css

@@ -0,0 +1,138 @@
+.hamburger-menu {
+    display: none;
+    position: fixed;
+    bottom: 20px;
+    right: 20px;
+    width: 50px;
+    height: 50px;
+    background-color: var(--background-color);
+    color: var(--primary-color);
+    border: none;
+    border-radius: 50%;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    cursor: pointer;
+    z-index: 1001;
+    transition: background-color 0.3s ease;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0;
+}
+
+.hamburger-menu svg {
+    width: 24px;
+    height: 24px;
+    fill: var(--primary-color);
+    transition: fill 0.3s ease;
+}
+
+.hamburger-menu:hover,
+.hamburger-menu.open {
+    background-color: var(--primary-color);
+}
+
+.hamburger-menu:hover svg,
+.hamburger-menu.open svg {
+    fill: var(--secondary-color);
+}
+
+.menu-overlay {
+    position: fixed;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    width: 100%;
+    background-color: var(--secondary-color);
+    color: white;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    transition: transform 0.3s ease-in-out;
+    z-index: 1000;
+    transform: translateY(100%);
+    overflow-y: auto;
+}
+
+.menu-overlay.open {
+    transform: translateY(0);
+}
+
+.menu-content {
+    text-align: center;
+    width: 100%;
+    padding: 20px;
+    box-sizing: border-box;
+}
+
+.menu-content .box {
+    background-color: var(--background-color);
+    margin: 10px 0;
+    padding: 10px;
+    border: 1px solid var(--border-color);
+    border-radius: 10px;
+    box-sizing: border-box;
+}
+
+.menu-content .box a {
+    display: block;
+    background-color: var(--background-color);
+    color: var(--text-color);
+    padding: 12px 20px;
+    text-decoration: none;
+    border-radius: 10px;
+    transition: background-color 0.3s ease;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    margin-bottom: 10px;
+}
+
+.menu-content .box a:hover, .menu-content .box a.active {
+    background-color: var(--primary-color);
+    color: var(--secondary-color);
+}
+
+.menu-close-btn {
+    position: absolute;
+    top: 20px;
+    right: 20px;
+    background: none;
+    border: none;
+    color: var(--primary-color);
+    font-size: 24px;
+    cursor: pointer;
+}
+
+.menu-close-btn:hover {
+    color: var(--secondary-color);
+}
+
+@media screen and (max-width: 1280px) {
+    .sidebar, .sidebar-right {
+        display: none;
+    }
+
+    .hamburger-menu {
+        display: flex;
+    }
+
+    .menu-overlay {
+        display: block;
+    }
+}
+
+@media screen and (max-width: 600px) {
+    .menu-content {
+        padding: 10px;
+    }
+
+    .menu-content .box a {
+        padding: 10px;
+        font-size: 14px;
+    }
+}
+
+@media screen and (min-width: 1281px) {
+    .hamburger-menu {
+        display: none;
+    }
+}

+ 224 - 0
website4/public/assets/css/navbar.css

@@ -0,0 +1,224 @@
+.navbar {
+    background-color: var(--secondary-color);
+    padding: 10px;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    font-family: 'default-512', Arial, sans-serif;
+    position: relative;
+}
+
+.navbar-container {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.navbar-left, .navbar-center, .navbar-right {
+    display: flex;
+    align-items: center;
+}
+
+.navbar-center {
+    justify-content: center;
+    flex-grow: 1;
+}
+
+.navbar-mobile {
+    display: none;
+    justify-content: space-between;
+    align-items: center;
+    width: 100%;
+    background-color: var(--secondary-color);
+    padding: 10px;
+}
+
+.navbar-mobile .navbar-left {
+    display: flex;
+    align-items: center;
+}
+
+.navbar-logo {
+    height: 40px;
+    margin-right: 10px;
+}
+
+.navbar-title {
+    font-size: 20px;
+    font-weight: bold;
+    color: var(--primary-color);
+    padding-right: 20px;
+}
+
+.navbar, .navbar button, .navbar input[type="text"], .navbar input[type="search"] {
+    color: var(--navbar-text-color);
+    text-decoration: none;
+    padding-inline: 10px;
+    margin: 0 5px;
+    border: none;
+    background: none;
+    cursor: pointer;
+    transition: color 0.3s ease;
+    font-family: 'default-512', Arial, sans-serif;
+    font-size: 18px;
+}
+
+.navbar-link {
+    color: var(--navbar-text-color);
+    text-decoration: none;
+    border: none;
+    background: none;
+    cursor: pointer;
+    transition: color 0.3s ease;
+    font-family: 'default-512', Arial, sans-serif;
+}
+
+.dropdown-link {
+    color: var(--navbar-text-color);
+    text-decoration: none;
+    transition: color 0.3s ease;
+    font-family: 'default-512', Arial, sans-serif;
+    padding-top: 5px;
+}
+
+.navbar a:hover, .navbar button:hover {
+    color: var(--navbar-hover-color);
+}
+
+.navbar-dropdown {
+    position: relative;
+    display: inline-block;
+}
+
+.navbar-dropbtn {
+    background-color: var(--navbar-color);
+    color: var(--navbar-text-color);
+    padding: 10px;
+    font-size: 16px;
+    border: none;
+    cursor: pointer;
+    border-radius: 10px;
+}
+
+.navbar-dropdown-content {
+    display: none;
+    position: absolute;
+    background-color: var(--background-color);
+    min-width: 160px;
+    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
+    z-index: 1;
+    border-radius: 10px;
+}
+
+.navbar-dropdown:hover .navbar-dropdown-content {
+    display: block;
+}
+
+.navbar-dropdown-content a {
+    color: var(--text-color);
+    padding: 12px 16px;
+    text-decoration: none;
+    display: block;
+    border-bottom: 1px solid var(--border-color);
+}
+
+.navbar-dropdown-content a:last-child {
+    border-bottom: none;
+}
+
+.bruh-why {
+    padding-inline: 0px;
+}
+
+.mobile-navbar-dropdown {
+    padding-top: 5px;
+}
+
+.mobile-navbar-dropdown:hover {
+    color: var(--navbar-hover-color);
+}
+
+.navbar-toggle {
+    display: none;
+    background: none;
+    border: none;
+    color: var(--primary-color);
+    cursor: pointer;
+    font-size: 24px;
+}
+
+.mobile-navbar-menu {
+    display: flex;
+    flex-direction: column;
+    width: 100%;
+    background-color: var(--secondary-color);
+    border-radius: 10px;
+    max-height: 0;
+    overflow: hidden;
+    transition: max-height 0.4s ease-out, padding 0.4s ease-out;
+    padding-top: 0;
+    padding-bottom: 0;
+}
+
+.mobile-navbar-menu.open {
+    padding-top: 10px;
+    padding-bottom: 10px;
+}
+
+.mobile-navbar-menu input[type="text"],
+.mobile-navbar-menu input[type="search"] {
+    padding: 10px;
+    margin: 5px 0;
+    border: none;
+    background: none;
+    cursor: pointer;
+    transition: color 0.3s ease;
+    font-family: 'default-512', Arial, sans-serif;
+    color: var(--navbar-text-color);
+    text-decoration: none;
+    display: block;
+    width: 100%;
+    box-sizing: border-box;
+}
+
+.mobile-navbar-menu input[type="text"]:hover,
+.mobile-navbar-menu input[type="search"]:hover,
+.mobile-navbar-menu button:hover {
+    color: var(--navbar-hover-color);
+}
+
+@media screen and (max-width: 768px) {
+    .navbar-container {
+        display: none;
+    }
+    
+    .navbar-mobile {
+        display: flex;
+    }
+
+    .navbar-toggle {
+        display: block;
+    }
+}
+
+@media screen and (min-width: 769px) {
+    .mobile-navbar-menu {
+        display: none !important;
+    }
+}
+
+.navbar .buttonify{
+    display: block;
+    background-color: var(--background-color); /* penis haha lol  ja das isch psychose klass will buttons nei segged abunzdue*/
+    color: var(--text-color);
+    padding: 12px 20px;
+    text-decoration: none;
+    border-radius: 10px;
+    transition: background-color 0.3s ease;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
+    font-family: 'default-512', Arial, sans-serif;
+    border: none;
+}
+
+.navbar .buttonify:hover {
+    background-color: var(--hover-color);
+    color: var(--hover-text-color);
+}

BIN
website4/public/assets/fonts/.DS_Store


BIN
website4/public/assets/fonts/default.ttf


BIN
website4/public/assets/img/.DS_Store


BIN
website4/public/assets/img/code-is-ass.jpeg


BIN
website4/public/assets/img/dialon.png


BIN
website4/public/assets/img/force.png


BIN
website4/public/assets/img/fuck-main.jpeg


BIN
website4/public/assets/img/fuckjs.jpeg


BIN
website4/public/assets/img/jsmomentom.jpg


BIN
website4/public/assets/img/router1.jpg


BIN
website4/public/assets/img/router2.jpg


BIN
website4/public/assets/img/rover.png


BIN
website4/public/assets/img/ssc.jpg


BIN
website4/public/assets/img/wrong.png


+ 94 - 0
website4/public/assets/js/chat.js

@@ -0,0 +1,94 @@
+// chat container setup for maximum verwirrung weil ich kann das alles langsam nicht mehr junge die sprach macht kei sinn
+const chatContainer = document.getElementById('chat-container');
+const chatLog = document.getElementById('chat-log');
+const userInput = document.getElementById('user-input');
+let hasGreeted = false; // flag so we only say grǔtzi eimal und ned sächzgs mal junge das wäri fett weird
+
+// toggle chat open and closed again ????????????? i dont remember what i haben gesoffen hier
+function toggleChat() {
+    if (chatContainer.classList.contains('open')) {
+        chatContainer.classList.remove('open');
+        setTimeout(() => {
+            chatContainer.style.visibility = 'hidden';
+        }, 400); // match delay with css so it doesnt look wie abfall
+    } else {
+        chatContainer.style.visibility = 'visible';
+        chatContainer.classList.add('open');
+        
+        // the actuall saying grǔtzi miternaand gugus
+        if (!hasGreeted) {
+            displayMessage('Virtual Assistant', "Grǔtzi 🇨🇭 ! I'm your virtual assistant! Please tell me about your problem or what you need help with.");
+            hasGreeted = true;
+        }
+    }
+}
+
+// send message when enter key is pressed because who will press a button to send a message ???? are you a psychopat ?
+userInput.addEventListener('keypress', function(event) {
+    if (event.key === 'Enter') {
+        sendMessage();
+    }
+});
+
+// handle sending messages
+function sendMessage() {
+    const userMessage = userInput.value.trim();
+    if (userMessage) {
+        displayMessage('You', userMessage);
+        userInput.value = '';
+        setTimeout(() => catReply(userMessage), 1000); // delay for realism so the "assistant" can "think" about the reply
+    }
+}
+
+// put a message in the chat log will chat funktioniert ned ohni message history und so lol
+function displayMessage(sender, message) {
+    const messageElement = document.createElement('div');
+    messageElement.classList.add('chat-message');
+
+    const senderSpan = document.createElement('span');
+    senderSpan.classList.add('sender');
+    senderSpan.classList.add(sender === 'You' ? 'user' : 'virtual-assistant');
+    senderSpan.textContent = sender + ': ';
+    
+    const messageSpan = document.createElement('span');
+    messageSpan.textContent = message;
+    
+    messageElement.appendChild(senderSpan);
+    messageElement.appendChild(messageSpan);
+    chatLog.appendChild(messageElement);
+    chatLog.scrollTop = chatLog.scrollHeight;
+}
+
+// cat assistant category based matched replies
+function catReply(userMessage) {
+    const keywords = {
+        "help": ["meeeooow...? figure it out yourself! because that sounds like a you problem bahahahasdjkasadlkj 💀", "meeooww! welp too bad. help yourself bahasjdhaskjdhaskjdh", "mrrrow! idk either lol. go ask yourself maybe your smart if you use your brain instread of relying on a virtual assistant cat"],
+        "problem": ["meeooow, eh thats normal here, should've chosen someone else to host your stuff ngl lol", "mrow, contact sysadminier maybe idk? i am just cat or a teaput ???? idk what i am help aaaaaaa", "mreeow, tell me more ig... if you want idc lol"],
+        "default": ["meow", "meeooow!", "mew.", "mrow!", "meeow...", "meow, meow.", "mroww", "mlem"]
+    };
+
+    // generate a bs reply to fool user into thinking the cat assistant is actually doing something
+    function generateScrambledReply() {
+        const phrases = keywords["default"];
+        let scrambled = [];
+        const length = Math.floor(Math.random() * 3) + 3; // random length of reply 3-5 words
+        
+        for (let i = 0; i < length; i++) {
+            const randomPhrase = phrases[Math.floor(Math.random() * phrases.length)];
+            scrambled.push(randomPhrase);
+        }
+        return scrambled.join(" ");
+    }
+
+    // check for keywords in user message and decide what kind of blödsinn to say zu the schafseckel using the chat
+    let reply;
+    if (userMessage.toLowerCase().includes("help")) {
+        reply = keywords["help"][Math.floor(Math.random() * keywords["help"].length)];
+    } else if (userMessage.toLowerCase().includes("problem")) {
+        reply = keywords["problem"][Math.floor(Math.random() * keywords["problem"].length)];
+    } else {
+        reply = generateScrambledReply(); // generate scrambled reply for "default" case
+    }
+
+    displayMessage('Virtual Assistant', reply);
+}

+ 40 - 0
website4/public/assets/js/menu.js

@@ -0,0 +1,40 @@
+document.addEventListener('DOMContentLoaded', function () {
+    // menu overlay so we can open and close it bruh
+    const overlay = document.querySelector('.menu-overlay');
+    const hamburger = document.querySelector('.hamburger-menu');
+    
+    function toggleMenu() {
+        if (overlay.classList.contains('open')) {
+            overlay.classList.remove('open');
+            setTimeout(() => {
+                overlay.style.visibility = 'hidden';
+            }, 400); // match this delay with the css transition duration because ja isch halt so
+        } else {
+            overlay.style.visibility = 'visible';
+            overlay.classList.add('open');
+        }
+        hamburger.classList.toggle('open');
+        document.body.style.overflow = overlay.classList.contains('open') ? 'hidden' : ''; // no scrolling on the main page while menu is open
+    }
+
+    // if burger king menu button exists, hook it up to toggle the menu
+    if (hamburger) {
+        hamburger.addEventListener('click', function () {
+            toggleMenu();
+        });
+    }
+
+    // close menu when clicking a link inside it because so funktioniert das halt, pech gha wenns der nid passt lol 
+    if (overlay) {
+        overlay.querySelectorAll('a').forEach(link => {
+            link.addEventListener('click', () => {
+                overlay.classList.remove('open');
+                setTimeout(() => {
+                    overlay.style.visibility = 'hidden';
+                    hamburger.classList.remove('open');
+                    document.body.style.overflow = ''; // kei ahnig was das macht aber es het mis problem emol glöst
+                }, 400); // match transition duration ... again no clue what this actually does but it works so i'm not touching it
+            });
+        });
+    }
+});

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 16 - 0
website4/public/assets/svg/teleco.svg


Vissa filer visades inte eftersom för många filer har ändrats