/** * 🌐 MASTER 08: INTERAKTIVE TASK-APP (VIEW & CONTROLLER) 🌐 * ========================================================== * Verbindet die TaskManager-Geschäftslogik mit einer modernen, * reaktiven Benutzeroberfläche im Browser. */ // Falls TaskManager noch nicht global vorhanden ist (z.B. Standalone): if (typeof TaskManager === "undefined") { // Fallback Minimal-Implementation oder Import console.warn("TaskManager nicht gefunden. Lade Fallback-Definition."); } class TaskApp { constructor(rootElementId = "app") { this.root = document.getElementById(rootElementId) || document.body; this.manager = new TaskManager([ { id: 1, title: "TypeScript Interfaces & Union Types verstehen", priority: "high", completed: true, dueDate: "2026-08-30", createdAt: new Date().toISOString() }, { id: 2, title: "Model-View-Controller Architektur im Web umsetzen", priority: "high", completed: false, dueDate: "2026-09-01", createdAt: new Date().toISOString() }, { id: 3, title: "Design System & Dark Mode Akzente optimieren", priority: "medium", completed: false, dueDate: "2026-09-05", createdAt: new Date().toISOString() }, { id: 4, title: "Automatisierte Unittests mit 100% Abdeckung schreiben", priority: "low", completed: false, dueDate: null, createdAt: new Date().toISOString() } ]); this.currentFilter = "all"; this.searchQuery = ""; this.init(); } init() { this.renderLayout(); this.attachEventListeners(); this.updateView(); } renderLayout() { this.root.innerHTML = `

🎯 Modern Task & Project Planner

Statussichere Aufgabenverwaltung mit TypeScript & Clean Architecture

Gesamt
0
Aktiv / Offen
0
Erledigt
0
🔥 Hohe Prio
0
`; } attachEventListeners() { // Formular-Submit const form = document.getElementById("task-form"); if (form) { form.addEventListener("submit", (e) => { e.preventDefault(); const titleInput = document.getElementById("task-input-title"); const prioritySelect = document.getElementById("task-select-priority"); const dueInput = document.getElementById("task-input-due"); const title = titleInput.value.trim(); const priority = prioritySelect.value; const dueDate = dueInput.value || null; if (title) { try { this.manager.addTask(title, priority, dueDate); titleInput.value = ""; dueInput.value = ""; this.updateView(); } catch (err) { alert(err.message); } } }); } // Filter Buttons const filterContainer = document.getElementById("filter-buttons"); if (filterContainer) { filterContainer.addEventListener("click", (e) => { const btn = e.target.closest("button[data-filter]"); if (btn) { this.currentFilter = btn.getAttribute("data-filter"); // Button-Stile aktualisieren filterContainer.querySelectorAll(".filter-btn").forEach((b) => { b.style.background = "white"; b.style.color = "#475569"; b.style.borderColor = "#cbd5e1"; }); btn.style.background = "#4f46e5"; btn.style.color = "white"; btn.style.borderColor = "#4f46e5"; this.updateView(); } }); } // Live-Suche const searchInput = document.getElementById("search-input"); if (searchInput) { searchInput.addEventListener("input", (e) => { this.searchQuery = e.target.value; this.updateView(); }); } // Erledigte aufräumen const clearBtn = document.getElementById("btn-clear-completed"); if (clearBtn) { clearBtn.addEventListener("click", () => { if (confirm("Möchtest du alle erledigten Aufgaben wirklich entfernen?")) { this.manager.clearCompleted(); this.updateView(); } }); } // Task-Liste Delegation (Toggle & Delete) const listContainer = document.getElementById("task-list"); if (listContainer) { listContainer.addEventListener("click", (e) => { const target = e.target; const taskCard = target.closest("[data-task-id]"); if (!taskCard) return; const id = Number(taskCard.getAttribute("data-task-id")); if (target.classList.contains("btn-delete") || target.closest(".btn-delete")) { this.manager.deleteTask(id); this.updateView(); } else if (target.classList.contains("task-checkbox")) { this.manager.toggleTask(id); this.updateView(); } }); } } updateView() { this.renderStats(); this.renderTasks(); } renderStats() { const stats = this.manager.getStatistics(); const elTotal = document.getElementById("stat-total"); const elActive = document.getElementById("stat-active"); const elCompleted = document.getElementById("stat-completed"); const elHigh = document.getElementById("stat-high"); if (elTotal) elTotal.textContent = stats.total; if (elActive) elActive.textContent = stats.active; if (elCompleted) elCompleted.textContent = stats.completed; if (elHigh) elHigh.textContent = stats.highPriorityCount; } renderTasks() { const container = document.getElementById("task-list"); if (!container) return; const filtered = this.manager.getFilteredTasks(this.currentFilter, this.searchQuery); if (filtered.length === 0) { container.innerHTML = `
✨
Keine Aufgaben gefunden
Alle Aufgaben erledigt oder kein Treffer für den aktuellen Filter.
`; return; } container.innerHTML = filtered .map((t) => { const priorityColors = { high: { bg: "#fee2e2", text: "#991b1b", label: "🔥 Hoch" }, medium: { bg: "#fef3c7", text: "#92400e", label: "⚡ Mittel" }, low: { bg: "#dcfce7", text: "#166534", label: "🌱 Niedrig" } }; const p = priorityColors[t.priority] || priorityColors.medium; const dueHtml = t.dueDate ? ` 📅 ${t.dueDate} ` : ""; return `
${this.escapeHtml(t.title)}
${p.label} ${dueHtml}
`; }) .join(""); } escapeHtml(str) { if (!str) return ""; return str .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } } // Bei DOMContentLoaded automatisch starten wenn im Browser if (typeof document !== "undefined") { document.addEventListener("DOMContentLoaded", () => { if (document.getElementById("app") || document.getElementById("task-app-root")) { new TaskApp(document.getElementById("task-app-root") ? "task-app-root" : "app"); } }); }