Files
TaskMate/frontend/index.html
2026-01-10 16:47:02 +00:00

2197 Zeilen
107 KiB
HTML
Originalformat Blame Verlauf

Diese Datei enthält unsichtbare Unicode-Zeichen

Diese Datei enthält unsichtbare Unicode-Zeichen, die für Menschen nicht unterscheidbar sind, aber von einem Computer unterschiedlich verarbeitet werden können. Wenn du glaubst, dass das absichtlich so ist, kannst du diese Warnung ignorieren. Benutze den „Escape“-Button, um versteckte Zeichen anzuzeigen.

Diese Datei enthält Unicode-Zeichen, die mit anderen Zeichen verwechselt werden können. Wenn du glaubst, dass das absichtlich so ist, kannst du diese Warnung ignorieren. Benutze den „Escape“-Button, um versteckte Zeichen anzuzeigen.

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="TaskMate - Aufgaben einfach verwalten">
<meta name="theme-color" content="#000000">
<title>TaskMate</title>
<!-- PWA Manifest -->
<link rel="manifest" href="/manifest.json">
<!-- iOS PWA Support -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="TaskMate">
<link rel="apple-touch-icon" href="/assets/icons/icon-152x152.png">
<!-- Poppins Font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
<!-- CSS -->
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/components.css">
<link rel="stylesheet" href="css/board.css">
<link rel="stylesheet" href="css/modal.css">
<link rel="stylesheet" href="css/calendar.css">
<link rel="stylesheet" href="css/list.css">
<link rel="stylesheet" href="css/admin.css">
<link rel="stylesheet" href="css/proposals.css">
<link rel="stylesheet" href="css/notifications.css">
<link rel="stylesheet" href="css/gitea.css">
<link rel="stylesheet" href="css/coding.css">
<link rel="stylesheet" href="css/knowledge.css">
<link rel="stylesheet" href="css/reminders.css">
<link rel="stylesheet" href="css/contacts.css">
<link rel="stylesheet" href="css/responsive.css">
<link rel="stylesheet" href="css/mobile.css">
<link rel="stylesheet" href="css/pwa.css">
<!-- Favicon - Transparente PNG Icons ohne schwarzen Hintergrund -->
<link rel="icon" type="image/png" sizes="32x32" href="/assets/icons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/icons/favicon-16x16.png">
<link rel="icon" type="image/png" href="/assets/icons/icon-48x48.png">
</head>
<body>
<!-- Login Screen -->
<div id="login-screen" class="login-screen">
<div class="login-container">
<div class="login-header">
<h1>TaskMate</h1>
<p>Melden Sie sich an, um fortzufahren</p>
</div>
<form id="login-form" class="login-form" method="POST" action="/api/auth/login" onsubmit="return false;">
<div class="form-group">
<label for="login-username">E-Mail</label>
<input type="text" id="login-username" name="username" required autocomplete="email" autofocus placeholder="benutzer@beispiel.de">
</div>
<div class="form-group">
<label for="login-password">Passwort</label>
<input type="password" id="login-password" name="password" required autocomplete="current-password">
</div>
<div id="login-error" class="error-message hidden"></div>
<button type="submit" class="btn btn-primary btn-block">
<span class="btn-text">Anmelden</span>
<span class="btn-loading hidden">
<span class="spinner"></span>
</span>
</button>
</form>
</div>
</div>
<!-- Admin Screen -->
<div id="admin-screen" class="admin-screen">
<header class="admin-header">
<h1>
<svg viewBox="0 0 24 24"><path d="M12 2a5 5 0 0 1 5 5v2a5 5 0 0 1-10 0V7a5 5 0 0 1 5-5zm-7 18a7 7 0 0 1 14 0" stroke="currentColor" stroke-width="2" fill="none"/></svg>
Benutzerverwaltung
</h1>
<button id="admin-logout-btn" class="btn btn-secondary">Abmelden</button>
</header>
<div class="admin-content">
<div class="admin-users-section">
<div class="admin-users-header">
<h2>Benutzer</h2>
<button id="btn-new-user" class="btn btn-primary">Neuer Benutzer</button>
</div>
<div id="admin-users-list" class="admin-users-list">
<!-- Users will be rendered here -->
</div>
</div>
<!-- Upload-Einstellungen -->
<div class="admin-upload-section">
<div class="admin-section-header">
<h2>
<svg viewBox="0 0 24 24" width="20" height="20"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
Upload-Einstellungen
</h2>
</div>
<!-- Maximale Dateigröße -->
<div class="admin-upload-size">
<label for="upload-max-size">Maximale Dateigröße</label>
<div class="upload-size-input">
<input type="number" id="upload-max-size" min="1" max="100" value="15">
<span class="upload-size-unit">MB</span>
</div>
</div>
<!-- Erlaubte Dateiendungen -->
<div class="admin-upload-extensions">
<h3>Erlaubte Dateiendungen</h3>
<!-- Aktive Endungen als Tags -->
<div id="extension-tags" class="extension-tags">
<!-- Tags werden dynamisch gerendert -->
</div>
<!-- Neue Endung hinzufügen -->
<div class="extension-add-group">
<label for="extension-input">Neue Endung hinzufügen</label>
<div class="extension-input-row">
<input type="text" id="extension-input" class="extension-input" placeholder="z.B. xlsx" maxlength="10">
<button type="button" id="btn-add-extension" class="btn btn-secondary">+ Hinzufügen</button>
</div>
</div>
<!-- Vorschläge -->
<div class="extension-suggestions">
<span class="extension-suggestions-label">Vorschläge:</span>
<div id="extension-suggestions-list" class="extension-suggestions-list">
<!-- Vorschläge werden dynamisch gerendert -->
</div>
</div>
</div>
<!-- Speichern-Button -->
<div class="admin-upload-actions">
<button id="btn-save-upload-settings" class="btn btn-primary">Einstellungen speichern</button>
</div>
</div>
</div>
</div>
<!-- Main App -->
<div id="app-screen" class="app hidden">
<!-- Header -->
<header class="header">
<div class="header-left">
<!-- Hamburger Menu Button (Mobile) -->
<button id="hamburger-btn" class="hamburger-btn" aria-label="Menu" aria-expanded="false">
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
</button>
<h1 class="logo">TaskMate</h1>
<!-- Project Selector -->
<div class="project-selector">
<select id="project-select" class="project-select">
<option value="">Projekt wählen...</option>
</select>
<button id="btn-edit-project" class="btn btn-icon" title="Projekt bearbeiten">
<svg class="icon" viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" stroke="currentColor" stroke-width="2" fill="none"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</button>
<button id="btn-new-project" class="btn btn-icon" title="Neues Projekt">
<svg class="icon" viewBox="0 0 24 24"><path d="M12 4v16m-8-8h16" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</button>
</div>
</div>
<div class="header-center">
<!-- View Tabs -->
<nav class="view-tabs">
<button class="view-tab active" data-view="board">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="7" height="7" rx="1"/>
<rect x="14" y="3" width="7" height="7" rx="1"/>
<rect x="3" y="14" width="7" height="7" rx="1"/>
<rect x="14" y="14" width="7" height="7" rx="1"/>
</svg>
Board
</button>
<button class="view-tab" data-view="list">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="8" y1="6" x2="21" y2="6"/>
<line x1="8" y1="12" x2="21" y2="12"/>
<line x1="8" y1="18" x2="21" y2="18"/>
<circle cx="3.5" cy="6" r="1" fill="currentColor"/>
<circle cx="3.5" cy="12" r="1" fill="currentColor"/>
<circle cx="3.5" cy="18" r="1" fill="currentColor"/>
</svg>
Liste
</button>
<button class="view-tab" data-view="calendar">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="4" width="18" height="18" rx="2"/>
<line x1="16" y1="2" x2="16" y2="6"/>
<line x1="8" y1="2" x2="8" y2="6"/>
<line x1="3" y1="10" x2="21" y2="10"/>
<circle cx="12" cy="16" r="1" fill="currentColor"/>
</svg>
Kalender
</button>
<button class="view-tab" data-view="proposals">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M9 11l3 3L22 4"/>
<path d="M21 12v7a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2h11"/>
</svg>
Genehmigung
</button>
<button class="view-tab" data-view="coding">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="16 18 22 12 16 6"/>
<polyline points="8 6 2 12 8 18"/>
<line x1="12" y1="20" x2="12" y2="4" transform="rotate(-15 12 12)"/>
</svg>
Coding
</button>
<button class="view-tab" data-view="knowledge">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
</svg>
Wissen
</button>
<button class="view-tab" data-view="contacts">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
</svg>
Kontakte
</button>
</nav>
</div>
<div class="header-right">
<!-- Search -->
<div class="search-container">
<svg class="search-icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8" stroke="currentColor" stroke-width="2" fill="none"/><path d="m21 21-4.35-4.35" stroke="currentColor" stroke-width="2"/></svg>
<input type="text" id="search-input" class="search-input" placeholder="Suchen...">
<button type="button" id="search-clear" class="search-clear hidden" title="Suche zurücksetzen (Esc)">
<svg viewBox="0 0 24 24" width="16" height="16"><path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
</button>
<div id="search-spinner" class="search-spinner hidden"></div>
</div>
<!-- Connection Status -->
<div id="connection-status" class="connection-status online" title="Verbunden">
<span class="status-dot"></span>
<span class="status-text">Online</span>
</div>
<!-- Notification Bell -->
<div class="notification-bell" id="notification-bell">
<button id="notification-btn" class="btn btn-icon" title="Benachrichtigungen">
<svg class="notification-icon" viewBox="0 0 24 24">
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.73 21a2 2 0 0 1-3.46 0" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span id="notification-badge" class="notification-badge hidden">0</span>
</button>
<div id="notification-dropdown" class="notification-dropdown hidden">
<div class="notification-header">
<h3>Benachrichtigungen</h3>
<button id="btn-mark-all-read" class="btn btn-text">Alle gelesen</button>
</div>
<div id="notification-list" class="notification-list">
<!-- Notifications rendered here -->
</div>
<div id="notification-empty" class="notification-empty hidden">
<svg class="notification-empty-icon" viewBox="0 0 24 24">
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" stroke="currentColor" stroke-width="2" fill="none"/>
<path d="M13.73 21a2 2 0 0 1-3.46 0" stroke="currentColor" stroke-width="2" fill="none"/>
</svg>
<p>Keine Benachrichtigungen</p>
</div>
</div>
</div>
<!-- Session Timer -->
<div id="session-timer" class="session-timer" title="Verbleibende Sitzungszeit">
<svg class="session-timer-icon" viewBox="0 0 24 24" width="16" height="16">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"/>
<polyline points="12 6 12 12 16 14" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span id="session-countdown">--:--</span>
</div>
<!-- User Menu -->
<div class="user-menu">
<button id="user-menu-btn" class="user-avatar">
<span id="user-initial">U</span>
</button>
<div id="user-dropdown" class="user-dropdown hidden">
<div class="user-info">
<span id="user-name">Benutzer</span>
<span id="user-role">Angemeldet</span>
</div>
<div class="dropdown-divider"></div>
<button id="btn-settings" class="dropdown-item">Einstellungen</button>
<div class="dropdown-divider"></div>
<button id="btn-logout" class="dropdown-item text-danger">Abmelden</button>
</div>
</div>
</div>
</header>
<!-- Offline Banner -->
<div id="offline-banner" class="offline-banner hidden">
<svg class="icon" viewBox="0 0 24 24"><path d="M1 1l22 22M16.72 11.06A10.94 10.94 0 0 1 19 12.55M5 12.55a10.94 10.94 0 0 1 5.17-2.39M10.71 5.05A16 16 0 0 1 22.58 9M1.42 9a15.91 15.91 0 0 1 4.7-2.88M8.53 16.11a6 6 0 0 1 6.95 0M12 20h.01" stroke="currentColor" stroke-width="2" fill="none"/></svg>
<span>Offline - Änderungen werden bei Wiederverbindung synchronisiert</span>
</div>
<!-- Main Content Area -->
<main class="main-content">
<!-- Board View -->
<div id="view-board" class="view view-board active">
<!-- Filter Bar -->
<div class="filter-bar">
<div class="filter-group">
<label>Filter:</label>
<select id="filter-assignee" class="filter-select">
<option value="">Alle Benutzer</option>
</select>
<select id="filter-priority" class="filter-select">
<option value="">Alle Prioritäten</option>
<option value="high">Hoch</option>
<option value="medium">Mittel</option>
<option value="low">Niedrig</option>
</select>
<select id="filter-labels" class="filter-select">
<option value="">Alle Labels</option>
</select>
<select id="filter-due" class="filter-select">
<option value="">Alle Fälligkeiten</option>
<option value="overdue">Überfällig</option>
<option value="today">Heute</option>
<option value="week">Diese Woche</option>
<option value="none">Ohne Datum</option>
</select>
</div>
<div class="filter-actions">
<button id="btn-clear-filters" class="btn btn-text">Filter zurücksetzen</button>
<button id="btn-show-archived" class="btn btn-text">Archiv anzeigen</button>
</div>
</div>
<!-- Week Strip Calendar -->
<div id="week-strip" class="week-strip">
<button id="week-strip-prev" class="week-strip-nav" title="Vorherige Woche">
<svg viewBox="0 0 24 24"><path d="M15 18l-6-6 6-6" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</button>
<div id="week-strip-days" class="week-strip-days">
<!-- Days will be rendered by JavaScript -->
</div>
<button id="week-strip-next" class="week-strip-nav" title="Nächste Woche">
<svg viewBox="0 0 24 24"><path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</button>
<button id="week-strip-today" class="week-strip-today btn btn-text" title="Zur aktuellen Woche">Heute</button>
</div>
<!-- Stats Bar -->
<div class="board-stats-bar">
<div class="board-stat">
<span class="board-stat-icon stat-open">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</span>
<span class="board-stat-value" id="board-stat-open">0</span>
<span class="board-stat-label">Offen</span>
</div>
<div class="board-stat">
<span class="board-stat-icon stat-progress">
<svg viewBox="0 0 24 24"><path d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48 2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48 2.83-2.83" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</span>
<span class="board-stat-value" id="board-stat-progress">0</span>
<span class="board-stat-label">In Arbeit</span>
</div>
<div class="board-stat">
<span class="board-stat-icon stat-done">
<svg viewBox="0 0 24 24"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" stroke="currentColor" stroke-width="2" fill="none"/><path d="m22 4-10 10-3-3" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</span>
<span class="board-stat-value" id="board-stat-done">0</span>
<span class="board-stat-label">Erledigt</span>
</div>
<div class="board-stat stat-danger">
<span class="board-stat-icon stat-overdue">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"/><path d="M12 8v4l3 3" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</span>
<span class="board-stat-value" id="board-stat-overdue">0</span>
<span class="board-stat-label">Überfällig</span>
</div>
</div>
<!-- Board -->
<div id="board" class="board">
<!-- Columns will be rendered here -->
<!-- Add Column Button is rendered dynamically inside the board -->
</div>
</div>
<!-- List View -->
<div id="view-list" class="view view-list hidden">
<div class="list-header">
<div class="list-controls">
<div class="list-view-toggle">
<button class="list-toggle-btn active" data-mode="grouped" title="Gruppiert nach Status">
<svg viewBox="0 0 24 24"><path d="M3 6h18M3 12h18M3 18h18" stroke="currentColor" stroke-width="2" fill="none"/></svg>
Gruppiert
</button>
<button class="list-toggle-btn" data-mode="flat" title="Flache Liste">
<svg viewBox="0 0 24 24"><path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" stroke="currentColor" stroke-width="2" fill="none"/></svg>
Flach
</button>
</div>
<div class="list-sort">
<label>Sortieren:</label>
<select id="list-sort-select">
<option value="dueDate">Fälligkeit</option>
<option value="priority">Priorität</option>
<option value="title">Name</option>
<option value="assignee">Zugewiesen</option>
<option value="status">Status</option>
</select>
<button id="list-sort-direction" class="btn btn-icon" title="Sortierrichtung">
<svg viewBox="0 0 24 24"><path d="M12 5v14M19 12l-7 7-7-7" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</button>
</div>
</div>
</div>
<div id="list-content" class="list-content">
<!-- Table will be rendered by JavaScript -->
</div>
</div>
<!-- Calendar View -->
<div id="view-calendar" class="view view-calendar hidden">
<div class="calendar-header">
<div class="calendar-nav">
<button id="btn-prev-period" class="btn btn-icon" title="Zurück">
<svg class="icon" viewBox="0 0 24 24"><path d="m15 18-6-6 6-6" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</button>
<h2 id="calendar-title">Dezember 2025</h2>
<button id="btn-next-period" class="btn btn-icon" title="Vor">
<svg class="icon" viewBox="0 0 24 24"><path d="m9 18 6-6-6-6" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</button>
</div>
<div class="calendar-actions">
<div class="calendar-filter-dropdown">
<button class="btn btn-secondary calendar-filter-btn" id="btn-calendar-filter">
<svg class="icon" viewBox="0 0 24 24"><path d="M22 3H2l8 9.46V19l4 2v-8.54L22 3z" stroke="currentColor" stroke-width="2" fill="none"/></svg>
Filter
</button>
<div class="calendar-filter-menu hidden" id="calendar-filter-menu">
<!-- Dynamisch gefüllt -->
</div>
</div>
<button id="btn-new-reminder" class="btn btn-secondary btn-reminder" title="Erinnerung hinzufügen">
<svg class="icon" viewBox="0 0 24 24"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9M13.73 21a2 2 0 0 1-3.46 0" stroke="currentColor" stroke-width="2" fill="none"/></svg>
Erinnerung
</button>
<button id="btn-today" class="btn btn-secondary">Heute</button>
<div class="calendar-view-toggle">
<button class="btn btn-toggle active" data-calendar-view="month">Monat</button>
<button class="btn btn-toggle" data-calendar-view="week">Woche</button>
</div>
</div>
</div>
<div class="calendar-weekdays" id="calendar-weekdays">
<div class="calendar-weekday">Mo</div>
<div class="calendar-weekday">Di</div>
<div class="calendar-weekday">Mi</div>
<div class="calendar-weekday">Do</div>
<div class="calendar-weekday">Fr</div>
<div class="calendar-weekday">Sa</div>
<div class="calendar-weekday">So</div>
</div>
<div id="calendar-grid" class="calendar-grid calendar-month-view">
<!-- Calendar will be rendered here -->
</div>
</div>
<!-- Proposals View -->
<div id="view-proposals" class="view proposals-view hidden">
<div class="proposals-header">
<h2 id="proposals-title">Genehmigungen</h2>
<div class="proposals-controls">
<div class="proposals-sort">
<label for="proposals-sort">Sortierung:</label>
<select id="proposals-sort">
<option value="date">Nach Datum</option>
<option value="alpha">Alphabetisch</option>
</select>
</div>
<button id="btn-show-proposals-archive" class="btn btn-secondary">Archiv anzeigen</button>
<button id="btn-new-proposal" class="btn btn-primary">Neue Genehmigung</button>
</div>
</div>
<div id="proposals-list" class="proposals-list">
<!-- Proposals will be rendered here -->
</div>
<div id="proposals-empty" class="proposals-empty hidden">
<svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke="currentColor" stroke-width="2" fill="none"/><path d="M14 2v6h6M16 13H8M16 17H8M10 9H8" stroke="currentColor" stroke-width="2" fill="none"/></svg>
<h3>Keine Genehmigungen vorhanden</h3>
<p>Erstellen Sie die erste Genehmigung!</p>
</div>
</div>
<!-- Coding View -->
<div id="view-coding" class="view view-coding hidden">
<!-- Header -->
<div class="coding-header coding-header-centered">
<button id="add-coding-directory-btn" class="btn btn-primary">
<svg viewBox="0 0 24 24" width="18" height="18"><path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
Anwendung hinzufügen
</button>
</div>
<!-- Grid für Kacheln -->
<div id="coding-grid" class="coding-grid">
<!-- Kacheln werden per JS gerendert -->
</div>
<!-- Empty State -->
<div id="coding-empty" class="coding-empty hidden">
<div class="empty-icon">
<svg viewBox="0 0 24 24" width="64" height="64"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" stroke="currentColor" stroke-width="2" fill="none"/></svg>
</div>
<h3>Keine Anwendungen</h3>
<p>Füge deine erste Server-Anwendung hinzu, um mit Claude oder Codex zu arbeiten.</p>
</div>
</div>
<!-- Knowledge View (Wissensmanagement) -->
<div id="view-knowledge" class="view view-knowledge hidden">
<!-- Mobile: Kategorien als horizontale Chips -->
<div id="knowledge-mobile-categories" class="knowledge-mobile-categories">
<!-- Wird dynamisch befüllt -->
</div>
<!-- Haupt-Layout: Sidebar + Main -->
<div class="knowledge-layout">
<!-- Sidebar (links) - Kategorien -->
<aside class="knowledge-sidebar">
<div class="knowledge-sidebar-header">
<h3 class="knowledge-sidebar-title">Kategorien</h3>
<button id="btn-new-category" class="btn btn-primary btn-sm">
<svg viewBox="0 0 24 24" width="16" height="16"><path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
Neu
</button>
</div>
<div id="knowledge-categories" class="knowledge-category-list">
<!-- Kategorien werden dynamisch geladen -->
</div>
<div id="knowledge-categories-empty" class="knowledge-sidebar-empty hidden">
<svg viewBox="0 0 24 24" width="48" height="48">
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20" stroke="currentColor" stroke-width="2" fill="none"/>
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z" stroke="currentColor" stroke-width="2" fill="none"/>
</svg>
<p>Keine Kategorien</p>
</div>
<!-- Resize Handle -->
<div id="knowledge-resize-handle" class="knowledge-resize-handle"></div>
</aside>
<!-- Hauptbereich (rechts) - Einträge -->
<main class="knowledge-main">
<div class="knowledge-main-header">
<h2 id="knowledge-category-title" class="knowledge-main-title">Kategorie wählen</h2>
<button id="btn-new-entry" class="btn btn-primary" disabled>
<svg viewBox="0 0 24 24" width="18" height="18"><path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
Neuer Eintrag
</button>
</div>
<!-- Einträge-Liste -->
<div id="knowledge-entries" class="knowledge-entry-list">
<!-- Einträge werden dynamisch geladen -->
</div>
<!-- Leerer Zustand: Keine Kategorie ausgewählt -->
<div id="knowledge-no-selection" class="knowledge-empty">
<svg viewBox="0 0 24 24" width="64" height="64">
<path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20" stroke="currentColor" stroke-width="2" fill="none"/>
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z" stroke="currentColor" stroke-width="2" fill="none"/>
</svg>
<h3>Kategorie auswählen</h3>
<p>Wählen Sie links eine Kategorie aus, um Einträge anzuzeigen.</p>
</div>
<!-- Leerer Zustand: Keine Einträge -->
<div id="knowledge-entries-empty" class="knowledge-empty hidden">
<svg viewBox="0 0 24 24" width="64" height="64">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke="currentColor" stroke-width="2" fill="none"/>
<path d="M14 2v6h6M16 13H8M16 17H8M10 9H8" stroke="currentColor" stroke-width="2" fill="none"/>
</svg>
<h3>Keine Einträge</h3>
<p>Erstellen Sie den ersten Eintrag in dieser Kategorie.</p>
</div>
<!-- Suchergebnisse -->
<div id="knowledge-search-results" class="knowledge-search-results hidden">
<div class="knowledge-search-header">
<button id="btn-clear-search" class="btn btn-text">
<svg viewBox="0 0 24 24" width="18" height="18"><path d="M6 18L18 6M6 6l12 12" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
Suche beenden
</button>
<span class="knowledge-search-info">Ergebnisse für "<span id="knowledge-search-query"></span>"</span>
</div>
<div id="knowledge-search-list" class="knowledge-entry-list">
<!-- Suchergebnisse werden hier angezeigt -->
</div>
<div id="knowledge-search-empty" class="knowledge-empty hidden">
<svg viewBox="0 0 24 24" width="64" height="64">
<circle cx="11" cy="11" r="8" stroke="currentColor" stroke-width="2" fill="none"/>
<path d="M21 21l-4.35-4.35" stroke="currentColor" stroke-width="2" fill="none"/>
</svg>
<h3>Keine Ergebnisse</h3>
<p>Keine Einträge gefunden.</p>
</div>
</div>
</main>
</div>
</div>
<!-- Contacts View -->
<div id="view-contacts" class="view view-contacts hidden">
<div class="view-wrapper">
<div class="contacts-header">
<h2>Kontakte</h2>
<div class="header-actions">
<div class="contacts-stats">
<span id="contacts-count">0 Kontakte</span>
</div>
<button id="btn-export-contacts" class="btn btn-secondary btn-export">
<svg viewBox="0 0 24 24" width="16" height="16">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Exportieren
</button>
<button id="btn-new-contact" class="btn btn-primary">
<svg viewBox="0 0 24 24" width="18" height="18">
<path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/>
</svg>
Neuer Kontakt
</button>
</div>
</div>
<div class="contacts-controls">
<div class="contacts-controls-top">
<div class="bulk-actions hidden" id="bulk-actions">
<span class="bulk-actions-info"><span id="selected-count">0</span> ausgewählt</span>
<button id="btn-bulk-delete" class="btn btn-danger btn-sm">
<svg viewBox="0 0 24 24" width="16" height="16">
<path d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2m3 0v12a2 2 0 01-2 2H7a2 2 0 01-2-2V6h14M10 11v6M14 11v6" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Löschen
</button>
<button id="btn-deselect-all" class="btn btn-secondary btn-sm">Abwählen</button>
</div>
<div class="contacts-filters">
<div class="filter-group">
<label for="contacts-tag-filter" class="sr-only">Tags filtern</label>
<select id="contacts-tag-filter" class="filter-select">
<option value="">Alle Tags</option>
</select>
</div>
</div>
</div>
</div>
<div class="contacts-table-container">
<table class="contacts-table" id="contacts-table">
<thead>
<tr>
<th class="checkbox-cell">
<input type="checkbox" class="table-checkbox" id="select-all-contacts">
</th>
<th class="sortable" data-sort="name">Name</th>
<th class="sortable" data-sort="company">Firma</th>
<th class="sortable hide-mobile" data-sort="position">Position</th>
<th class="sortable" data-sort="email">E-Mail</th>
<th class="hide-mobile">Telefon</th>
<th>Tags</th>
<th>Aktionen</th>
</tr>
</thead>
<tbody id="contacts-tbody">
<!-- Table rows will be rendered here -->
</tbody>
</table>
<div class="pagination hidden" id="contacts-pagination">
<button class="pagination-btn" id="btn-prev-page" disabled>
<svg viewBox="0 0 24 24" width="16" height="16">
<path d="M15 18l-6-6 6-6" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<span class="pagination-info">
Seite <span id="current-page">1</span> von <span id="total-pages">1</span>
</span>
<button class="pagination-btn" id="btn-next-page" disabled>
<svg viewBox="0 0 24 24" width="16" height="16">
<path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
</div>
</div>
<div id="contacts-empty" class="contacts-empty hidden">
<div class="empty-icon">
<svg viewBox="0 0 24 24" width="64" height="64" fill="none" stroke="currentColor" stroke-width="2">
<path d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<h3>Keine Kontakte vorhanden</h3>
<p>Erstellen Sie Ihren ersten Kontakt.</p>
<button class="btn btn-primary" onclick="document.getElementById('btn-new-contact').click()">
<svg viewBox="0 0 24 24" width="18" height="18">
<path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/>
</svg>
Ersten Kontakt erstellen
</button>
</div>
</div>
</div>
</main>
</div>
<!-- Modals -->
<div id="modal-overlay" class="modal-overlay hidden"></div>
<!-- Task Modal -->
<div id="task-modal" class="modal modal-large hidden">
<div class="modal-header">
<h2 id="task-modal-title">Neue Aufgabe</h2>
<span id="save-status-indicator" class="save-status-indicator"></span>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="task-form">
<input type="hidden" id="task-id">
<input type="hidden" id="task-column-id">
<div class="form-row">
<div class="form-group form-group-large">
<label for="task-title">Titel *</label>
<input type="text" id="task-title" required maxlength="200">
</div>
</div>
<div class="form-row">
<div class="form-group form-group-large">
<label for="task-description">Beschreibung (Markdown)</label>
<textarea id="task-description" rows="4" placeholder="Beschreibung..."></textarea>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="task-status">Status</label>
<select id="task-status"></select>
</div>
<div class="form-group">
<label for="task-priority">Priorität</label>
<select id="task-priority">
<option value="low">Niedrig</option>
<option value="medium" selected>Mittel</option>
<option value="high">Hoch</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group form-group-wide">
<label>Mitarbeitende zuweisen</label>
<div class="multi-select-dropdown" id="assignees-dropdown">
<div class="multi-select-trigger" id="assignees-trigger">
<span class="multi-select-placeholder">Mitarbeitende auswählen...</span>
<span class="multi-select-arrow"></span>
</div>
<div class="multi-select-options hidden" id="assignees-options">
<!-- Options werden dynamisch generiert -->
</div>
</div>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="task-start">Startdatum</label>
<input type="date" id="task-start">
</div>
<div class="form-group">
<label for="task-due">Enddatum</label>
<input type="date" id="task-due">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="task-time-hours">Zeitschätzung</label>
<div class="time-estimate-inputs">
<input type="number" id="task-time-hours" min="0" max="999" placeholder="0"> Std
<input type="number" id="task-time-mins" min="0" max="59" placeholder="0"> Min
</div>
</div>
</div>
<div class="form-group">
<label>Labels</label>
<div id="task-labels" class="labels-select"></div>
</div>
<!-- Subtasks -->
<div class="form-group">
<label>Checkliste</label>
<div id="subtask-progress" class="subtask-progress hidden">
<div class="progress">
<div id="subtask-progress-bar" class="progress-bar"></div>
</div>
<span id="subtask-progress-text">0/0</span>
</div>
<div id="subtasks-container" class="subtasks-container"></div>
<div class="add-subtask-form">
<input type="text" id="subtask-input" placeholder="Neue Unteraufgabe...">
<button type="button" id="btn-add-subtask" class="btn btn-secondary">Hinzufügen</button>
</div>
</div>
<!-- Links -->
<div class="form-group" id="links-section">
<label>Links</label>
<div id="links-container" class="links-container"></div>
<div class="add-link-form">
<input type="text" id="link-title" placeholder="Titel (optional)">
<input type="url" id="link-url" placeholder="https://...">
<button type="button" id="btn-add-link" class="btn btn-secondary">Hinzufügen</button>
</div>
</div>
<!-- Attachments -->
<div class="form-group" id="attachments-section">
<label>Anhänge</label>
<div id="attachments-container" class="attachments-container"></div>
<div class="file-upload-area" id="file-upload-area">
<svg class="icon" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12" stroke="currentColor" stroke-width="2" fill="none"/></svg>
<span>Dateien hierher ziehen oder <label for="file-input" class="file-input-label">auswählen</label></span>
<input type="file" id="file-input" multiple hidden>
<span class="file-hint">Max. 15 MB pro Datei</span>
</div>
</div>
<!-- Comments (only in edit mode) -->
<div class="form-group" id="comments-section" style="display: none;">
<label>Kommentare</label>
<div id="comments-container" class="comments-container"></div>
<div class="add-comment-form">
<textarea id="comment-input" rows="2" placeholder="Kommentar schreiben... (@Benutzer für Erwähnungen)"></textarea>
<button type="button" id="btn-add-comment" class="btn btn-secondary">Senden</button>
</div>
</div>
<!-- History (only in edit mode) -->
<div class="form-group" id="history-section" style="display: none;">
<label>Historie</label>
<div id="history-container" class="history-container"></div>
</div>
</form>
</div>
<div class="modal-footer">
<div class="modal-footer-left">
<button type="button" id="btn-duplicate-task" class="btn btn-text hidden">Duplizieren</button>
<button type="button" id="btn-archive-task" class="btn btn-text hidden">Archivieren</button>
<button type="button" id="btn-restore-task" class="btn btn-text hidden">Wiederherstellen</button>
<button type="button" id="btn-delete-task" class="btn btn-text text-danger hidden">Löschen</button>
</div>
<div class="modal-footer-right">
<button type="button" id="btn-cancel-task" class="btn btn-secondary hidden">Abbrechen</button>
<button type="button" id="btn-save-task" class="btn btn-primary hidden">Speichern</button>
<button type="button" id="btn-back-task" class="btn btn-primary">Zurück</button>
</div>
</div>
</div>
<!-- Quick Add Modal -->
<div id="quick-add-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2>Schnell hinzufügen</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="quick-add-form">
<div class="form-group">
<input type="text" id="quick-task-title" placeholder="Aufgabentitel..." required autofocus>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="quick-add-form" class="btn btn-primary">Hinzufügen</button>
</div>
</div>
<!-- Column Modal -->
<div id="column-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2 id="column-modal-title">Neue Spalte</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="column-form">
<input type="hidden" id="column-id">
<div class="form-group">
<label for="column-name">Name *</label>
<input type="text" id="column-name" required maxlength="50">
</div>
<div class="form-group">
<label for="column-color">Farbe (optional)</label>
<input type="color" id="column-color" value="#00D4FF">
</div>
<div class="form-group">
<label for="column-filter-category">Kalender-Filter</label>
<select id="column-filter-category">
<option value="open">Offen</option>
<option value="in_progress" selected>In Arbeit</option>
<option value="completed">Erledigt</option>
<option value="custom">Neuer Filter...</option>
</select>
</div>
<div class="form-group hidden" id="column-custom-filter-group">
<label for="column-custom-filter">Neuer Filtername</label>
<input type="text" id="column-custom-filter" maxlength="30" placeholder="z.B. Wartend, Blockiert...">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" id="btn-delete-column" class="btn btn-text text-danger" style="display: none;">Löschen</button>
<div class="modal-footer-right">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="column-form" class="btn btn-primary">Speichern</button>
</div>
</div>
</div>
<!-- Project Modal -->
<div id="project-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2 id="project-modal-title">Neues Projekt</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="project-form">
<input type="hidden" id="project-id">
<div class="form-group">
<label for="project-name">Name *</label>
<input type="text" id="project-name" required maxlength="100">
</div>
<div class="form-group">
<label for="project-description">Beschreibung</label>
<textarea id="project-description" rows="3"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" id="btn-delete-project" class="btn btn-danger hidden">Projekt löschen</button>
<div class="modal-footer-right">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="project-form" class="btn btn-primary">Speichern</button>
</div>
</div>
</div>
<!-- Label Modal -->
<div id="label-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2 id="label-modal-title">Neues Label</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="label-form">
<input type="hidden" id="label-id">
<div class="form-group">
<label for="label-name">Name *</label>
<input type="text" id="label-name" required maxlength="30">
</div>
<div class="form-group">
<label for="label-color">Farbe *</label>
<div class="color-presets">
<button type="button" class="color-preset" data-color="#DC2626" style="background:#DC2626"></button>
<button type="button" class="color-preset" data-color="#D97706" style="background:#D97706"></button>
<button type="button" class="color-preset" data-color="#059669" style="background:#059669"></button>
<button type="button" class="color-preset" data-color="#3182CE" style="background:#3182CE"></button>
<button type="button" class="color-preset" data-color="#7C3AED" style="background:#7C3AED"></button>
<button type="button" class="color-preset" data-color="#DB2777" style="background:#DB2777"></button>
</div>
<input type="color" id="label-color" value="#3182CE">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" id="btn-delete-label" class="btn btn-text text-danger" style="display: none;">Löschen</button>
<div class="modal-footer-right">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="label-form" class="btn btn-primary">Speichern</button>
</div>
</div>
</div>
<!-- Confirm Modal -->
<div id="confirm-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2 id="confirm-title">Bestätigung</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<p id="confirm-message"></p>
</div>
<div class="modal-footer">
<button type="button" id="confirm-cancel" class="btn btn-secondary">Abbrechen</button>
<button type="button" id="confirm-ok" class="btn btn-danger">Bestätigen</button>
</div>
</div>
<!-- Archive Modal -->
<div id="archive-modal" class="modal modal-large hidden">
<div class="modal-header">
<h2>Archiv</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<div id="archive-list" class="archive-list">
<!-- Archived tasks will be rendered here -->
</div>
<div id="archive-empty" class="archive-empty hidden">
<p>Keine archivierten Aufgaben vorhanden.</p>
</div>
</div>
</div>
<!-- Settings Modal -->
<div id="settings-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2>Einstellungen</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<!-- User Color Selection -->
<div class="form-group">
<label>Meine Farbe</label>
<p class="text-secondary" style="font-size: var(--text-sm); margin-bottom: var(--spacing-3);">
Wählen Sie Ihre persönliche Farbe für Aufgaben und Kalender.
</p>
<div class="color-picker-container">
<div id="user-color-options" class="color-options">
<button type="button" class="color-option" data-color="#EF4444" style="background-color: #EF4444" title="Rot"></button>
<button type="button" class="color-option" data-color="#F97316" style="background-color: #F97316" title="Orange"></button>
<button type="button" class="color-option" data-color="#F59E0B" style="background-color: #F59E0B" title="Gelb"></button>
<button type="button" class="color-option" data-color="#10B981" style="background-color: #10B981" title="Grün"></button>
<button type="button" class="color-option" data-color="#14B8A6" style="background-color: #14B8A6" title="Türkis"></button>
<button type="button" class="color-option" data-color="#3B82F6" style="background-color: #3B82F6" title="Blau"></button>
<button type="button" class="color-option" data-color="#8B5CF6" style="background-color: #8B5CF6" title="Violett"></button>
<button type="button" class="color-option" data-color="#EC4899" style="background-color: #EC4899" title="Pink"></button>
<button type="button" class="color-option" data-color="#6B7280" style="background-color: #6B7280" title="Grau"></button>
</div>
<div class="color-custom-row">
<label for="user-color-custom" class="text-secondary" style="font-size: var(--text-sm);">Eigene Farbe:</label>
<input type="color" id="user-color-custom" value="#3B82F6" title="Beliebige Farbe waehlen">
</div>
<div class="color-preview-row">
<span class="text-secondary" style="font-size: var(--text-sm);">Vorschau:</span>
<span id="user-color-preview" class="avatar" style="background-color: #3B82F6">
<span id="user-color-preview-initial">U</span>
</span>
</div>
</div>
</div>
<div class="settings-divider"></div>
<!-- Password Change -->
<div class="form-group">
<label>Passwort ändern</label>
<p class="text-secondary" style="font-size: var(--text-sm); margin-bottom: var(--spacing-3);">
Ändern Sie Ihr Passwort für mehr Sicherheit.
</p>
<form id="change-password-form">
<div class="form-group">
<label for="current-password">Aktuelles Passwort</label>
<input type="password" id="current-password" required>
</div>
<div class="form-group">
<label for="new-password">Neues Passwort</label>
<input type="password" id="new-password" required minlength="8">
</div>
<div class="form-group">
<label for="confirm-password">Passwort bestätigen</label>
<input type="password" id="confirm-password" required>
</div>
<div id="password-error" class="error-message hidden"></div>
<button type="submit" class="btn btn-primary btn-block">Passwort ändern</button>
</form>
</div>
</div>
</div>
<!-- User Modal (Admin) -->
<div id="user-modal" class="modal hidden">
<div class="modal-header">
<h2 id="user-modal-title">Neuer Benutzer</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="user-form" class="user-modal-form">
<input type="hidden" id="edit-user-id">
<div class="form-group">
<label for="user-username">Kürzel</label>
<div class="input-with-prefix">
<span class="input-prefix">@</span>
<input type="text" id="user-username" required minlength="2" maxlength="2" pattern="[A-Za-z]{2}" style="text-transform: uppercase;">
</div>
<span class="form-hint">2 Buchstaben zur Identifikation bei Aufgaben und Kommentaren</span>
</div>
<div class="form-group">
<label for="user-displayname">Anzeigename</label>
<input type="text" id="user-displayname" required maxlength="100">
</div>
<div class="form-group">
<label for="user-email">E-Mail</label>
<input type="email" id="user-email" required placeholder="benutzer@beispiel.de">
</div>
<div class="form-group">
<label for="user-password">Passwort <span id="password-hint" class="form-hint">(automatisch generiert)</span></label>
<div class="password-input-group">
<input type="text" id="user-password" minlength="8" readonly>
<button type="button" id="edit-password-btn" class="btn btn-secondary btn-sm" title="Passwort bearbeiten">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" stroke="currentColor" stroke-width="2" fill="none"/>
<path d="m18.5 2.5 3 3L12 15l-4 1 1-4 9.5-9.5z" stroke="currentColor" stroke-width="2" fill="none"/>
</svg>
</button>
<button type="button" id="generate-password-btn" class="btn btn-secondary btn-sm" title="Neues Passwort generieren">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M1 4v6h6" stroke="currentColor" stroke-width="2" fill="none"/>
<path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10" stroke="currentColor" stroke-width="2" fill="none"/>
</svg>
</button>
</div>
</div>
<div class="form-group">
<label for="user-role">Rolle</label>
<select id="user-role" required>
<option value="user">Benutzer</option>
<option value="admin">Administrator</option>
</select>
</div>
<div class="form-group" id="permissions-group">
<label>Berechtigungen</label>
<div class="permissions-list">
<div class="permission-item">
<input type="checkbox" id="perm-genehmigung" value="genehmigung">
<label for="perm-genehmigung">Genehmigung</label>
<span class="permission-desc">Kann Vorschläge genehmigen</span>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" id="btn-delete-user" class="btn btn-text text-danger hidden">Löschen</button>
<button type="button" id="btn-unlock-user" class="btn btn-text hidden">Entsperren</button>
<div class="modal-footer-right">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="user-form" class="btn btn-primary">Speichern</button>
</div>
</div>
</div>
<!-- Proposal Modal -->
<div id="proposal-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2 id="proposal-modal-title">Neue Genehmigung</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="proposal-form" class="proposal-modal-form">
<div class="form-group">
<label for="proposal-title">Titel *</label>
<input type="text" id="proposal-title" required maxlength="200">
</div>
<div class="form-group">
<label for="proposal-description">Beschreibung</label>
<textarea id="proposal-description" rows="4" placeholder="Optionale Beschreibung..."></textarea>
</div>
<div class="form-group">
<label for="proposal-task">Verknüpfte Aufgabe (optional)</label>
<select id="proposal-task">
<option value="">Keine Aufgabe</option>
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="proposal-form" class="btn btn-primary">Erstellen</button>
</div>
</div>
<!-- Git Commit Modal -->
<div id="git-commit-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2>Commit erstellen</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="git-commit-form">
<div class="form-group">
<label for="commit-message">Commit-Nachricht *</label>
<textarea id="commit-message" rows="4" required
placeholder="Beschreiben Sie Ihre Änderungen..."></textarea>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="commit-stage-all" checked>
Alle Änderungen einschließen (git add -A)
</label>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="git-commit-form" class="btn btn-primary">Commit erstellen</button>
</div>
</div>
<!-- Git Branch Rename Modal -->
<div id="git-rename-branch-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2>Branch umbenennen</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="git-rename-branch-form">
<div class="form-group">
<label>Aktueller Branch</label>
<div id="rename-current-branch" class="form-static-value">master</div>
</div>
<div class="form-group">
<label for="rename-new-branch">Neuer Name *</label>
<input type="text" id="rename-new-branch" required
placeholder="z.B. main" pattern="[a-zA-Z0-9_\-]+"
title="Nur Buchstaben, Zahlen, Unterstriche und Bindestriche">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="git-rename-branch-form" class="btn btn-primary">Umbenennen</button>
</div>
</div>
<!-- Git Push Modal -->
<div id="git-push-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2>Push zu Gitea</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="git-push-form">
<div class="form-group">
<label>Lokaler Branch</label>
<div id="push-local-branch" class="form-static-value">wird ermittelt...</div>
<span class="form-hint">Der aktuelle lokale Branch wird automatisch erkannt</span>
</div>
<div class="form-group">
<label for="push-target-branch">Ziel-Branch auf Remote</label>
<select id="push-target-branch">
<option value="">Gleicher Name wie lokal</option>
<option value="main">main</option>
<option value="master">master</option>
<option value="develop">develop</option>
</select>
<span class="form-hint">Wählen Sie den Branch-Namen auf Gitea</span>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="push-force">
Force Push (Remote überschreiben)
</label>
<span class="form-hint warning">Achtung: Überschreibt alle Änderungen auf dem Remote-Branch!</span>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="git-push-form" class="btn btn-primary">Push starten</button>
</div>
</div>
<!-- Create Repository Modal -->
<div id="create-repo-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2>Neues Repository erstellen</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="create-repo-form">
<div class="form-group">
<label for="new-repo-name">Repository-Name *</label>
<input type="text" id="new-repo-name" required
pattern="[a-zA-Z0-9_-]+"
placeholder="mein-projekt">
<span class="form-hint">Nur Buchstaben, Zahlen, Unterstriche und Bindestriche</span>
</div>
<div class="form-group">
<label for="new-repo-description">Beschreibung</label>
<textarea id="new-repo-description" rows="2"
placeholder="Optionale Beschreibung..."></textarea>
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="new-repo-private" checked>
Privates Repository
</label>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="create-repo-form" class="btn btn-primary">Repository erstellen</button>
</div>
</div>
<!-- Knowledge Category Modal -->
<div id="knowledge-category-modal" class="modal modal-small hidden">
<div class="modal-header">
<h2 id="knowledge-category-modal-title">Neue Kategorie</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="knowledge-category-form">
<input type="hidden" id="knowledge-category-id">
<div class="form-group">
<label for="knowledge-category-name">Name *</label>
<input type="text" id="knowledge-category-name" required maxlength="100" placeholder="z.B. Technik">
</div>
<div class="form-group">
<label for="knowledge-category-description">Beschreibung</label>
<textarea id="knowledge-category-description" rows="2" placeholder="Optionale Beschreibung..."></textarea>
</div>
<div class="form-row">
<div class="form-group">
<label for="knowledge-category-color">Farbe</label>
<input type="color" id="knowledge-category-color" value="#3B82F6">
</div>
<div class="form-group">
<label>Icon</label>
<div class="icon-picker-container">
<div class="icon-picker-preview" id="icon-picker-preview">
<span class="icon-preview-emoji" id="icon-preview-emoji">📁</span>
<span class="icon-preview-label">Klicken zum Ändern</span>
</div>
<input type="hidden" id="knowledge-category-icon" value="📁">
</div>
</div>
</div>
<!-- Icon Picker Grid -->
<div class="icon-picker-section" id="icon-picker-section">
<div class="icon-picker-tabs">
<button type="button" class="icon-tab active" data-tab="tech">💻 Technik</button>
<button type="button" class="icon-tab" data-tab="network">🌐 Netzwerk</button>
<button type="button" class="icon-tab" data-tab="office">📋 Büro</button>
<button type="button" class="icon-tab" data-tab="finance">💰 Finanzen</button>
<button type="button" class="icon-tab" data-tab="home">🏠 Haus</button>
<button type="button" class="icon-tab" data-tab="misc">⭐ Sonstige</button>
</div>
<!-- Technik Icons -->
<div class="icon-grid" data-tab-content="tech">
<button type="button" class="icon-btn" data-icon="💻">💻</button>
<button type="button" class="icon-btn" data-icon="🖥️">🖥️</button>
<button type="button" class="icon-btn" data-icon="🖨️">🖨️</button>
<button type="button" class="icon-btn" data-icon="⌨️">⌨️</button>
<button type="button" class="icon-btn" data-icon="🖱️">🖱️</button>
<button type="button" class="icon-btn" data-icon="💾">💾</button>
<button type="button" class="icon-btn" data-icon="💿">💿</button>
<button type="button" class="icon-btn" data-icon="📀">📀</button>
<button type="button" class="icon-btn" data-icon="🔌">🔌</button>
<button type="button" class="icon-btn" data-icon="🔋">🔋</button>
<button type="button" class="icon-btn" data-icon="📱">📱</button>
<button type="button" class="icon-btn" data-icon="📲">📲</button>
<button type="button" class="icon-btn" data-icon="☎️">☎️</button>
<button type="button" class="icon-btn" data-icon="📞">📞</button>
<button type="button" class="icon-btn" data-icon="📟">📟</button>
<button type="button" class="icon-btn" data-icon="📠">📠</button>
<button type="button" class="icon-btn" data-icon="📺">📺</button>
<button type="button" class="icon-btn" data-icon="📷">📷</button>
<button type="button" class="icon-btn" data-icon="📹">📹</button>
<button type="button" class="icon-btn" data-icon="🎥">🎥</button>
<button type="button" class="icon-btn" data-icon="🔦">🔦</button>
<button type="button" class="icon-btn" data-icon="💡">💡</button>
<button type="button" class="icon-btn" data-icon="🔧">🔧</button>
<button type="button" class="icon-btn" data-icon="🔨">🔨</button>
<button type="button" class="icon-btn" data-icon="⚙️">⚙️</button>
<button type="button" class="icon-btn" data-icon="🛠️">🛠️</button>
<button type="button" class="icon-btn" data-icon="🔩">🔩</button>
<button type="button" class="icon-btn" data-icon="⛏️">⛏️</button>
<button type="button" class="icon-btn" data-icon="🧰">🧰</button>
<button type="button" class="icon-btn" data-icon="🎮">🎮</button>
<button type="button" class="icon-btn" data-icon="🕹️">🕹️</button>
<button type="button" class="icon-btn" data-icon="🎧">🎧</button>
<button type="button" class="icon-btn" data-icon="🎤">🎤</button>
<button type="button" class="icon-btn" data-icon="🔊">🔊</button>
<button type="button" class="icon-btn" data-icon="📡">📡</button>
<button type="button" class="icon-btn" data-icon="🔬">🔬</button>
</div>
<!-- Netzwerk Icons -->
<div class="icon-grid hidden" data-tab-content="network">
<button type="button" class="icon-btn" data-icon="🌐">🌐</button>
<button type="button" class="icon-btn" data-icon="🌍">🌍</button>
<button type="button" class="icon-btn" data-icon="🌎">🌎</button>
<button type="button" class="icon-btn" data-icon="🌏">🌏</button>
<button type="button" class="icon-btn" data-icon="📡">📡</button>
<button type="button" class="icon-btn" data-icon="📶">📶</button>
<button type="button" class="icon-btn" data-icon="🛜">🛜</button>
<button type="button" class="icon-btn" data-icon="📤">📤</button>
<button type="button" class="icon-btn" data-icon="📥">📥</button>
<button type="button" class="icon-btn" data-icon="📧">📧</button>
<button type="button" class="icon-btn" data-icon="✉️">✉️</button>
<button type="button" class="icon-btn" data-icon="📨">📨</button>
<button type="button" class="icon-btn" data-icon="📩">📩</button>
<button type="button" class="icon-btn" data-icon="🔗">🔗</button>
<button type="button" class="icon-btn" data-icon="⛓️">⛓️</button>
<button type="button" class="icon-btn" data-icon="🔐">🔐</button>
<button type="button" class="icon-btn" data-icon="🔒">🔒</button>
<button type="button" class="icon-btn" data-icon="🔓">🔓</button>
<button type="button" class="icon-btn" data-icon="🔑">🔑</button>
<button type="button" class="icon-btn" data-icon="🗝️">🗝️</button>
<button type="button" class="icon-btn" data-icon="🛡️">🛡️</button>
<button type="button" class="icon-btn" data-icon="⚡"></button>
<button type="button" class="icon-btn" data-icon="☁️">☁️</button>
<button type="button" class="icon-btn" data-icon="🖧">🖧</button>
<button type="button" class="icon-btn" data-icon="🔄">🔄</button>
<button type="button" class="icon-btn" data-icon="♻️">♻️</button>
<button type="button" class="icon-btn" data-icon="🔃">🔃</button>
<button type="button" class="icon-btn" data-icon="🌀">🌀</button>
<button type="button" class="icon-btn" data-icon="💠">💠</button>
<button type="button" class="icon-btn" data-icon="🔷">🔷</button>
</div>
<!-- Büro Icons -->
<div class="icon-grid hidden" data-tab-content="office">
<button type="button" class="icon-btn" data-icon="📁">📁</button>
<button type="button" class="icon-btn" data-icon="📂">📂</button>
<button type="button" class="icon-btn" data-icon="🗂️">🗂️</button>
<button type="button" class="icon-btn" data-icon="📋">📋</button>
<button type="button" class="icon-btn" data-icon="📄">📄</button>
<button type="button" class="icon-btn" data-icon="📃">📃</button>
<button type="button" class="icon-btn" data-icon="📑">📑</button>
<button type="button" class="icon-btn" data-icon="📊">📊</button>
<button type="button" class="icon-btn" data-icon="📈">📈</button>
<button type="button" class="icon-btn" data-icon="📉">📉</button>
<button type="button" class="icon-btn" data-icon="📝">📝</button>
<button type="button" class="icon-btn" data-icon="✏️">✏️</button>
<button type="button" class="icon-btn" data-icon="✒️">✒️</button>
<button type="button" class="icon-btn" data-icon="🖊️">🖊️</button>
<button type="button" class="icon-btn" data-icon="🖋️">🖋️</button>
<button type="button" class="icon-btn" data-icon="📌">📌</button>
<button type="button" class="icon-btn" data-icon="📍">📍</button>
<button type="button" class="icon-btn" data-icon="📎">📎</button>
<button type="button" class="icon-btn" data-icon="🖇️">🖇️</button>
<button type="button" class="icon-btn" data-icon="📏">📏</button>
<button type="button" class="icon-btn" data-icon="📐">📐</button>
<button type="button" class="icon-btn" data-icon="✂️">✂️</button>
<button type="button" class="icon-btn" data-icon="🗃️">🗃️</button>
<button type="button" class="icon-btn" data-icon="🗄️">🗄️</button>
<button type="button" class="icon-btn" data-icon="🗑️">🗑️</button>
<button type="button" class="icon-btn" data-icon="📆">📆</button>
<button type="button" class="icon-btn" data-icon="📅">📅</button>
<button type="button" class="icon-btn" data-icon="🗓️">🗓️</button>
<button type="button" class="icon-btn" data-icon="⏰"></button>
<button type="button" class="icon-btn" data-icon="🕐">🕐</button>
<button type="button" class="icon-btn" data-icon="📰">📰</button>
<button type="button" class="icon-btn" data-icon="🗞️">🗞️</button>
<button type="button" class="icon-btn" data-icon="📓">📓</button>
<button type="button" class="icon-btn" data-icon="📔">📔</button>
<button type="button" class="icon-btn" data-icon="📒">📒</button>
<button type="button" class="icon-btn" data-icon="📕">📕</button>
<button type="button" class="icon-btn" data-icon="📗">📗</button>
<button type="button" class="icon-btn" data-icon="📘">📘</button>
<button type="button" class="icon-btn" data-icon="📙">📙</button>
<button type="button" class="icon-btn" data-icon="📚">📚</button>
</div>
<!-- Finanzen Icons -->
<div class="icon-grid hidden" data-tab-content="finance">
<button type="button" class="icon-btn" data-icon="💰">💰</button>
<button type="button" class="icon-btn" data-icon="💵">💵</button>
<button type="button" class="icon-btn" data-icon="💴">💴</button>
<button type="button" class="icon-btn" data-icon="💶">💶</button>
<button type="button" class="icon-btn" data-icon="💷">💷</button>
<button type="button" class="icon-btn" data-icon="💸">💸</button>
<button type="button" class="icon-btn" data-icon="💳">💳</button>
<button type="button" class="icon-btn" data-icon="🏦">🏦</button>
<button type="button" class="icon-btn" data-icon="🏧">🏧</button>
<button type="button" class="icon-btn" data-icon="💹">💹</button>
<button type="button" class="icon-btn" data-icon="🧾">🧾</button>
<button type="button" class="icon-btn" data-icon="💲">💲</button>
<button type="button" class="icon-btn" data-icon="💱">💱</button>
<button type="button" class="icon-btn" data-icon="🪙">🪙</button>
<button type="button" class="icon-btn" data-icon="💎">💎</button>
<button type="button" class="icon-btn" data-icon="⚖️">⚖️</button>
<button type="button" class="icon-btn" data-icon="🏛️">🏛️</button>
<button type="button" class="icon-btn" data-icon="🏢">🏢</button>
<button type="button" class="icon-btn" data-icon="🏪">🏪</button>
<button type="button" class="icon-btn" data-icon="🛒">🛒</button>
<button type="button" class="icon-btn" data-icon="🛍️">🛍️</button>
<button type="button" class="icon-btn" data-icon="🎁">🎁</button>
<button type="button" class="icon-btn" data-icon="🎫">🎫</button>
<button type="button" class="icon-btn" data-icon="🎟️">🎟️</button>
</div>
<!-- Haus/Wohnen Icons -->
<div class="icon-grid hidden" data-tab-content="home">
<button type="button" class="icon-btn" data-icon="🏠">🏠</button>
<button type="button" class="icon-btn" data-icon="🏡">🏡</button>
<button type="button" class="icon-btn" data-icon="🏘️">🏘️</button>
<button type="button" class="icon-btn" data-icon="🏚️">🏚️</button>
<button type="button" class="icon-btn" data-icon="🚪">🚪</button>
<button type="button" class="icon-btn" data-icon="🪟">🪟</button>
<button type="button" class="icon-btn" data-icon="🛏️">🛏️</button>
<button type="button" class="icon-btn" data-icon="🛋️">🛋️</button>
<button type="button" class="icon-btn" data-icon="🪑">🪑</button>
<button type="button" class="icon-btn" data-icon="🚿">🚿</button>
<button type="button" class="icon-btn" data-icon="🛁">🛁</button>
<button type="button" class="icon-btn" data-icon="🚽">🚽</button>
<button type="button" class="icon-btn" data-icon="🧹">🧹</button>
<button type="button" class="icon-btn" data-icon="🧺">🧺</button>
<button type="button" class="icon-btn" data-icon="🧴">🧴</button>
<button type="button" class="icon-btn" data-icon="🪥">🪥</button>
<button type="button" class="icon-btn" data-icon="🍳">🍳</button>
<button type="button" class="icon-btn" data-icon="🍴">🍴</button>
<button type="button" class="icon-btn" data-icon="🥄">🥄</button>
<button type="button" class="icon-btn" data-icon="🔪">🔪</button>
<button type="button" class="icon-btn" data-icon="🏺">🏺</button>
<button type="button" class="icon-btn" data-icon="🌡️">🌡️</button>
<button type="button" class="icon-btn" data-icon="🌿">🌿</button>
<button type="button" class="icon-btn" data-icon="🪴">🪴</button>
<button type="button" class="icon-btn" data-icon="🚗">🚗</button>
<button type="button" class="icon-btn" data-icon="🚙">🚙</button>
<button type="button" class="icon-btn" data-icon="🚕">🚕</button>
<button type="button" class="icon-btn" data-icon="🛵">🛵</button>
<button type="button" class="icon-btn" data-icon="🚲">🚲</button>
<button type="button" class="icon-btn" data-icon="⛽"></button>
</div>
<!-- Sonstige Icons -->
<div class="icon-grid hidden" data-tab-content="misc">
<button type="button" class="icon-btn" data-icon="⭐"></button>
<button type="button" class="icon-btn" data-icon="🌟">🌟</button>
<button type="button" class="icon-btn" data-icon="✨"></button>
<button type="button" class="icon-btn" data-icon="💫">💫</button>
<button type="button" class="icon-btn" data-icon="❤️">❤️</button>
<button type="button" class="icon-btn" data-icon="💙">💙</button>
<button type="button" class="icon-btn" data-icon="💚">💚</button>
<button type="button" class="icon-btn" data-icon="💛">💛</button>
<button type="button" class="icon-btn" data-icon="💜">💜</button>
<button type="button" class="icon-btn" data-icon="🧡">🧡</button>
<button type="button" class="icon-btn" data-icon="✅"></button>
<button type="button" class="icon-btn" data-icon="❌"></button>
<button type="button" class="icon-btn" data-icon="⚠️">⚠️</button>
<button type="button" class="icon-btn" data-icon="❗"></button>
<button type="button" class="icon-btn" data-icon="❓"></button>
<button type="button" class="icon-btn" data-icon=""></button>
<button type="button" class="icon-btn" data-icon="🔔">🔔</button>
<button type="button" class="icon-btn" data-icon="🔕">🔕</button>
<button type="button" class="icon-btn" data-icon="🎯">🎯</button>
<button type="button" class="icon-btn" data-icon="🎲">🎲</button>
<button type="button" class="icon-btn" data-icon="🧩">🧩</button>
<button type="button" class="icon-btn" data-icon="🏆">🏆</button>
<button type="button" class="icon-btn" data-icon="🥇">🥇</button>
<button type="button" class="icon-btn" data-icon="🥈">🥈</button>
<button type="button" class="icon-btn" data-icon="🥉">🥉</button>
<button type="button" class="icon-btn" data-icon="🎵">🎵</button>
<button type="button" class="icon-btn" data-icon="🎶">🎶</button>
<button type="button" class="icon-btn" data-icon="🎬">🎬</button>
<button type="button" class="icon-btn" data-icon="🎨">🎨</button>
<button type="button" class="icon-btn" data-icon="🎭">🎭</button>
<button type="button" class="icon-btn" data-icon="👤">👤</button>
<button type="button" class="icon-btn" data-icon="👥">👥</button>
<button type="button" class="icon-btn" data-icon="👨‍💼">👨‍💼</button>
<button type="button" class="icon-btn" data-icon="👩‍💼">👩‍💼</button>
<button type="button" class="icon-btn" data-icon="👨‍💻">👨‍💻</button>
<button type="button" class="icon-btn" data-icon="👩‍💻">👩‍💻</button>
<button type="button" class="icon-btn" data-icon="🧑‍🔧">🧑‍🔧</button>
<button type="button" class="icon-btn" data-icon="👷">👷</button>
<button type="button" class="icon-btn" data-icon="🔴">🔴</button>
<button type="button" class="icon-btn" data-icon="🟠">🟠</button>
<button type="button" class="icon-btn" data-icon="🟡">🟡</button>
<button type="button" class="icon-btn" data-icon="🟢">🟢</button>
<button type="button" class="icon-btn" data-icon="🔵">🔵</button>
<button type="button" class="icon-btn" data-icon="🟣">🟣</button>
<button type="button" class="icon-btn" data-icon="⚪"></button>
<button type="button" class="icon-btn" data-icon="⚫"></button>
<button type="button" class="icon-btn" data-icon="🟤">🟤</button>
<button type="button" class="icon-btn" data-icon="🔶">🔶</button>
<button type="button" class="icon-btn" data-icon="🔸">🔸</button>
<button type="button" class="icon-btn" data-icon="🔹">🔹</button>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="knowledge-category-form" class="btn btn-primary" id="btn-save-category">Speichern</button>
</div>
</div>
<!-- Knowledge Entry Modal -->
<div id="knowledge-entry-modal" class="modal modal-medium hidden">
<div class="modal-header">
<h2 id="knowledge-entry-modal-title">Neuer Eintrag</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="knowledge-entry-form">
<input type="hidden" id="knowledge-entry-id">
<input type="hidden" id="knowledge-entry-category-id">
<div class="form-group">
<label for="knowledge-entry-title">Titel *</label>
<input type="text" id="knowledge-entry-title" required maxlength="200" placeholder="z.B. Fritzbox Router">
</div>
<div class="form-group">
<label for="knowledge-entry-url">Link (URL)</label>
<input type="url" id="knowledge-entry-url" placeholder="https://...">
</div>
<div class="form-group">
<label for="knowledge-entry-notes">Notizen</label>
<textarea id="knowledge-entry-notes" rows="5" placeholder="Notizen, Anleitungen, Tipps... (Markdown unterstützt)"></textarea>
</div>
<!-- Anhänge (nur im Bearbeitungsmodus) -->
<div class="form-group" id="knowledge-attachments-section" style="display: none;">
<label>Anhänge</label>
<div id="knowledge-attachments-container" class="knowledge-attachments-container"></div>
<div class="file-upload-area" id="knowledge-file-upload-area">
<svg class="icon" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12" stroke="currentColor" stroke-width="2" fill="none"/></svg>
<span>Dateien hierher ziehen oder <label for="knowledge-file-input" class="file-input-label">auswählen</label></span>
<input type="file" id="knowledge-file-input" multiple hidden>
<span class="file-hint">Max. 15 MB pro Datei</span>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<div class="modal-footer-left">
<button type="button" id="btn-delete-entry" class="btn btn-text text-danger hidden">Löschen</button>
</div>
<div class="modal-footer-right">
<button type="button" class="btn btn-secondary" data-close-modal>Abbrechen</button>
<button type="submit" form="knowledge-entry-form" class="btn btn-primary" id="btn-save-entry">Speichern</button>
</div>
</div>
</div>
<!-- Coding Directory Modal -->
<div id="coding-modal" class="modal hidden">
<div class="modal-content modal-medium">
<div class="modal-header">
<h3 id="coding-modal-title">Anwendung hinzufügen</h3>
<button class="modal-close" aria-label="Schliessen">&times;</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="coding-name">Anwendungsname *</label>
<input type="text" id="coding-name" class="form-control" placeholder="z.B. TaskMate" required>
<small class="form-hint" id="coding-path-hint">Ordner: /home/claude-dev/<span id="coding-path-preview">...</span></small>
</div>
<div class="form-group">
<label for="coding-description">Beschreibung</label>
<textarea id="coding-description" class="form-control" rows="2" placeholder="Optionale Beschreibung..."></textarea>
</div>
<div class="form-group">
<label>Farbe</label>
<div class="color-presets" id="coding-color-presets">
<!-- Farb-Buttons werden per JS gerendert -->
</div>
</div>
<div class="form-group">
<label>CLAUDE.md</label>
<div class="claude-link-container">
<button type="button" id="coding-claude-link" class="claude-link" disabled>
<span class="claude-icon">📄</span>
<span class="claude-text">Keine CLAUDE.md vorhanden</span>
</button>
</div>
</div>
<details class="coding-gitea-section">
<summary>Gitea-Repository verknüpfen (optional)</summary>
<div class="form-group" style="margin-top: 1rem;">
<label for="coding-gitea-repo">Repository</label>
<select id="coding-gitea-repo" class="form-control">
<option value="">-- Kein Repository --</option>
</select>
</div>
<div class="form-group">
<label for="coding-branch">Standard-Branch</label>
<input type="text" id="coding-branch" class="form-control" value="main" placeholder="main">
</div>
</details>
</div>
<div class="modal-footer">
<button id="coding-delete-btn" class="btn btn-danger hidden">Löschen</button>
<button class="btn btn-secondary modal-cancel">Abbrechen</button>
<button id="coding-save-btn" class="btn btn-primary">Speichern</button>
</div>
</div>
</div>
<!-- Coding Command Modal -->
<div id="coding-command-modal" class="modal hidden">
<div class="modal-content modal-small">
<div class="modal-header">
<h3>Befehl ausführen</h3>
<button class="modal-close" aria-label="Schliessen">&times;</button>
</div>
<div class="modal-body">
<p id="coding-command-hint">Führe diesen Befehl in WSL aus:</p>
<div class="command-box">
<code id="coding-command-text"></code>
<button id="coding-copy-command" class="btn btn-sm btn-secondary">Kopieren</button>
</div>
</div>
</div>
</div>
<!-- Contact Modal -->
<div id="contact-modal" class="modal modal-medium hidden">
<div class="modal-header">
<h2 id="contact-modal-title">Neuer Kontakt</h2>
<button class="modal-close" data-close-modal>&times;</button>
</div>
<div class="modal-body">
<form id="contact-form">
<input type="hidden" id="contact-id" />
<div class="form-row">
<div class="form-group">
<label for="contact-first-name">Vorname</label>
<input type="text" id="contact-first-name" placeholder="Max" />
</div>
<div class="form-group">
<label for="contact-last-name">Nachname</label>
<input type="text" id="contact-last-name" placeholder="Mustermann" />
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="contact-company">Firma</label>
<input type="text" id="contact-company" placeholder="Musterfirma GmbH" />
</div>
<div class="form-group">
<label for="contact-position">Position</label>
<input type="text" id="contact-position" placeholder="Geschäftsführer" />
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="contact-email">E-Mail</label>
<input type="email" id="contact-email" placeholder="max@musterfirma.de" />
</div>
<div class="form-group">
<label for="contact-website">Website</label>
<input type="url" id="contact-website" placeholder="https://www.musterfirma.de" />
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="contact-phone">Telefon</label>
<input type="tel" id="contact-phone" placeholder="+49 30 12345678" />
</div>
<div class="form-group">
<label for="contact-mobile">Mobil</label>
<input type="tel" id="contact-mobile" placeholder="+49 170 1234567" />
</div>
</div>
<div class="form-group full-width">
<label for="contact-address">Adresse</label>
<input type="text" id="contact-address" placeholder="Musterstraße 123" />
</div>
<div class="form-row">
<div class="form-group">
<label for="contact-postal-code">PLZ</label>
<input type="text" id="contact-postal-code" placeholder="12345" />
</div>
<div class="form-group">
<label for="contact-city">Stadt</label>
<input type="text" id="contact-city" placeholder="Berlin" />
</div>
<div class="form-group">
<label for="contact-country">Land</label>
<input type="text" id="contact-country" placeholder="Deutschland" />
</div>
</div>
<div class="form-group full-width">
<label for="contact-notes">Notizen</label>
<textarea id="contact-notes" rows="3" placeholder="Zusätzliche Informationen..."></textarea>
</div>
<div class="form-group full-width">
<label for="contact-tags">Tags</label>
<input type="text" id="contact-tags" placeholder="Kunde, Partner, Lieferant" />
<div class="tags-help">Mehrere Tags mit Komma trennen</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" id="btn-delete-contact" class="btn btn-danger hidden">
<i class="fas fa-trash"></i>
Löschen
</button>
<button type="button" class="btn btn-secondary modal-cancel">Abbrechen</button>
<button type="submit" form="contact-form" class="btn btn-primary">Speichern</button>
</div>
</div>
<!-- Toast Container -->
<div id="toast-container" class="toast-container"></div>
<!-- Mobile Navigation Menu -->
<nav id="mobile-menu" class="mobile-menu" aria-hidden="true">
<div class="mobile-menu-header">
<h2 class="mobile-menu-title">TaskMate</h2>
<button id="mobile-menu-close" class="mobile-menu-close" aria-label="Menu schliessen">
<svg viewBox="0 0 24 24" width="24" height="24">
<path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
</button>
</div>
<div class="mobile-menu-section">
<label class="mobile-menu-label">Projekt</label>
<select id="mobile-project-select" class="mobile-project-select">
<!-- Populated by JS -->
</select>
</div>
<div class="mobile-menu-section">
<label class="mobile-menu-label">Ansicht</label>
<div class="mobile-menu-nav">
<button class="mobile-nav-item active" data-view="board">
<svg viewBox="0 0 24 24" width="20" height="20"><rect x="3" y="3" width="7" height="9" rx="1" stroke="currentColor" stroke-width="2" fill="none"/><rect x="14" y="3" width="7" height="5" rx="1" stroke="currentColor" stroke-width="2" fill="none"/><rect x="14" y="12" width="7" height="9" rx="1" stroke="currentColor" stroke-width="2" fill="none"/><rect x="3" y="16" width="7" height="5" rx="1" stroke="currentColor" stroke-width="2" fill="none"/></svg>
<span>Board</span>
</button>
<button class="mobile-nav-item" data-view="list">
<svg viewBox="0 0 24 24" width="20" height="20"><path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
<span>Liste</span>
</button>
<button class="mobile-nav-item" data-view="calendar">
<svg viewBox="0 0 24 24" width="20" height="20"><rect x="3" y="4" width="18" height="18" rx="2" stroke="currentColor" stroke-width="2" fill="none"/><line x1="16" y1="2" x2="16" y2="6" stroke="currentColor" stroke-width="2"/><line x1="8" y1="2" x2="8" y2="6" stroke="currentColor" stroke-width="2"/><line x1="3" y1="10" x2="21" y2="10" stroke="currentColor" stroke-width="2"/></svg>
<span>Kalender</span>
</button>
<button class="mobile-nav-item" data-view="proposals">
<svg viewBox="0 0 24 24" width="20" height="20"><path d="M9 11l3 3L22 4" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11" stroke="currentColor" stroke-width="2" fill="none"/></svg>
<span>Genehmigung</span>
</button>
<button class="mobile-nav-item" data-view="coding">
<svg viewBox="0 0 24 24" width="20" height="20"><polyline points="16 18 22 12 16 6" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/><polyline points="8 6 2 12 8 18" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
<span>Coding</span>
</button>
<button class="mobile-nav-item" data-view="knowledge">
<svg viewBox="0 0 24 24" width="20" height="20"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20" stroke="currentColor" stroke-width="2" fill="none"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z" stroke="currentColor" stroke-width="2" fill="none"/></svg>
<span>Wissen</span>
</button>
<button class="mobile-nav-item" data-view="contacts">
<svg viewBox="0 0 24 24" width="20" height="20"><path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" stroke="currentColor" stroke-width="2" fill="none"/><circle cx="8.5" cy="7" r="4" stroke="currentColor" stroke-width="2" fill="none"/><line x1="20" y1="8" x2="20" y2="14" stroke="currentColor" stroke-width="2"/><line x1="23" y1="11" x2="17" y2="11" stroke="currentColor" stroke-width="2"/></svg>
<span>Kontakte</span>
</button>
</div>
</div>
<div class="mobile-menu-section mobile-menu-user">
<div class="mobile-user-info">
<span id="mobile-user-avatar" class="mobile-user-avatar">U</span>
<div class="mobile-user-details">
<span id="mobile-user-name" class="mobile-user-name">Benutzer</span>
<span id="mobile-user-role" class="mobile-user-role">Angemeldet</span>
</div>
</div>
<button id="mobile-admin-btn" class="mobile-menu-btn hidden">Admin-Bereich</button>
<button id="mobile-logout-btn" class="mobile-menu-btn mobile-menu-btn-danger">Abmelden</button>
</div>
</nav>
<!-- Mobile Menu Overlay -->
<div id="mobile-menu-overlay" class="mobile-menu-overlay"></div>
<!-- Swipe Indicators -->
<div id="swipe-indicator-left" class="swipe-indicator left">
<svg viewBox="0 0 24 24" width="24" height="24"><path d="M15 18l-6-6 6-6" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div>
<div id="swipe-indicator-right" class="swipe-indicator right">
<svg viewBox="0 0 24 24" width="24" height="24"><path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>
</div>
<!-- Onboarding Tour -->
<div id="onboarding-overlay" class="onboarding-overlay hidden">
<div id="onboarding-tooltip" class="onboarding-tooltip">
<div class="onboarding-content">
<h3 id="onboarding-title"></h3>
<p id="onboarding-text"></p>
</div>
<div class="onboarding-footer">
<span id="onboarding-step">1/5</span>
<div>
<button id="btn-skip-tour" class="btn btn-text">Überspringen</button>
<button id="btn-next-tour" class="btn btn-primary">Weiter</button>
</div>
</div>
</div>
</div>
<!-- Image Lightbox -->
<div id="lightbox" class="lightbox hidden">
<button id="lightbox-close" class="lightbox-close">&times;</button>
<img id="lightbox-image" src="" alt="">
</div>
<!-- CLAUDE.md Modal -->
<div id="claude-md-modal" class="modal hidden">
<div class="modal-content modal-large">
<div class="modal-header">
<h3>CLAUDE.md (Nur-Lesen)</h3>
<button class="modal-close" aria-label="Schließen">&times;</button>
</div>
<div class="modal-body">
<div class="claude-md-viewer">
<pre id="claude-md-content" class="claude-md-display"></pre>
</div>
</div>
</div>
</div>
<!-- Reminder Modal -->
<div id="reminder-modal" class="modal hidden">
<div class="modal-content">
<div class="modal-header">
<h3 id="reminder-modal-title">Neue Erinnerung</h3>
<button class="modal-close" aria-label="Schließen">&times;</button>
</div>
<div class="modal-body">
<form id="reminder-form">
<div class="form-group">
<label for="reminder-title">Titel *</label>
<input type="text" id="reminder-title" class="form-control" required maxlength="255" placeholder="z.B. Meeting mit Kunde">
</div>
<div class="form-group">
<label for="reminder-description">Beschreibung</label>
<textarea id="reminder-description" class="form-control" rows="3" placeholder="Optionale Beschreibung..."></textarea>
</div>
<div class="form-group">
<label for="reminder-assignee">Zugewiesen an</label>
<div class="custom-select" id="reminder-assignee-wrapper">
<div class="custom-select-trigger" id="reminder-assignee-trigger">
<span class="custom-select-value">Alle Benutzer</span>
<svg class="custom-select-arrow" viewBox="0 0 24 24" width="16" height="16">
<path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" fill="none"/>
</svg>
</div>
<div class="custom-select-options" id="reminder-assignee-options">
<div class="custom-select-option" data-value="">
<span class="option-text">Alle Benutzer</span>
</div>
<!-- Wird dynamisch gefüllt -->
</div>
<input type="hidden" id="reminder-assignee" name="reminder-assignee" value="">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="reminder-date">Datum *</label>
<input type="date" id="reminder-date" class="form-control" required>
</div>
<div class="form-group">
<label for="reminder-time">Uhrzeit</label>
<input type="time" id="reminder-time" class="form-control" value="09:00">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="reminder-color">Farbe</label>
<div class="color-picker-wrapper">
<div class="color-picker-trigger" id="color-picker-trigger" style="background-color: #F59E0B">
<svg class="color-picker-icon" viewBox="0 0 24 24" width="16" height="16">
<path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" fill="none"/>
</svg>
</div>
<div class="color-picker-dropdown hidden" id="color-picker-dropdown">
<div class="color-option" data-color="#F59E0B" style="background: #F59E0B" title="Amber"></div>
<div class="color-option" data-color="#EF4444" style="background: #EF4444" title="Rot"></div>
<div class="color-option" data-color="#10B981" style="background: #10B981" title="Grün"></div>
<div class="color-option" data-color="#3B82F6" style="background: #3B82F6" title="Blau"></div>
<div class="color-option" data-color="#8B5CF6" style="background: #8B5CF6" title="Lila"></div>
<div class="color-option" data-color="#F97316" style="background: #F97316" title="Orange"></div>
<div class="color-option" data-color="#06B6D4" style="background: #06B6D4" title="Cyan"></div>
<div class="color-option" data-color="#84CC16" style="background: #84CC16" title="Lime"></div>
</div>
</div>
<input type="hidden" id="reminder-color" value="#F59E0B">
</div>
<div class="form-group">
<label for="reminder-advance">Vorab-Erinnerung</label>
<div class="advance-options">
<div class="reminder-advance-control">
<div class="reminder-advance-inputs">
<input type="number" id="reminder-advance-number" min="1" max="9" value="1" class="form-control reminder-number-input">
<select id="reminder-advance-unit" class="form-control reminder-unit-select">
<option value="day">Tag(e)</option>
<option value="week">Woche(n)</option>
<option value="month">Monat(e)</option>
</select>
<span class="reminder-advance-suffix">vorher</span>
</div>
</div>
</div>
</div>
</div>
<div class="form-actions">
<div class="form-actions-left">
<button type="button" class="btn btn-secondary" id="btn-cancel-reminder">Abbrechen</button>
<button type="submit" class="btn btn-primary" id="btn-save-reminder">
<span class="btn-text">Speichern</span>
<span class="btn-loading hidden">Speichere...</span>
</button>
</div>
<button type="button" class="btn btn-danger btn-delete-reminder hidden" id="btn-delete-reminder">
<svg viewBox="0 0 24 24" width="16" height="16">
<path d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2m3 0v12a2 2 0 01-2 2H7a2 2 0 01-2-2V6h14M10 11v6M14 11v6" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
Löschen
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Socket.io Client -->
<script src="/socket.io/socket.io.js"></script>
<!-- Main App (ES Module) -->
<script type="module" src="js/app.js"></script>
<script type="module" src="js/reminders.js"></script>
<script type="module" src="js/contacts.js"></script>
<!-- Emergency Login Handler -->
<script>
console.log('[Login] Fallback handler wird geladen...');
function setupLoginHandler() {
const loginForm = document.getElementById('login-form');
const submitButton = loginForm?.querySelector('button[type="submit"]');
if (!loginForm) {
console.error('[Login] Login-Formular nicht gefunden!');
return;
}
console.log('[Login] Login-Formular gefunden, Handler wird eingerichtet...');
// Force override - entferne alle existierenden Handler
const newForm = loginForm.cloneNode(true);
loginForm.parentNode.replaceChild(newForm, loginForm);
newForm.addEventListener('submit', async function(e) {
e.preventDefault();
e.stopPropagation();
console.log('[Login] Submit Event ausgelöst');
const username = document.getElementById('login-username').value.trim();
const password = document.getElementById('login-password').value;
const errorEl = document.getElementById('login-error');
const newSubmitButton = newForm.querySelector('button[type="submit"]');
console.log('[Login] Username:', username);
if (!username || !password) {
errorEl.textContent = 'Bitte Benutzername und Passwort eingeben';
errorEl.classList.remove('hidden');
return;
}
// Loading state
if (newSubmitButton) {
newSubmitButton.disabled = true;
newSubmitButton.textContent = 'Anmelden...';
}
try {
console.log('[Login] Sende Login-Request...');
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password })
});
const data = await response.json();
console.log('[Login] Response Status:', response.status);
console.log('[Login] Response Data:', data);
if (response.ok && data.token) {
console.log('[Login] Login erfolgreich!');
localStorage.setItem('auth_token', data.token);
localStorage.setItem('current_user', JSON.stringify(data.user));
window.location.reload();
} else {
console.log('[Login] Login fehlgeschlagen:', data.error);
errorEl.textContent = data.error || 'Anmeldung fehlgeschlagen';
errorEl.classList.remove('hidden');
}
} catch (err) {
console.error('[Login] Netzwerkfehler:', err);
errorEl.textContent = 'Netzwerkfehler - bitte versuchen Sie es erneut';
errorEl.classList.remove('hidden');
}
// Reset button
if (newSubmitButton) {
newSubmitButton.disabled = false;
newSubmitButton.textContent = 'Anmelden';
}
});
// Additional click handler for button
const newSubmitButton = newForm.querySelector('button[type="submit"]');
if (newSubmitButton) {
newSubmitButton.addEventListener('click', function(e) {
console.log('[Login] Button clicked');
// Let form submit handle it
});
}
console.log('[Login] Handler eingerichtet');
}
// Try multiple times to ensure DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', setupLoginHandler);
} else {
setupLoginHandler();
}
// Backup after 1 second
setTimeout(setupLoginHandler, 1000);
</script>
</body>
</html>