update tasks and sidebar

This commit is contained in:
Lukas Cremer
2026-01-25 22:01:09 +01:00
parent c0b29dc368
commit 8356ae9ebe
4 changed files with 176 additions and 91 deletions

View File

@@ -5,6 +5,7 @@ const API_BASE = '';
let totalPoints = 0;
let tasks = [];
let chapters = [];
let chapterDescriptions = {}; // Map von chapter name zu description
let activeChapter = null;
// Initialisiere die App
@@ -12,7 +13,7 @@ async function init() {
await loadTasks();
extractChapters();
calculateTotalPoints();
renderTabs();
renderSidebar();
renderTasks();
updateProgress();
}
@@ -40,9 +41,15 @@ async function loadTasks() {
// Extrahiere alle Chapters aus den Tasks
function extractChapters() {
const chapterSet = new Set();
chapterDescriptions = {};
tasks.forEach(task => {
if (task.chapter) {
chapterSet.add(task.chapter);
// Speichere die erste gefundene Beschreibung für jedes Kapitel
if (task.chapterDescription && !chapterDescriptions[task.chapter]) {
chapterDescriptions[task.chapter] = task.chapterDescription;
}
}
});
chapters = Array.from(chapterSet).sort();
@@ -56,32 +63,37 @@ function extractChapters() {
}
}
// Rendere Tabs für alle Chapters
function renderTabs() {
const tabsContainer = document.getElementById('tabsContainer');
tabsContainer.innerHTML = '';
// Rendere Sidebar für alle Chapters
function renderSidebar() {
const sidebar = document.getElementById('sidebar');
sidebar.innerHTML = '';
// Zeige Tabs nur an, wenn es Chapters gibt
// Zeige Sidebar nur an, wenn es Chapters gibt
if (chapters.length === 0) {
tabsContainer.style.display = 'none';
sidebar.style.display = 'none';
return;
}
tabsContainer.style.display = 'flex';
sidebar.style.display = 'block';
chapters.forEach(chapter => {
const tabButton = document.createElement('button');
tabButton.className = `tab-button ${activeChapter === chapter ? 'active' : ''}`;
tabButton.textContent = chapter;
tabButton.onclick = () => switchChapter(chapter);
tabsContainer.appendChild(tabButton);
const sidebarItem = document.createElement('div');
sidebarItem.className = `sidebar-item ${activeChapter === chapter ? 'active' : ''}`;
sidebarItem.onclick = () => switchChapter(chapter);
const title = document.createElement('div');
title.className = 'sidebar-item-title';
title.textContent = chapter;
sidebarItem.appendChild(title);
sidebar.appendChild(sidebarItem);
});
}
// Wechsle zu einem anderen Chapter
function switchChapter(chapter) {
activeChapter = chapter;
renderTabs();
renderSidebar();
renderTasks();
}
@@ -96,7 +108,17 @@ function getTasksForActiveChapter() {
// Rendere Aufgaben
function renderTasks() {
const container = document.getElementById('taskContainer');
const descriptionEl = document.getElementById('chapterDescription');
container.innerHTML = '';
// Zeige Kapitel-Beschreibung an
if (activeChapter && chapterDescriptions[activeChapter]) {
descriptionEl.textContent = chapterDescriptions[activeChapter];
descriptionEl.style.display = 'block';
} else {
descriptionEl.style.display = 'none';
}
const tasksToShow = getTasksForActiveChapter();
@@ -203,7 +225,7 @@ async function checkAnswer(taskId) {
// Nach Animation die Aufgabe entfernen
setTimeout(() => {
renderTabs();
renderSidebar();
renderTasks();
updateProgress();
}, 1500);
@@ -214,9 +236,9 @@ async function checkAnswer(taskId) {
input.focus();
}
// Rendere Tabs und Tasks neu, um den aktuellen Status anzuzeigen (nur wenn nicht korrekt)
// Rendere Sidebar und Tasks neu, um den aktuellen Status anzuzeigen (nur wenn nicht korrekt)
if (!data.correct) {
renderTabs();
renderSidebar();
renderTasks();
updateProgress();
}

View File

@@ -7,34 +7,38 @@
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<header>
<h1>🌟 MathQuest 🌟</h1>
<div class="points-display">
<div class="points-label">Quest-Punkte</div>
<div class="points-value" id="totalPoints">0</div>
</div>
</header>
<div class="app-wrapper">
<aside class="sidebar" id="sidebar">
<!-- Sidebar wird hier dynamisch eingefügt -->
</aside>
<div class="main-content">
<div class="container">
<header>
<h1>🌟 MathQuest 🌟</h1>
<div class="points-display">
<div class="points-label">Quest-Punkte</div>
<div class="points-value" id="totalPoints">0</div>
</div>
</header>
<div class="progress-section">
<div class="progress-label">Fortschritt</div>
<div class="progress-bar-container">
<div class="progress-bar" id="progressBar"></div>
</div>
<div class="progress-text" id="progressText">0 / 100</div>
</div>
<div class="progress-section">
<div class="progress-label">Fortschritt</div>
<div class="progress-bar-container">
<div class="progress-bar" id="progressBar"></div>
</div>
<div class="progress-text" id="progressText">0 / 100</div>
</div>
<div class="task-section">
<h2>Mathe-Aufgaben</h2>
<div class="tabs-container" id="tabsContainer">
<!-- Tabs werden hier dynamisch eingefügt -->
</div>
<div id="taskContainer" class="task-container">
<!-- Aufgaben werden hier dynamisch eingefügt -->
<div class="task-section">
<div id="chapterDescription" class="chapter-description"></div>
<div id="taskContainer" class="task-container">
<!-- Aufgaben werden hier dynamisch eingefügt -->
</div>
</div>
<div class="message" id="message"></div>
</div>
</div>
<div class="message" id="message"></div>
</div>
<script src="app.js"></script>

View File

@@ -8,13 +8,66 @@ body {
font-family: 'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', cursive, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
padding: 0;
margin: 0;
color: #333;
}
.app-wrapper {
display: flex;
min-height: 100vh;
gap: 20px;
padding: 20px;
}
.sidebar {
width: 280px;
background: white;
border-radius: 20px;
padding: 20px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
position: sticky;
top: 20px;
height: fit-content;
max-height: calc(100vh - 40px);
overflow-y: auto;
}
.sidebar-item {
padding: 15px;
margin-bottom: 10px;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s ease;
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
border: 2px solid transparent;
}
.sidebar-item:hover {
transform: translateX(5px);
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
}
.sidebar-item.active {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-color: rgba(255, 255, 255, 0.3);
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.sidebar-item-title {
font-size: 1.1em;
font-weight: bold;
margin-bottom: 5px;
}
.main-content {
flex: 1;
min-width: 0;
}
.container {
max-width: 800px;
margin: 0 auto;
max-width: 100%;
background: white;
border-radius: 20px;
padding: 30px;
@@ -93,50 +146,16 @@ h1 {
margin-top: 30px;
}
.task-section h2 {
color: #667eea;
margin-bottom: 20px;
text-align: center;
font-size: 1.8em;
}
.tabs-container {
display: flex;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
justify-content: center;
}
.tab-button {
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
color: #333;
border: none;
padding: 12px 20px;
.chapter-description {
background: linear-gradient(135deg, #e8f5e9 0%, #fff3e0 100%);
padding: 20px;
border-radius: 15px;
margin-bottom: 25px;
font-size: 1.1em;
border-radius: 10px;
cursor: pointer;
font-family: 'Comic Sans MS', cursive;
font-weight: bold;
transition: all 0.3s ease;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
position: relative;
}
.tab-button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
}
.tab-button.active {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.tab-button.active:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5);
line-height: 1.6;
color: #555;
border-left: 4px solid #667eea;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.task-container {
@@ -228,6 +247,7 @@ h1 {
margin: 20px 0;
color: #333;
font-weight: bold;
white-space: pre-line;
}
.task-input-group {
@@ -332,6 +352,30 @@ h1 {
color: white;
}
@media (max-width: 900px) {
.app-wrapper {
flex-direction: column;
padding: 10px;
}
.sidebar {
width: 100%;
position: relative;
top: 0;
max-height: none;
display: flex;
gap: 10px;
overflow-x: auto;
overflow-y: hidden;
padding: 15px;
}
.sidebar-item {
min-width: 200px;
margin-bottom: 0;
}
}
@media (max-width: 600px) {
.container {
padding: 20px;
@@ -352,4 +396,17 @@ h1 {
.task-button {
width: 100%;
}
.sidebar {
padding: 10px;
}
.sidebar-item {
min-width: 180px;
padding: 12px;
}
.sidebar-item-title {
font-size: 1em;
}
}