Files
Webklar-Kundenbereich/public/dashboard.html
T
ClaudeandClaude Opus 5.5 ba9916cfe6 Projektdetails und Fortschritt kundenverständlich
Der Server bereitet Commits, Tickets und Arbeitseinträge für Kunden auf
(server/services/customerProjectView.js), die Rohdaten bleiben intern:
- keine Co-Authored-By-/Signed-off-by-Zeilen und KI-Hinweise, keine
  Commit-Kürzel, Kontonamen, Git-Links oder Branch
- technische Commits (Preview-Config, Merges) ausgeblendet, bekannte
  Automatik-Texte übersetzt, "fix"/"upload" -> "Website aktualisiert"
- Ticketstatus und Arbeitsarten auf Deutsch (Open -> Eingegangen,
  Remote -> Online erledigt, ...), Fortschritt in 4 Schritten
- Akquise-Tickets auch in den Projektdetails verborgen
- /api/projects ohne Gitea-URL, Repo- und Vorlagennamen

Darstellung: Auftragskarte mit Status und Fortschrittsleiste, Zeitleiste
"Letzte Änderungen" nach Tagen, Arbeiten mit Farbe/Symbol je Art und
Arbeitszeit; der Tab "Fortschritt" nutzt dieselben Bausteine. In der
App-Ansicht öffnen sich die Projektdetails als eigene Seite mit Zurück
zu "Projekte".

Tests: npm test (node --test, 22 Fälle).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 18:46:22 +00:00

220 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content">
<title>Kundenbereich – WEBklar</title>
<!-- Als App auf den Homescreen: Manifest, Icons, Statusleiste (App-Ansicht auf dem Handy, kundenbereich.css) -->
<link rel="manifest" href="/manifest.webmanifest">
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/img/apple-touch-icon.png">
<meta name="theme-color" content="#000000">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<!-- Durchsichtige Statusleiste: der lila Hintergrund reicht bis in die Notch. Damit fixierte Leisten
trotzdem ganz unten sitzen, bleibt die Seite in der installierten App immer 1 px scrollbar
(siehe "Installierte App auf dem iPhone" in login.css/kundenbereich.css) -->
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="WEBklar">
<link rel="stylesheet" href="/login.css">
<link rel="stylesheet" href="/kundenbereich.css">
<link rel="stylesheet" href="/chat-composer.css">
</head>
<body class="portal-page dashboard-page kb-page">
<div class="dot-background" aria-hidden="true">
<div class="dot-pattern"></div>
<div class="dot-fade"></div>
</div>
<div class="kb-glow" aria-hidden="true"></div>
<header class="kb-header">
<!-- App-Ansicht: Zurueck aus Unterseiten (Wartung, Projektdetails; Text setzt updateAppBar), Seitentitel beim Scrollen (initAppShell) -->
<button type="button" class="kb-back hidden" id="kb-back" aria-label="Zurück zu Wartung">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15 18l-6-6 6-6"/></svg>
<span>Wartung</span>
</button>
<div class="kb-bar-title">
<a class="kb-logo" href="/dashboard.html"><svg class="kb-logo-mark" viewBox="0 0 512 512" aria-hidden="true"><rect width="512" height="512" fill="#fff"/><g transform="translate(256 256) scale(0.9) translate(-256 -256)"><ellipse cx="256" cy="256" rx="210" ry="150" fill="#111" transform="rotate(-28 256 256)"/><circle cx="356" cy="172" r="18" fill="#fff"/><path transform="translate(256 256) rotate(-28)" d="M 0,-170 C 22,-105 60,-72 120,-56 C 60,-40 22,-8 0,64 C -22,-8 -60,-40 -120,-56 C -60,-72 -22,-105 0,-170 Z" fill="#fff"/></g></svg>WEBKLAR</a>
<span class="kb-app-title" id="kb-app-title" aria-hidden="true"></span>
</div>
<div class="kb-account">
<div class="kb-account-text">
<strong id="customer-name"></strong>
<span id="customer-meta"></span>
</div>
<button type="button" class="kb-avatar" id="customer-avatar" aria-label="Mein Konto" title="Mein Konto" aria-haspopup="dialog" aria-controls="kb-sheet"></button>
</div>
</header>
<!-- Konto: auf dem Handy als Bottom-Sheet, am Desktop als Popover unter dem Avatar (initAccountSheet).
Alles zu den Verträgen und "Abmelden" steht im Kundenbereich nur hier. Einzige Ausnahme: während
der Widerrufsfrist zeigt die Wartungskarte "Vertrag widerrufen" (§ 356a BGB: hervorgehoben platziert).
Öffentlich, ohne Anmeldung: Login-Seite und Footer von webklar.com. -->
<dialog class="kb-sheet" id="kb-sheet" aria-label="Mein Konto">
<div class="kb-sheet-panel">
<div class="kb-sheet-grip" aria-hidden="true"></div>
<div class="kb-sheet-me">
<span class="kb-avatar" id="kb-sheet-avatar" aria-hidden="true"></span>
<div class="kb-sheet-me-text">
<strong id="kb-sheet-name">Mein Konto</strong>
<span id="kb-sheet-meta"></span>
</div>
<button type="button" class="kb-sheet-x" data-sheet-close aria-label="Schließen">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg>
</button>
</div>
<!-- App-Ansicht: hierher wandert die Karte "Dein Ansprechpartner" aus der Seitenleiste -->
<div id="kb-contact-slot"></div>
<div class="kb-install hidden" data-install></div>
<p class="kb-label kb-sheet-label">Verträge</p>
<nav class="kb-sheet-links" aria-label="Verträge">
<!-- Nur mit Wartungs-Abo: Stripe-Kundenportal; Name wie in den Bedingungen § 7 ("Abo verwalten") -->
<button type="button" class="kb-sheet-ext hidden" id="kb-sheet-abo">Abo verwalten &amp; Rechnungen</button>
<a href="/abo-bedingungen.html" target="_blank" rel="noopener">Vertragsbedingungen</a>
<a class="legal-strong" href="/kuendigen.html">Verträge hier kündigen</a>
<a class="legal-strong" href="/widerrufen.html">Vertrag widerrufen</a>
</nav>
<p class="error hidden" id="kb-sheet-error"></p>
<nav class="kb-sheet-links" aria-label="Rechtliches">
<a href="/datenschutz.html" target="_blank" rel="noopener">Datenschutz</a>
<a href="https://webklar.com/impressum" target="_blank" rel="noopener">Impressum</a>
</nav>
<button type="button" class="kb-sheet-logout" id="kb-sheet-logout">Abmelden</button>
</div>
</dialog>
<div class="kb-shell dashboard-content-reveal">
<!-- Seitenleiste: Navigation, Ansprechpartner, Wartungs-Abo. In der App-Ansicht (Handy)
wird die Navigation zur Tab-Leiste unten; die Karten wandern in Konto-Sheet bzw. Tab "Wartung". -->
<aside class="kb-side">
<p class="kb-label">Kundenbereich</p>
<nav class="kb-nav" aria-label="Kundenbereich">
<button type="button" class="kb-nav-item active" data-view="projects">
<svg class="kb-tab-ico" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="3"/><path d="M3 9h18M6.5 6.5h.01M9.5 6.5h.01"/></svg>
<span class="kb-tab-label">Projekte</span> <span class="kb-count" id="projects-count"></span></button>
<button type="button" class="kb-nav-item" data-view="activity">
<svg class="kb-tab-ico" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 12h4l3-7 4 14 3-7h4"/></svg>
<span class="kb-tab-label">Fortschritt</span></button>
<button type="button" class="kb-nav-item" data-view="invoices">
<svg class="kb-tab-ico" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 3h12v18l-3-2-3 2-3-2-3 2z"/><path d="M9 8h6M9 12h6M9 16h3"/></svg>
<span class="kb-tab-label">Rechnungen</span> <span class="kb-badge kb-badge-red hidden" id="invoices-badge" title="offene Rechnungen"></span></button>
<button type="button" class="kb-nav-item" data-view="chat">
<svg class="kb-tab-ico" viewBox="0 0 24 24" aria-hidden="true"><path d="M20 14.5a2.5 2.5 0 0 1-2.5 2.5H8l-4 4V5.5A2.5 2.5 0 0 1 6.5 3h11A2.5 2.5 0 0 1 20 5.5z"/></svg>
<span class="kb-tab-label">Chat</span> <span class="kb-badge hidden" id="chat-badge" title="ungelesene Nachrichten"></span></button>
<!-- Nur App-Ansicht; am Desktop steht die Wartung als Karte in der Seitenleiste -->
<button type="button" class="kb-nav-item kb-tab-wartung hidden" data-view="wartung" id="kb-tab-wartung">
<svg class="kb-tab-ico" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3l7 3v5.5c0 4.3-2.9 8.1-7 9.5-4.1-1.4-7-5.2-7-9.5V6z"/><path d="M9 12l2 2 4-4"/></svg>
<span class="kb-tab-label">Wartung</span> <span class="kb-badge hidden" id="kb-tab-wartung-badge"></span></button>
</nav>
<section class="kb-card kb-contact" aria-label="Ansprechpartner">
<p class="kb-label">Dein Ansprechpartner</p>
<strong id="contact-name">WEBklar-Team</strong>
<span id="contact-response">Antwort meist &lt; 1 Werktag</span>
<button type="button" data-view="chat">Nachricht schreiben</button>
</section>
<!-- Wartungs-Abo: Angebot bzw. Status (app.js) -->
<section class="kb-abo hidden" id="abo-card" aria-live="polite"></section>
</aside>
<main class="kb-main">
<div id="viewas-banner" class="viewas-banner hidden"></div>
<p id="load-error" class="error hidden"></p>
<!-- Projekte -->
<section class="kb-view active" id="view-projects">
<header class="kb-head">
<h1>Projekte</h1>
<p id="projects-subtitle">Deine Website – Vorschau, Status und Details.</p>
</header>
<!-- App-Ansicht im Browser: Hinweis "Zum Homescreen hinzufügen" (ausblendbar) -->
<div class="kb-install kb-install-card hidden" data-install data-install-dismissible></div>
<p id="loading" class="kb-empty">Projekte werden geladen…</p>
<ul id="projects" class="kb-projects hidden"></ul>
<div id="empty" class="kb-panel kb-empty hidden">Noch keine Website-Projekte zugewiesen.</div>
</section>
<!-- App-Ansicht: Projektdetails als eigene Seite mit Zurueck zu "Projekte" (app.js, openProjectPage);
am Desktop klappen die Details in der Projektkarte auf -->
<section class="kb-view" id="view-projekt">
<header class="kb-head">
<h1>Projekt</h1>
<p>Stand des Auftrags, letzte Änderungen und Dateien.</p>
</header>
<div class="kb-details pd-page"></div>
</section>
<!-- Fortschritt -->
<section class="kb-view" id="view-activity">
<header class="kb-head">
<h1>Fortschritt</h1>
<p>Was wir an deinen Projekten erledigt haben.</p>
</header>
<div class="kb-panel" id="activity-body"><p class="kb-empty">Lade…</p></div>
</section>
<!-- Rechnungen -->
<section class="kb-view" id="view-invoices">
<header class="kb-head">
<h1>Rechnungen</h1>
<p>Deine Rechnungen ansehen, bezahlen und herunterladen.</p>
</header>
<div class="kb-panel" id="invoices-body"><p class="kb-empty">Lade…</p></div>
<p class="kb-note hidden" id="invoices-abo-note">Rechnungen zum Wartungs-Abo findest du über dein <button type="button" class="kb-link" data-open-account>Profilbild</button> oben rechts unter „Abo verwalten &amp; Rechnungen“.</p>
</section>
<!-- Chat -->
<section class="kb-view" id="view-chat">
<header class="kb-head">
<h1>Chat</h1>
<p>Schreib uns – wir antworten meist innerhalb eines Werktags.</p>
</header>
<div class="kb-panel chat-box">
<div class="chat-messages" id="chat-messages"></div>
<!-- Eingabezeile mit Bild, Kamera, Datei und Sprachnachricht (chat-composer.js) -->
<div id="chat-composer"></div>
<p class="chat-hint">Enter = Senden, Shift+Enter = neue Zeile. Bilder und Dateien bis 25 MB – auch per Einfügen oder Hineinziehen.</p>
</div>
</section>
<!-- App-Ansicht, Tab "Wartung": die Abo-Karte der Seitenleiste als Übersicht;
Stundenkonto bzw. Bestellung und Übernahmegutschrift öffnen sich als Unterseiten -->
<section class="kb-view" id="view-wartung">
<header class="kb-head">
<h1>Wartung</h1>
<p>Betrieb, Pflege und Support für Ihre Website.</p>
</header>
<div id="kb-abo-slot"><p class="kb-empty">Lade…</p></div>
</section>
<!-- Wartungs-Abo: Bestellung bzw. Stundenkonto (app.js) -->
<section class="kb-view" id="view-abo" aria-live="polite"></section>
<!-- Übernahmegutschrift (app.js) -->
<section class="kb-view" id="view-takeover">
<header class="kb-head">
<h1>Übernahmegutschrift</h1>
<p>Schon woanders bezahlt? Wir rechnen die doppelt bezahlte Zeit an.</p>
</header>
<div id="takeover-card" aria-live="polite"><p class="kb-empty">Lade…</p></div>
</section>
<footer class="kb-legal">
<a href="/abo-bedingungen.html" target="_blank" rel="noopener">Vertragsbedingungen</a>
<a href="/datenschutz.html" target="_blank" rel="noopener">Datenschutz</a>
<a href="https://webklar.com/impressum" target="_blank" rel="noopener">Impressum</a>
</footer>
</main>
</div>
<script src="/chat-composer.js"></script>
<script src="/app.js"></script>
<script>
initDashboardPage();
</script>
</body>
</html>