Browse Source

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

UMTS at Teleco 11 tháng trước cách đây
commit
f402e0c96a
100 tập tin đã thay đổi với 4813 bổ sung0 xóa
  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


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 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


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 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


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 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
+            });
+        });
+    }
+});

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 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
+            });
+        });
+    }
+});

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 16 - 0
website4/public/assets/svg/teleco.svg


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác