File size: 32,786 Bytes
5cf774c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 | const assets = {
calendar: "assets/materials/mq3zhq9n-clipboard.png",
slide: "assets/materials/mq3zhqat-clipboard.png",
notes: "assets/materials/mq3zhqbu-clipboard.png",
evidence: "assets/materials/mq3zhqdk-clipboard.png",
recent: [
"assets/materials/mq3zhqe0-clipboard.png",
"assets/materials/mq3zhqe3-clipboard.png",
"assets/materials/mq3zhqea-clipboard.png",
"assets/materials/mq3zhqeg-clipboard.png"
]
};
const routes = ["overview", "uploads", "canvas", "calendar", "learning-plan", "gaps", "flashcards", "quiz", "reminders"];
const app = document.querySelector("#app");
const navList = document.querySelector("#navList");
const toast = document.querySelector("#toast");
const pageHead = (title, subtitle, actions = "") => `
<header class="page-head">
<div><h1>${title}</h1><p>${subtitle}</p></div>
<div class="head-actions">${actions}</div>
</header>`;
const panel = (title, body, extra = "", className = "") => `
<section class="panel ${className}">
<div class="panel-head"><h2>${title}</h2>${extra || '<span class="more">...</span>'}</div>
${body}
</section>`;
function overviewPage() {
const agenda = [
["09:00", "Mehrsprachigkeitsdidaktik", "Seminar im Hörsaal 3 · Sprachbewusstsein & Transferstrategien", "book-open", "green"],
["11:30", "Englischdidaktik", "Übung · Classroom Interaction & Feedback", "globe", "blue"],
["13:00", "Mittagspause", "Zeit für gutes Essen und einen kurzen Spaziergang am Rhein", "fork-knife", "rose"],
["15:00", "Lernblock Bildungspsychologie", "Kapitel 4: Motivation & Selbstregulation · Karteikarten erstellen", "brain", "aubergine"],
["17:30", "Familie & Freunde", "Abendessen bei Mama & Papa", "users-three", "gold"]
].map(([time, title, sub, icon, tone]) => `
<button class="day-entry ${tone}" data-route="${time === "15:00" ? "canvas" : "calendar"}">
<time>${time}</time>
<span class="day-icon"><i class="ph ph-${icon}"></i></span>
<span><strong>${title}</strong><small>${sub}</small></span>
<i class="ph ph-caret-right entry-arrow"></i>
</button>`).join("");
return `
<div class="josephine-home">
<section class="josephine-hero">
<img src="assets/hero/josephine-mainz-morning.png" alt="Josephine lernt an einem sonnigen Morgen in Mainz, umgeben von Erinnerungen an Familie, Freunde und ihr Lieblingspferd.">
<div class="weather-line">Dienstag, 7. Juni <span>·</span> Mainz <span>·</span> 18° <i class="ph ph-sun"></i></div>
<div class="hero-copy">
<h1>Josephine<br>Wendland</h1>
<p class="hero-motto">Lehren. Verstehen. Verbinden.</p>
<h2>Guten Morgen, Josephine</h2>
<p>Heute ist ein guter Tag, etwas zu lernen,<br>zu wachsen und Menschen zu inspirieren.</p>
</div>
</section>
<section class="daily-journal">
<div class="journal-agenda">
<header><i class="ph ph-calendar-blank"></i><h2>Mein Tag</h2><span>7. Juni</span></header>
<div class="day-list">${agenda}</div>
</div>
<aside class="today-important">
<header><i class="ph ph-star"></i><h2>Heute wichtig</h2></header>
<button class="important-row deadline" data-route="calendar">
<span class="important-icon"><i class="ph ph-calendar-dots"></i></span>
<span><small>Deadline</small><strong>Reflexionsbericht Mehrsprachigkeit</strong><em>Abgabe: Freitag, 10. Juni</em></span>
<i class="ph ph-caret-right"></i>
</button>
<button class="important-row gap" data-route="gaps">
<span class="important-icon"><i class="ph ph-target"></i></span>
<span><small>Wissenslücke</small><strong>Selbstwirksamkeit verstehen</strong><em>Wiederholen · Karte 24–27</em></span>
<i class="ph ph-caret-right"></i>
</button>
<button class="important-row next" data-route="canvas">
<span class="important-icon"><i class="ph ph-book-open"></i></span>
<span><small>Nächster Schritt</small><strong>Lernen fortsetzen</strong><em>Bildungspsychologie · Kapitel 4</em></span>
<i class="ph ph-caret-right"></i>
</button>
<p class="journal-note">Kleine Schritte jeden Tag<br>führen zu großen Veränderungen.</p>
</aside>
</section>
</div>`;
}
function uploadsPage() {
const extracted = `Sprachbewusstheit fördern (VL 07)
Begriff: Fähigkeit, Sprache(n) als System(e) wahrzunehmen und über Sprache(n) nachzudenken.
Ziele:
- Sensibilisierung für sprachliche Strukturen und Variation
- Vergleich von Sprachen als Ressourcen nutzen
- Transferstrategien entwickeln
Vergleich DE - FR
DE: Ich gehe in die Schule.
FR: Je vais à l'école.
Gemeinsamkeiten: Subjekt - Verb - Objekt
Unterschiede: Artikel, Präpositionen, Akkordanz
Didaktische Prinzipien:
1) Sprachenvergleich
2) Bewusstmachung
3) Funktionaler Einsatz im Fachunterricht`;
return pageHead("Materialien", "Notizen, Folien und Kalender an einem ruhigen Ort.", `
<button class="button secondary" id="addFiles">Dateien hinzufügen</button>
<button class="button primary" data-route="canvas">In Arbeitsfläche öffnen</button>
`) + `
<div class="uploads-grid">
${panel("Upload-Queue (3)", `<div class="queue-list">
<div class="queue-item selected"><div class="queue-title"><strong>Mehrsprachigkeitsdidaktik_VL07.pdf</strong><span class="badge green">100%</span></div><div class="progress"><span style="width:100%"></span></div><small>OCR abgeschlossen · 32 Seiten</small></div>
<div class="queue-item"><div class="queue-title"><strong>Englischdidaktik_Orthografie.pdf</strong><span class="badge blue">76%</span></div><div class="progress"><span style="width:76%;background:var(--blue)"></span></div><small>OCR läuft · Seite 3 von 11</small></div>
<div class="queue-item"><div class="queue-title"><strong>Bildungspsychologie_Notizen.jpg</strong><span class="badge">0%</span></div><div class="progress"><span style="width:0%"></span></div><small>Wartet in der Queue</small></div>
<div class="dropzone" id="dropzone"><strong>Dateien hier ablegen</strong><br><small>PDF, JPG oder PNG · Verarbeitung bleibt lokal</small></div>
</div>`, '<span class="badge green">Lokal</span>', "upload-queue")}
${panel("Mehrsprachigkeitsdidaktik_VL07.pdf", `<div class="doc-review">
<div class="doc-pane"><div class="doc-toolbar"><button class="icon-button">‹</button><span>4 / 32</span><button class="icon-button">›</button><span>100%</span><button class="icon-button">↗</button></div><div class="document-page"><img src="${assets.slide}" alt="Vorlesungsfolie zu Scaffolding im mehrsprachigen Unterricht"></div></div>
<div class="note-pane"><img src="${assets.notes}" alt="Handschriftliche Notizen zu Scaffolding im mehrsprachigen Unterricht"></div>
</div>`, '<span class="badge blue">Seite 4 verknüpft</span>')}
${panel("OCR-Extraktion", `<div class="panel-body ocr-panel">
<div class="language-tabs"><button class="badge green">Deutsch 99%</button><button class="badge blue">Französisch 82%</button><button class="badge">Englisch 12%</button></div>
<div class="confidence">Konfidenz der Seite: <strong>93%</strong> · 7 Markierungen prüfen</div>
<label class="field"><span class="label">Extrahierter Text</span><textarea id="ocrText">${extracted}</textarea></label>
<div class="row" style="justify-content:space-between"><span class="badge amber">Niedrige Konfidenz: Akkordanz</span><button class="button secondary" id="reviewAll">Alle prüfen</button></div>
<div class="ocr-actions"><button class="button secondary">Verwerfen</button><button class="button primary" id="saveOcr">Übernehmen & speichern</button></div>
<div class="trust-inline">Speichern in: Mehrsprachigkeitsdidaktik · nur lokal</div>
</div>`, '<span class="badge green">Abgeschlossen</span>')}
</div>`;
}
function canvasPage() {
const thumbs = [assets.recent[0], assets.recent[1], assets.slide, assets.recent[2], assets.recent[3]]
.map((src, i) => `<button class="slide-thumb ${i === 2 ? "active" : ""}" data-slide="${i}"><img src="${src}" alt="Materialvorschau ${i + 1}"></button>`).join("");
return `<div class="canvas-page">
<header class="canvas-head">
<h1>Smart Study Canvas <span>Mehrsprachigkeitsdidaktik / Woche 7</span></h1>
<div class="head-actions"><button class="button secondary">Verknüpfungen</button><button class="button secondary">Notiz hinzufügen</button><button class="button secondary">Exportieren</button></div>
</header>
<div class="canvas-grid">
${panel("Vorlesungsfolien", `<div class="slide-workspace"><div class="slide-thumbs">${thumbs}</div><div class="slide-main"><img id="mainSlide" src="${assets.slide}" alt="Vorlesungsfolie Scaffolding"></div></div>`)}
${panel("Handschriftliche Notizen", `<div class="notes-main"><img src="${assets.notes}" alt="Maya Hoffmanns handschriftliche Scaffolding-Notizen"></div>`, '<span class="badge blue">4 semantische Links</span>')}
${panel("AI-Copilot", `<div class="chat"><div class="messages" id="messages">
<div class="message user">Wie hängen Translanguaging und Scaffolding zusammen?</div>
<div class="message ai"><strong>Maya</strong><br>Scaffolding schafft temporäre sprachliche und kognitive Stützen. Translanguaging erlaubt Lernenden, ihr gesamtes sprachliches Repertoire für Bedeutungsbildung zu nutzen. Zusammen fördern sie fachliche Teilhabe, ohne die Zielsprache auszublenden.<div class="language-tabs"><span class="badge green">Folie 14</span><span class="badge blue">Notiz S. 1</span></div></div>
<div class="alert-card"><strong>Fehlendes Konzept erkannt: Interlanguage</strong>Die Unterscheidung zur Interlanguage fehlt in deinen verknüpften Notizen.<div class="language-tabs"><button class="badge">Konzept erklären</button><button class="badge">Quelle suchen</button><button class="badge">Karte erstellen</button></div></div>
</div><form class="chat-compose" id="chatForm"><input id="chatInput" placeholder="Stelle eine Frage zu deinen Materialien..." required><button class="button primary" aria-label="Senden">➤</button></form></div>`, '<span class="badge green">Lokal · Quellengebunden</span>')}
</div>
</div>`;
}
function calendarPage() {
const cells = Array.from({length: 35}, () => "<div></div>").join("");
const roadmapRows = [
["Mehrsprachigkeitsdidaktik","on,on,on,,blue,blue,,"],
["Englischdidaktik","blue,blue,,on,on,,,"],
["Französischdidaktik",",amber,amber,,on,on,,"],
["Bildungspsychologie","on,,blue,blue,,on,on,on"]
].map(([name, states]) => `<b>${name}</b>${states.split(",").map(s => `<span class="${s}"></span>`).join("")}`).join("");
return pageHead("Kalender & Lernplan", "Geprüfte Termine, realistische Lernblöcke und dein 8-Tage-Fokus.", `
<button class="button secondary" id="reviewExtractions">Extraktionen prüfen · 3</button>
<button class="button primary" id="planBlock">Lernblock planen</button>
`) + `
<div class="calendar-grid">
${panel("Wochenplan · 7.-11. Juni", `<div class="week-grid">
<div></div>${["Di 7.","Mi 8.","Do 9.","Fr 10.","Sa 11."].map(d=>`<div class="day">${d}</div>`).join("")}
${["09:00","10:00","11:00","12:00","13:00","14:00","15:00"].map(t=>`<div class="time">${t}</div>`).join("")}${cells}
<div class="event" style="grid-column:2;grid-row:2/4"><strong>09:00</strong><br>Mehrsprachigkeitsdidaktik<br>Seminar</div>
<div class="event amber" style="grid-column:3;grid-row:3/5"><strong>10:00</strong><br>Hausarbeit<br>Quellenarbeit</div>
<div class="event blue" style="grid-column:4;grid-row:4/6"><strong>11:00</strong><br>Französischdidaktik<br>Séance 5</div>
<div class="event" style="grid-column:5;grid-row:2/5"><strong>09:00</strong><br>Fachdidaktik Deutsch<br>Portfolio</div>
<div class="event blue" style="grid-column:6;grid-row:3/5"><strong>10:00</strong><br>Lerngruppe<br>Bibliothek</div>
</div><div class="roadmap"><h3>8-Tage-Prüfungsroadmap</h3><div class="roadmap-grid"><b></b>${["Di 7","Mi 8","Do 9","Fr 10","Sa 11","So 12","Mo 13","Di 14"].map(d=>`<b>${d}</b>`).join("")}${roadmapRows}</div><p class="muted" style="font-size:10px">Fokus: Hausarbeit abschließen → Französischdidaktik wiederholen → Prüfungssimulation</p></div>`, '<span class="badge green">72% geplant</span>', "week-calendar")}
<div class="stack">
${panel("Heute · 5 Std. 30 Min.", `<div class="panel-body"><div class="today-block"><strong>09:00-10:30 · Seminarfolien</strong><small>Translanguaging und Scaffolding verknüpfen</small></div><div class="today-block"><strong>11:30-13:00 · Reading response</strong><small>Englischdidaktik · Kapitel 4</small></div><div class="today-block"><strong>15:00-16:30 · Retrieval Practice</strong><small>Bildungspsychologie · Lernkarten 31-54</small></div></div>`, '<span class="badge green">Im Plan</span>')}
${panel("Geprüfte Extraktionen", `<div class="panel-body"><div class="extraction-row"><span>10. Juni</span><strong>Hausarbeit abgeben</strong><span class="badge amber">Bestätigt</span></div><div class="extraction-row"><span>14. Juni</span><strong>Französischdidaktik Prüfung</strong><span class="badge blue">Kalender</span></div><div class="extraction-row"><span>19. Juni</span><strong>Portfolio Deutsch</strong><span class="badge green">Bestätigt</span></div><img class="calendar-asset" src="${assets.calendar}" alt="Handschriftlicher Kalender Juni 2025"></div>`, '<span class="badge">3 aus PDF</span>')}
</div>
</div>`;
}
function flashcardsPage() {
const decks = [
["Mehrsprachigkeitsdidaktik",48,"18 fällig · zuletzt heute",72],
["Englischdidaktik",36,"Nächste Wiederholung morgen",58],
["Französischdidaktik",42,"Nächste Wiederholung morgen",44],
["Bildungspsychologie",61,"Nächste Wiederholung morgen",81],
["Fachdidaktik Deutsch",27,"Nächste Wiederholung morgen",36]
].map(([name,count,sub,pct],i)=>`<div class="deck-row ${i===0?"selected":""}" data-deck="${name}"><strong>${name} · ${count} Karten</strong><small>${sub}</small><div class="progress"><span style="width:${pct}%"></span></div></div>`).join("");
return pageHead("Karteikarten", "Quellengebundene Karten bearbeiten, lernen und exportieren.", `
<button class="button secondary" id="generateCards">Aus Quellen generieren</button>
<button class="button primary" id="learnCards">12 Karten lernen</button>
`) + `
<div class="cards-grid">
${panel("Meine Decks", `<div>${decks}</div>`)}
${panel("Karte bearbeiten · 12 von 48", `<div class="panel-body">
<div class="field question"><label for="cardQuestion">Frage</label><textarea id="cardQuestion">Wie unterscheidet sich Translanguaging vom klassischen Code-Switching?</textarea></div>
<div class="field answer"><label for="cardAnswer">Antwort</label><textarea id="cardAnswer">Translanguaging beschreibt die flexible Nutzung des gesamten sprachlichen Repertoires zur Bedeutungsbildung. Code-Switching bezeichnet dagegen meist den situativen Wechsel zwischen getrennt gedachten Sprachen.</textarea></div>
<div class="field"><label>Quellen</label><div class="source-box">▣ Mehrsprachigkeitsdidaktik_Woche_7.pdf · Folie 14<br>▤ Notizen_Scaffolding_03-06.jpg · Seite 1</div><div class="evidence-strip"><img src="${assets.evidence}" alt="Quellenausschnitt aus einer Notiz"><img src="${assets.notes}" alt="Handschriftliche Evidenz zu Scaffolding"></div></div>
<div class="language-tabs"><span class="badge green">Translanguaging</span><span class="badge blue">Code-Switching</span><span class="badge">Woche 7</span></div>
<div class="row" style="justify-content:space-between"><button class="button danger" id="deleteCard">Karte löschen</button><button class="button primary" id="saveCard">Änderungen speichern</button></div>
</div>`)}
${panel("Vorschau & Export", `<div class="panel-body stack"><div class="card-preview" id="cardPreview"><div class="front"><small>Vorderseite</small><strong>Wie unterscheidet sich Translanguaging vom klassischen Code-Switching?</strong><span class="muted">Klicken zum Umdrehen</span></div><div class="back"><small>Rückseite</small><p>Translanguaging nutzt das gesamte sprachliche Repertoire flexibel. Code-Switching beschreibt den situativen Wechsel zwischen getrennt gedachten Sprachen.</p></div></div><div class="divider"></div><h3 style="font-family:var(--serif);margin:2px 0">Deck exportieren</h3><span class="muted" style="font-size:11px">48 Karten · Quellen enthalten · DE</span><div class="export-list"><button class="button" data-export="Anki">Anki (.apkg)</button><button class="button" data-export="CSV">CSV</button><button class="button" data-export="PDF">PDF zum Drucken</button></div><small class="muted">Letzte Generierung: heute, 10:42 · vollständig lokal</small></div>`)}
</div>`;
}
function quizPage() {
return pageHead("Quizmodus", "Prüfungssimulation · Mehrsprachigkeitsdidaktik", `<button class="button secondary" id="endQuiz">Simulation beenden</button>`) + `
<div class="quiz-grid">
${panel("Frage 7 von 12", `<div class="quiz-content">
<div class="quiz-meta"><span class="muted">Fortschritt · <span id="quizProgressText">58%</span></span><span class="badge amber">Schwierigkeit: Anspruchsvoll</span></div>
<div class="progress"><span id="quizProgress" style="width:58%"></span></div>
<h2 class="quiz-question">Welche Aussage beschreibt den didaktischen Nutzen von Translanguaging am präzisesten?</h2>
<div class="answers" id="answers">
<button class="answer-option" data-answer="A"><span class="answer-letter">A</span><span>Es verhindert den Wechsel zwischen Unterrichtssprachen vollständig.</span></button>
<button class="answer-option" data-answer="B"><span class="answer-letter">B</span><span><strong>Es aktiviert das gesamte sprachliche Repertoire zur Bedeutungsbildung und fachlichen Teilhabe.</strong></span></button>
<button class="answer-option" data-answer="C"><span class="answer-letter">C</span><span>Es ersetzt fachsprachliche Lernziele durch alltagssprachliche Kommunikation.</span></button>
<button class="answer-option" data-answer="D"><span class="answer-letter">D</span><span>Es ist ausschließlich für den Fremdsprachenunterricht geeignet.</span></button>
</div>
<div class="explanation" id="quizExplanation" hidden><h3 id="answerState">Richtig beantwortet</h3><p>Translanguaging nutzt vorhandene sprachliche Ressourcen gezielt als Brücke zum fachlichen Verstehen. Die Zielsprache bleibt wichtig, wird aber nicht als isoliertes System behandelt.</p><div class="source-citation">Quelle: Mehrsprachigkeitsdidaktik_Woche_7.pdf · Folie 14<br>„Dynamische Nutzung des gesamten sprachlichen Repertoires zur Bedeutungskonstruktion.“</div><div class="row" style="justify-content:space-between;margin-top:14px"><small class="muted" id="chosenAnswer"></small><button class="button primary" id="nextQuestion">Nächste Frage →</button></div></div>
</div>`, '<span class="more">...</span>', "quiz-card")}
<div class="stack">
${panel("Simulationsstatus", `<div class="panel-body"><div class="stats-grid"><div class="stat"><strong id="correctCount">5</strong><small>richtig</small></div><div class="stat"><strong id="wrongCount">1</strong><small>falsch</small></div><div class="stat"><strong id="hitRate">82%</strong><small>Trefferquote</small></div><div class="stat"><strong id="timer">06:42</strong><small>verbleibend</small></div></div></div>`)}
${panel("Schwierigkeit", `<div class="panel-body"><div class="difficulty"><button data-level="Adaptiv">Adaptiv</button><button data-level="Mittel">Mittel</button><button class="active" data-level="Anspruchsvoll">Anspruchsvoll</button></div><p class="muted" style="font-size:11px">Die nächsten Fragen gewichten deine Wissenslücken stärker.</p></div>`)}
${panel("Prüfungsfokus", `<div class="panel-body"><div class="focus-list"><div><span class="badge red">Lücke</span> Interlanguage</div><div><span class="badge amber">Prüfen</span> Scaffolding</div><div><span class="badge green">Sicher</span> Translanguaging</div></div><div class="divider" style="margin:14px 0"></div><small class="muted">12 Fragen · 15 Minuten<br>Nur aus 3 ausgewählten lokalen Quellen</small></div>`)}
</div>
</div>`;
}
function learningPlanPage() {
return pageHead("Mein Lernplan", "Ein realistischer Plan, der zu Josephines Woche passt.", `
<button class="button secondary" data-route="calendar">Kalender ansehen</button>
<button class="button primary" data-route="canvas">Lernblock starten</button>
`) + `
<div class="quiet-page">
<section class="plan-intro">
<span class="eyebrow">Prüfung in 8 Tagen</span>
<h2>Diese Woche zählt Beständigkeit,<br>nicht Perfektion.</h2>
<p>StudyFlow verbindet deine Termine, Materialien und offenen Themen zu kleinen, machbaren Schritten.</p>
</section>
<div class="plan-days">
<button data-route="canvas"><time>Heute</time><strong>Grundlagen wiederholen</strong><span>Mehrsprachigkeitsdidaktik · 75 Min.</span></button>
<button data-route="flashcards"><time>Morgen</time><strong>Scaffolding vertiefen</strong><span>Folien, Notizen und 12 Karten · 60 Min.</span></button>
<button data-route="quiz"><time>Donnerstag</time><strong>Formative Bewertung üben</strong><span>Quiz und Reflexion · 45 Min.</span></button>
<button data-route="gaps"><time>Freitag</time><strong>Wissenslücken schließen</strong><span>Selbstwirksamkeit und Interlanguage · 60 Min.</span></button>
</div>
</div>`;
}
function gapsPage() {
return pageHead("Wissenslücken", "Was noch unsicher ist, wird hier verständlich und machbar.", `
<button class="button primary" data-route="quiz">Kurzes Quiz starten</button>
`) + `
<div class="quiet-page two-column">
<section class="focus-story">
<span class="eyebrow">Heute empfohlen</span>
<h2>Selbstwirksamkeit verstehen</h2>
<p>In deinen Notizen fehlt noch die Verbindung zwischen Selbstwirksamkeit, Motivation und Lernerfolg.</p>
<button class="button primary" data-route="canvas">Mit Quellen erklären</button>
</section>
<section class="calm-list">
<button data-route="canvas"><span class="signal red"></span><span><strong>Interlanguage</strong><small>Nur indirekt in drei Quellen erklärt</small></span><em>Hoch</em></button>
<button data-route="flashcards"><span class="signal amber"></span><span><strong>Scaffolding</strong><small>Zwei unsichere Karten</small></span><em>Mittel</em></button>
<button data-route="canvas"><span class="signal green"></span><span><strong>Translanguaging</strong><small>Quellenlage vollständig</small></span><em>Sicher</em></button>
</section>
</div>`;
}
function remindersPage() {
return pageHead("Erinnerungen", "Freundliche Hinweise, damit Wichtiges nicht im Alltag untergeht.", `
<button class="button primary" id="newReminder">Erinnerung hinzufügen</button>
`) + `
<div class="quiet-page reminders-page">
<section class="reminder-date"><span>Heute</span><strong>7. Juni</strong><p>Du hast einen ruhigen Abend ohne Studienfrist.</p></section>
<section class="calm-list">
<button data-route="calendar"><span class="important-icon"><i class="ph ph-file-text"></i></span><span><strong>Reflexionsbericht Mehrsprachigkeit</strong><small>Freitag, 10. Juni · 23:59</small></span><em>In 3 Tagen</em></button>
<button data-route="calendar"><span class="important-icon"><i class="ph ph-presentation-chart"></i></span><span><strong>Französische Präsentation</strong><small>Montag, 13. Juni · 10:00</small></span><em>In 6 Tagen</em></button>
<button data-route="learning-plan"><span class="important-icon"><i class="ph ph-book-open"></i></span><span><strong>Bildungspsychologie wiederholen</strong><small>Morgen · 15:00</small></span><em>Geplant</em></button>
</section>
</div>`;
}
const renderers = {
overview: overviewPage,
uploads: uploadsPage,
canvas: canvasPage,
calendar: calendarPage,
"learning-plan": learningPlanPage,
gaps: gapsPage,
flashcards: flashcardsPage,
quiz: quizPage,
reminders: remindersPage
};
function normalizeRoute() {
const route = location.hash.replace("#/", "").replace("#", "");
return routes.includes(route) ? route : "overview";
}
function navigate(route) {
if (!routes.includes(route)) return;
if (location.hash !== `#/${route}`) location.hash = `#/${route}`;
else render();
}
function render() {
const route = normalizeRoute();
app.innerHTML = renderers[route]();
navList.querySelectorAll("[data-route]").forEach(btn => btn.classList.toggle("active", btn.dataset.route === route));
document.title = `${route === "overview" ? "Heute" : app.querySelector("h1")?.textContent || "StudyFlow"} · StudyFlow AI`;
closeMenu();
app.focus({ preventScroll: true });
bindPage(route);
}
function bindPage(route) {
app.querySelectorAll("[data-route]").forEach(el => el.addEventListener("click", () => navigate(el.dataset.route)));
if (route === "uploads") bindUploads();
if (route === "canvas") bindCanvas();
if (route === "calendar") bindCalendar();
if (route === "flashcards") bindFlashcards();
if (route === "quiz") bindQuiz();
if (route === "reminders") {
document.querySelector("#newReminder")?.addEventListener("click", () => showToast("Neue Erinnerung wird lokal angelegt."));
}
app.querySelector("[data-action='open-plan']")?.addEventListener("click", () => navigate("calendar"));
}
function bindUploads() {
const dropzone = document.querySelector("#dropzone");
["dragenter", "dragover"].forEach(type => dropzone.addEventListener(type, event => { event.preventDefault(); dropzone.classList.add("drag"); }));
["dragleave", "drop"].forEach(type => dropzone.addEventListener(type, event => { event.preventDefault(); dropzone.classList.remove("drag"); }));
dropzone.addEventListener("drop", () => showToast("Datei zur lokalen Queue hinzugefügt."));
document.querySelector("#addFiles").addEventListener("click", () => showToast("Dateiauswahl geöffnet. Demo bleibt lokal."));
document.querySelector("#reviewAll").addEventListener("click", () => {
document.querySelector("#ocrText").focus();
showToast("7 unsichere Stellen sind zur Prüfung markiert.");
});
document.querySelector("#saveOcr").addEventListener("click", () => showToast("OCR-Text lokal gespeichert und verknüpft."));
}
function bindCanvas() {
const mainSlide = document.querySelector("#mainSlide");
const slideAssets = [assets.recent[0], assets.recent[1], assets.slide, assets.recent[2], assets.recent[3]];
document.querySelectorAll(".slide-thumb").forEach(button => button.addEventListener("click", () => {
document.querySelectorAll(".slide-thumb").forEach(item => item.classList.remove("active"));
button.classList.add("active");
mainSlide.src = slideAssets[Number(button.dataset.slide)];
}));
document.querySelector("#chatForm").addEventListener("submit", event => {
event.preventDefault();
const input = document.querySelector("#chatInput");
const text = input.value.trim();
if (!text) return;
const messages = document.querySelector("#messages");
messages.insertAdjacentHTML("beforeend", `<div class="message user">${escapeHtml(text)}</div><div class="message ai"><strong>Maya</strong><br>Ich prüfe diese Frage gegen die lokal verknüpften Folien und Notizen. Die relevanten Stellen liegen auf Folie 14 und in deiner Scaffolding-Notiz.</div>`);
input.value = "";
messages.scrollTop = messages.scrollHeight;
});
}
function bindCalendar() {
document.querySelector("#planBlock").addEventListener("click", () => showToast("Neuer Lernblock für 17:15 vorgeschlagen."));
document.querySelector("#reviewExtractions").addEventListener("click", () => showToast("Drei bestätigte Termine aus lokalen Quellen."));
}
function bindFlashcards() {
const preview = document.querySelector("#cardPreview");
preview.addEventListener("click", () => preview.classList.toggle("flipped"));
document.querySelector("#saveCard").addEventListener("click", () => showToast("Karte lokal gespeichert."));
document.querySelector("#deleteCard").addEventListener("click", () => showToast("Karte zur Löschung vorgemerkt."));
document.querySelector("#generateCards").addEventListener("click", () => showToast("6 Kartenvorschläge aus zwei Quellen erzeugt."));
document.querySelector("#learnCards").addEventListener("click", () => showToast("Lernsession mit 12 fälligen Karten gestartet."));
document.querySelectorAll("[data-export]").forEach(button => button.addEventListener("click", () => showToast(`${button.dataset.export}-Export lokal vorbereitet.`)));
document.querySelectorAll(".deck-row").forEach(row => row.addEventListener("click", () => {
document.querySelectorAll(".deck-row").forEach(item => item.classList.remove("selected"));
row.classList.add("selected");
showToast(`${row.dataset.deck} ausgewählt.`);
}));
}
function bindQuiz() {
const options = [...document.querySelectorAll(".answer-option")];
const explanation = document.querySelector("#quizExplanation");
options.forEach(option => option.addEventListener("click", () => {
options.forEach(item => item.classList.remove("selected", "wrong"));
const correct = option.dataset.answer === "B";
option.classList.add(correct ? "selected" : "wrong");
explanation.hidden = false;
document.querySelector("#answerState").textContent = correct ? "Richtig beantwortet" : "Noch nicht richtig";
document.querySelector("#answerState").style.color = correct ? "var(--emerald-dark)" : "var(--red)";
document.querySelector("#chosenAnswer").textContent = `Antwort gewählt · ${option.dataset.answer}`;
}));
document.querySelectorAll("[data-level]").forEach(button => button.addEventListener("click", () => {
document.querySelectorAll("[data-level]").forEach(item => item.classList.remove("active"));
button.classList.add("active");
showToast(`Schwierigkeit auf ${button.dataset.level} gesetzt.`);
}));
document.querySelector("#nextQuestion")?.addEventListener("click", () => {
document.querySelector(".panel-head h2").textContent = "Frage 8 von 12";
document.querySelector("#quizProgress").style.width = "67%";
document.querySelector("#quizProgressText").textContent = "67%";
showToast("Nächste Frage geladen.");
});
document.querySelector("#endQuiz").addEventListener("click", () => showToast("Simulation pausiert. Dein Stand bleibt lokal gespeichert."));
}
function showToast(message) {
toast.textContent = message;
toast.classList.add("show");
clearTimeout(showToast.timer);
showToast.timer = setTimeout(() => toast.classList.remove("show"), 2600);
}
function escapeHtml(value) {
return value.replace(/[&<>"']/g, char => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[char]));
}
const sidebar = document.querySelector("#sidebar");
const scrim = document.querySelector("#scrim");
const menuButton = document.querySelector("#menuButton");
function closeMenu() {
sidebar.classList.remove("open");
scrim.classList.remove("show");
menuButton.setAttribute("aria-expanded", "false");
}
menuButton.addEventListener("click", () => {
const open = sidebar.classList.toggle("open");
scrim.classList.toggle("show", open);
menuButton.setAttribute("aria-expanded", String(open));
});
scrim.addEventListener("click", closeMenu);
navList.addEventListener("click", event => {
const button = event.target.closest("[data-route]");
if (button) navigate(button.dataset.route);
});
document.querySelector("#askButton").addEventListener("click", () => document.querySelector("#aiDialog").showModal());
document.querySelector("#aiSubmit").addEventListener("click", () => {
const prompt = document.querySelector("#aiPrompt").value.trim();
showToast(prompt ? "Lokale Antwort wird aus 12 Materialien erzeugt." : "Bitte gib zuerst eine Frage ein.");
});
document.querySelector("#globalSearch").addEventListener("keydown", event => {
if (event.key === "Enter" && event.currentTarget.value.trim()) showToast(`Lokale Suche nach „${event.currentTarget.value.trim()}“`);
});
document.addEventListener("keydown", event => {
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "k") {
event.preventDefault();
document.querySelector("#globalSearch").focus();
}
if (event.key === "Escape") closeMenu();
});
window.addEventListener("hashchange", render);
render();
|