Statt nur Name + Link zeigt jede Projektkarte jetzt ein kleines, skaliertes Live-Fenster der echten Webseite (iframe der previewUrl, responsiv per ResizeObserver auf 1280px-Basisbreite herunterskaliert). Klick aufs Fenster oeffnet die Seite im neuen Tab. Nicht-fertige Projekte zeigen einen Platzhalter statt iframe. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
176 lines
8.7 KiB
HTML
176 lines
8.7 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Kundenbereich – Webklar</title>
|
||
<link rel="stylesheet" href="/login.css">
|
||
<style>
|
||
.viewas-banner {
|
||
display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
|
||
padding: 10px 16px; margin-bottom: 16px; border-radius: 12px;
|
||
background: rgba(251,191,36,0.12); border: 1px solid rgba(251,191,36,0.45);
|
||
}
|
||
|
||
/* Tabs (Muster aus Admin, violett) */
|
||
.portal-tabs { display: flex; gap: 8px; margin: 14px 0 22px; flex-wrap: wrap; }
|
||
.portal-tab {
|
||
background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.14);
|
||
color: inherit; padding: 9px 18px; border-radius: 999px; cursor: pointer; font: inherit;
|
||
display: inline-flex; align-items: center; gap: 8px;
|
||
}
|
||
.portal-tab.active { background: rgba(157,61,254,0.22); border-color: rgba(157,61,254,0.65); }
|
||
.portal-section { display: none; }
|
||
.portal-section.active { display: block; }
|
||
.portal-section-title { margin: 0 0 14px; font-size: 20px; }
|
||
|
||
.badge-pill {
|
||
display: inline-flex; min-width: 20px; height: 20px; padding: 0 6px;
|
||
align-items: center; justify-content: center; border-radius: 999px;
|
||
background: #9d3dfe; color: #fff; font-size: 12px; font-weight: 700;
|
||
}
|
||
|
||
.simple-table { width: 100%; border-collapse: collapse; font-size: 14px; }
|
||
.simple-table th, .simple-table td { text-align: left; padding: 8px 10px; border-bottom: 1px solid rgba(255,255,255,0.08); }
|
||
.simple-table th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.65; }
|
||
.simple-table tr:last-child td { border-bottom: none; }
|
||
.btn-link { color: #7dd3fc; text-decoration: none; }
|
||
.btn-link:hover { text-decoration: underline; }
|
||
|
||
.pill { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 12px; border: 1px solid transparent; white-space: nowrap; }
|
||
.pill-ok { background: rgba(74,222,128,0.15); border-color: rgba(74,222,128,0.4); }
|
||
.pill-warn { background: rgba(157,61,254,0.18); border-color: rgba(157,61,254,0.5); }
|
||
.pill-red { background: rgba(248,113,113,0.15); border-color: rgba(248,113,113,0.45); }
|
||
.pill-muted { background: rgba(255,255,255,0.07); border-color: rgba(255,255,255,0.16); opacity: 0.85; }
|
||
.pill-git { background: rgba(251,146,60,0.16); border-color: rgba(251,146,60,0.5); }
|
||
|
||
.activity-item { padding: 10px 0; border-bottom: 1px solid rgba(255,255,255,0.08); }
|
||
.activity-item:last-child { border-bottom: none; }
|
||
.activity-status {
|
||
display: inline-block; margin-left: 6px; padding: 1px 9px; border-radius: 999px; font-size: 12px;
|
||
background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.16);
|
||
}
|
||
.activity-ws { font-size: 13px; opacity: 0.85; margin: 4px 0 4px 14px; white-space: pre-wrap; }
|
||
|
||
/* Projekt-Details */
|
||
.project-details-toggle { margin-top: 10px; }
|
||
.project-details { margin-top: 14px; border-top: 1px solid rgba(255,255,255,0.1); padding-top: 12px; }
|
||
.project-details h3 { margin: 12px 0 8px; font-size: 15px; }
|
||
.commit-item { padding: 6px 0; border-bottom: 1px solid rgba(255,255,255,0.06); font-size: 14px; }
|
||
.commit-item:last-child { border-bottom: none; }
|
||
.commit-meta { font-size: 12px; opacity: 0.6; }
|
||
.commit-body { font-size: 13px; opacity: 0.8; white-space: pre-wrap; margin: 2px 0 0 8px; }
|
||
|
||
/* Projekt-Vorschaufenster */
|
||
.preview-frame {
|
||
position: relative; display: block; width: 100%; aspect-ratio: 16 / 10;
|
||
overflow: hidden; border-radius: 12px; border: 1px solid rgba(255,255,255,0.14);
|
||
background: rgba(255,255,255,0.04); margin-bottom: 1rem; text-decoration: none;
|
||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
||
}
|
||
.preview-frame:hover { border-color: rgba(157,61,254,0.7); box-shadow: 0 0 0 1px rgba(157,61,254,0.35); }
|
||
.preview-frame__view {
|
||
position: absolute; top: 0; left: 0; width: 1280px; height: 800px; border: 0;
|
||
transform-origin: 0 0; pointer-events: none; background: #fff;
|
||
}
|
||
.preview-frame__hint {
|
||
position: absolute; left: 0; right: 0; bottom: 0; padding: 10px 14px;
|
||
font-size: 13px; font-weight: 600; color: #fff;
|
||
background: linear-gradient(to top, rgba(0,0,0,0.6), rgba(0,0,0,0));
|
||
opacity: 0; transition: opacity 0.2s ease; pointer-events: none;
|
||
}
|
||
.preview-frame:hover .preview-frame__hint { opacity: 1; }
|
||
.preview-frame--empty {
|
||
display: flex; align-items: center; justify-content: center;
|
||
color: rgba(255,255,255,0.5); font-size: 14px; aspect-ratio: 16 / 10;
|
||
}
|
||
.preview-open { margin: 0.75rem 0 0; }
|
||
|
||
/* Chat */
|
||
.chat-box { display: flex; flex-direction: column; height: 480px; }
|
||
.chat-messages { flex: 1; overflow-y: auto; padding: 6px 4px; display: flex; flex-direction: column; gap: 10px; }
|
||
.chat-bubble { max-width: 78%; padding: 10px 14px; border-radius: 16px; font-size: 14px; white-space: pre-wrap; word-break: break-word; }
|
||
.chat-bubble .chat-meta { display: block; font-size: 11px; opacity: 0.6; margin-top: 4px; }
|
||
.chat-bubble.mine { align-self: flex-end; background: rgba(157,61,254,0.3); border: 1px solid rgba(157,61,254,0.5); border-bottom-right-radius: 4px; }
|
||
.chat-bubble.theirs { align-self: flex-start; background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.14); border-bottom-left-radius: 4px; }
|
||
.chat-input-row { display: flex; gap: 10px; margin-top: 12px; align-items: flex-end; }
|
||
.chat-input-row textarea {
|
||
flex: 1; resize: none; min-height: 46px; max-height: 130px; padding: 12px 14px;
|
||
border-radius: 14px; border: 1px solid rgba(255,255,255,0.18);
|
||
background: rgba(255,255,255,0.06); color: inherit; font: inherit;
|
||
}
|
||
.chat-send {
|
||
background: #9d3dfe; border: none; color: #fff; font: inherit; font-weight: 600;
|
||
padding: 12px 20px; border-radius: 14px; cursor: pointer;
|
||
}
|
||
.chat-send:disabled { opacity: 0.5; cursor: default; }
|
||
.chat-hint { font-size: 12px; opacity: 0.55; margin-top: 6px; }
|
||
</style>
|
||
</head>
|
||
<body class="portal-page dashboard-page">
|
||
<div class="dot-background" aria-hidden="true">
|
||
<div class="dot-pattern"></div>
|
||
<div class="dot-fade"></div>
|
||
</div>
|
||
|
||
<header class="portal-header">
|
||
<a class="portal-logo" href="/dashboard.html">Webklar</a>
|
||
<div class="portal-header-actions">
|
||
<span class="portal-meta" id="customer-meta"></span>
|
||
<button type="button" class="portal-btn-outline" id="logout-btn">Abmelden</button>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="portal-main dashboard-content-reveal">
|
||
<div id="viewas-banner" class="viewas-banner hidden"></div>
|
||
|
||
<h1 class="portal-title">Kundenbereich</h1>
|
||
<p id="load-error" class="error hidden"></p>
|
||
|
||
<div class="portal-tabs">
|
||
<button class="portal-tab active" data-tab="projects">Projekte</button>
|
||
<button class="portal-tab" data-tab="activity">Was wurde gemacht</button>
|
||
<button class="portal-tab" data-tab="invoices">Rechnungen</button>
|
||
<button class="portal-tab" data-tab="chat">Chat <span id="chat-badge" class="badge-pill hidden"></span></button>
|
||
</div>
|
||
|
||
<!-- Projekte -->
|
||
<section class="portal-section active" id="tab-projects">
|
||
<p id="loading" class="muted portal-status">Projekte werden geladen…</p>
|
||
<ul id="projects" class="projects hidden"></ul>
|
||
<p id="empty" class="portal-card hidden portal-status">Noch keine Website-Projekte zugewiesen.</p>
|
||
</section>
|
||
|
||
<!-- Was wurde gemacht -->
|
||
<section class="portal-section" id="tab-activity">
|
||
<h2 class="portal-section-title">Was wurde gemacht</h2>
|
||
<div class="portal-card" id="activity-body"><p class="muted">Lade…</p></div>
|
||
</section>
|
||
|
||
<!-- Rechnungen -->
|
||
<section class="portal-section" id="tab-invoices">
|
||
<h2 class="portal-section-title">Meine Rechnungen</h2>
|
||
<div class="portal-card" id="invoices-body"><p class="muted">Lade…</p></div>
|
||
</section>
|
||
|
||
<!-- Chat -->
|
||
<section class="portal-section" id="tab-chat">
|
||
<h2 class="portal-section-title">Chat mit dem Webklar-Team</h2>
|
||
<div class="portal-card chat-box">
|
||
<div class="chat-messages" id="chat-messages"></div>
|
||
<div class="chat-input-row">
|
||
<textarea id="chat-input" maxlength="2000" placeholder="Nachricht an das Webklar-Team…"></textarea>
|
||
<button type="button" class="chat-send" id="chat-send">Senden</button>
|
||
</div>
|
||
<p class="chat-hint">Enter = Senden, Shift+Enter = Zeilenumbruch. Wir antworten in der Regel innerhalb eines Werktags.</p>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<script src="/app.js"></script>
|
||
<script>
|
||
initDashboardPage();
|
||
</script>
|
||
</body>
|
||
</html>
|