Webdesign von Grund auf neu aufgebaut: Saubere Flex/Grid-Architektur, fehlerfreie HTML-Kartenstruktur und robuste Sidebar

This commit is contained in:
Alex Mueller 2026-08-29 15:58:38 +02:00
parent 989ccb4f6d
commit 029f31015e
5 changed files with 1123 additions and 2031 deletions

View file

@ -10,5 +10,5 @@
"streak_tage": 1,
"letzter_aktiver_tag": "2026-08-29",
"historie": [],
"zuletzt_aktualisiert": "2026-08-29T15:54:00.836247"
"zuletzt_aktualisiert": "2026-08-29T15:58:35.233410"
}

View file

@ -11,7 +11,7 @@ window.GAMIFICATION_DATA = {
"streak_tage": 1,
"letzter_aktiver_tag": "2026-08-29",
"historie": [],
"zuletzt_aktualisiert": "2026-08-29T15:54:00.836247"
"zuletzt_aktualisiert": "2026-08-29T15:58:35.233410"
};
window.GAMIFICATION_BADGES_KATALOG = {
"rechenkonegin": {

View file

@ -1,7 +1,7 @@
/**
* 🧭 NEXT-GEN SIDEBAR NAVIGATION & APP LAYOUT 🧭
* ===============================================
* Erzeugt eine moderne, responsive Sidebar auf der linken Seite
* 🧭 NEXT-GEN SIDEBAR COMPONENT 🧭
* =================================
* Rendert eine saubere, linksbündige Sidebar-Navigation
* für das Hauptportal und alle 27 Kapitel-Seiten.
*/
@ -9,9 +9,8 @@
const LEHRPFADE = [
{
id: "lehrpfad_1",
title: "🌱 Lehrpfad 1: Grundlagen",
title: "🌱 1. Grundlagen",
badge: "G01–G10",
color: "#059669",
items: [
{ id: "01_erste_schritte_taschenrechner", num: "G01", icon: "🧮", title: "Taschenrechner", path: "lehrpfad_1_grundlagen/01_erste_schritte_taschenrechner/index.html" },
{ id: "02_variablen_und_datentypen", num: "G02", icon: "📦", title: "Variablen & Typen", path: "lehrpfad_1_grundlagen/02_variablen_und_datentypen/index.html" },
@ -27,11 +26,10 @@
},
{
id: "lehrpfad_2",
title: "🏗️ Lehrpfad 2: OOP Einstieg",
title: "🏗️ 2. OOP Einstieg",
badge: "00–06",
color: "#4f46e5",
items: [
{ id: "00_fehlersuche_und_grundlagen", num: "00", icon: "🔍", title: "Fehlersuche & Debugging", path: "lehrpfad_2_oop_einstieg/00_fehlersuche_und_grundlagen/index.html" },
{ id: "00_fehlersuche_und_grundlagen", num: "00", icon: "🔍", title: "Fehlersuche & Debug", path: "lehrpfad_2_oop_einstieg/00_fehlersuche_und_grundlagen/index.html" },
{ id: "01_einstieg_klassen", num: "01", icon: "🏗️", title: "Einstieg in Klassen", path: "lehrpfad_2_oop_einstieg/01_einstieg_klassen/index.html" },
{ id: "02_init_und_self", num: "02", icon: "⚙️", title: "Konstruktor & self", path: "lehrpfad_2_oop_einstieg/02_init_und_self/index.html" },
{ id: "03_methoden_und_verhalten", num: "03", icon: "🏎️", title: "Methoden & Verhalten", path: "lehrpfad_2_oop_einstieg/03_methoden_und_verhalten/index.html" },
@ -44,9 +42,8 @@
},
{
id: "lehrpfad_3",
title: "🚀 Lehrpfad 3: Fortgeschritten",
title: "🚀 3. Fortgeschritten",
badge: "07–16",
color: "#7c3aed",
items: [
{ id: "07_referenzen_und_speicher", num: "07", icon: "🧠", title: "Referenzen & Speicher", path: "lehrpfad_3_fortgeschrittenes_oop/07_referenzen_und_speicher/index.html" },
{ id: "08_operator_overloading_dunder", num: "08", icon: "➕", title: "Operator Overloading", path: "lehrpfad_3_fortgeschrittenes_oop/08_operator_overloading_dunder/index.html" },
@ -71,33 +68,43 @@
}
function initSidebar() {
if (document.querySelector(".app-sidebar")) return;
const prefix = detectRootPrefix();
const currentPath = window.location.pathname;
const isRoot = prefix === "./";
// Wrap existing body content in .app-main if not wrapped yet
if (!document.querySelector(".app-main")) {
const mainWrapper = document.createElement("div");
mainWrapper.className = "app-main";
while (document.body.firstChild) {
mainWrapper.appendChild(document.body.firstChild);
}
document.body.appendChild(mainWrapper);
}
// Check if sidebar already exists
if (document.querySelector(".app-sidebar")) return;
// Gamification Data
const gData = window.GAMIFICATION_DATA || { xp: 0, level: 1, titel: "Code-Küken 🐣", geloeste_kapitel: [] };
const solvedSet = new Set(gData.geloeste_kapitel || []);
// 1. Erstelle Drawer-Toggle Button für Mobile
// 1. Mobile Drawer Toggle Button
const toggleBtn = document.createElement("button");
toggleBtn.type = "button";
toggleBtn.className = "sidebar-mobile-toggle";
toggleBtn.innerHTML = "<span>☰ Menü</span>";
document.body.prepend(toggleBtn);
document.body.appendChild(toggleBtn);
// 2. Erstelle Overlay für Mobile
// 2. Mobile Overlay
const overlay = document.createElement("div");
overlay.className = "sidebar-overlay";
document.body.prepend(overlay);
document.body.appendChild(overlay);
// 3. Erstelle Sidebar Container
// 3. Sidebar Element
const sidebar = document.createElement("aside");
sidebar.className = "app-sidebar";
let tracksHtml = "";
let navSectionsHtml = "";
LEHRPFADE.forEach(track => {
let itemsHtml = "";
track.items.forEach(item => {
@ -106,21 +113,21 @@
const isSolved = solvedSet.has(item.path.replace("/index.html", ""));
itemsHtml += `
<a href="${fullLink}" class="sidebar-item ${isActive ? 'active' : ''}">
<span class="sidebar-item-icon">${item.icon}</span>
<span class="sidebar-item-text">${item.num}. ${item.title}</span>
${isSolved ? '<span class="sidebar-solved-badge" title="Gelöst!">✅</span>' : ''}
<a href="${fullLink}" class="sidebar-link ${isActive ? 'active' : ''}">
<span class="sidebar-link-icon">${item.icon}</span>
<span class="sidebar-link-text">${item.num}. ${item.title}</span>
${isSolved ? '<span style="font-size: 0.75rem;">✅</span>' : ''}
</a>
`;
});
tracksHtml += `
<div class="sidebar-section">
<div class="sidebar-section-header">
navSectionsHtml += `
<div class="sidebar-group">
<div class="sidebar-group-title">
<span>${track.title}</span>
<span class="sidebar-section-badge" style="background: ${track.color}22; color: ${track.color};">${track.badge}</span>
<span style="background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 99px; font-size: 0.7rem;">${track.badge}</span>
</div>
<div class="sidebar-nav-list">
<div style="display: flex; flex-direction: column; gap: 2px;">
${itemsHtml}
</div>
</div>
@ -128,42 +135,37 @@
});
sidebar.innerHTML = `
<div class="sidebar-brand">
<a href="${prefix}index.html" class="sidebar-brand-link">
<div class="sidebar-brand-logo">🐍</div>
<div class="sidebar-header">
<a href="${prefix}index.html" style="display: flex; align-items: center; gap: 10px; text-decoration: none; color: white;">
<div class="sidebar-logo">🐍</div>
<div>
<div class="sidebar-brand-title">Python Lernportal</div>
<div class="sidebar-brand-sub">Interaktiver Kurs</div>
<div class="sidebar-title">Python Portal</div>
<div class="sidebar-subtitle">Lernplattform</div>
</div>
</a>
</div>
<div class="sidebar-quick-nav">
<a href="${prefix}index.html#tutorial" class="sidebar-quick-link">📖 Anleitung & Workflow</a>
<a href="${prefix}index.html#python-live-playground" class="sidebar-quick-link">⚡ Live-Playground</a>
<a href="${prefix}index.html#error-interpreter-widget" class="sidebar-quick-link">🩺 Fehler-Dolmetscher</a>
<a href="${prefix}index.html#zertifikate" class="sidebar-quick-link">🏆 Zertifikate</a>
<div style="padding: 10px 14px; border-bottom: 1px solid var(--border-dark); display: flex; flex-direction: column; gap: 2px; background: rgba(0,0,0,0.15);">
<a href="${prefix}index.html" class="sidebar-link">🏠 Startseite</a>
<a href="${prefix}index.html#tutorial" class="sidebar-link">📖 Tutorial & Workflow</a>
<a href="${prefix}index.html#zertifikate" class="sidebar-link">🏆 Zertifikate</a>
</div>
<div class="sidebar-content">
${tracksHtml}
<div class="sidebar-nav">
${navSectionsHtml}
</div>
<div class="sidebar-footer">
<div class="sidebar-user-card">
<div class="sidebar-user-avatar">🐣</div>
<div class="sidebar-user-info">
<div class="sidebar-user-name">Level ${gData.level || 1}</div>
<div class="sidebar-user-title">${gData.titel || "Code-Küken"}</div>
</div>
<div class="sidebar-user-xp">${gData.xp || 0} XP</div>
<div style="display: flex; align-items: center; justify-content: space-between;">
<div style="font-size: 0.85rem; font-weight: 700; color: white;">⭐ Level ${gData.level || 1}</div>
<div style="font-size: 0.82rem; font-weight: 700; color: #38bdf8;">${gData.xp || 0} XP</div>
</div>
</div>
`;
document.body.prepend(sidebar);
// Toggle Events
// Toggle Handler
toggleBtn.addEventListener("click", () => {
sidebar.classList.toggle("open");
overlay.classList.toggle("active");

File diff suppressed because it is too large Load diff

1117
index.html

File diff suppressed because it is too large Load diff