179 lines
10 KiB
HTML
179 lines
10 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Admin – Webklar Kundenbereich</title>
|
||
<link rel="stylesheet" href="/login.css">
|
||
<style>
|
||
.admin-tabs { display: flex; gap: 8px; margin: 18px 0; flex-wrap: wrap; }
|
||
.admin-tab {
|
||
background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.14);
|
||
color: inherit; padding: 8px 16px; border-radius: 999px; cursor: pointer; font: inherit;
|
||
}
|
||
.admin-tab.active { background: rgba(94,234,212,0.16); border-color: rgba(94,234,212,0.5); }
|
||
.admin-section { display: none; }
|
||
.admin-section.active { display: block; }
|
||
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 18px; }
|
||
.stat-tile { padding: 14px 16px; border-radius: 12px; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); }
|
||
.stat-tile .num { font-size: 26px; font-weight: 700; display: block; }
|
||
.stat-tile .lbl { font-size: 12px; opacity: 0.7; }
|
||
.admin-search { width: 100%; max-width: 380px; padding: 9px 14px; border-radius: 10px;
|
||
border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.06); color: inherit; margin-bottom: 12px; }
|
||
.admin-table-wrap { overflow-x: auto; border-radius: 12px; border: 1px solid rgba(255,255,255,0.1); }
|
||
/* Kundentabelle: volle Breite, kein Links-/Rechts-Scroll */
|
||
.admin-table-wrap.no-scroll { overflow-x: visible; }
|
||
.admin-table-wrap.no-scroll table.admin-table { table-layout: fixed; }
|
||
.admin-table-wrap.no-scroll .admin-table td { word-break: break-word; overflow-wrap: anywhere; }
|
||
.cust-actions { display: flex; flex-wrap: wrap; gap: 6px; }
|
||
table.admin-table { width: 100%; border-collapse: collapse; font-size: 14px; }
|
||
.admin-table th, .admin-table td { text-align: left; padding: 9px 12px; border-bottom: 1px solid rgba(255,255,255,0.08); vertical-align: middle; }
|
||
.admin-table th { font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.65; }
|
||
.admin-table tr:last-child td { border-bottom: none; }
|
||
.pill { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 12px; border: 1px solid transparent; }
|
||
.pill-ok { background: rgba(74,222,128,0.15); border-color: rgba(74,222,128,0.4); }
|
||
.pill-warn { background: rgba(251,191,36,0.15); border-color: rgba(251,191,36,0.45); }
|
||
.pill-muted { background: rgba(255,255,255,0.07); border-color: rgba(255,255,255,0.16); opacity: 0.8; }
|
||
.pill-red { background: rgba(248,113,113,0.15); border-color: rgba(248,113,113,0.45); }
|
||
.mini-btn { background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.18); color: inherit;
|
||
padding: 5px 11px; border-radius: 8px; cursor: pointer; font-size: 13px; white-space: nowrap; }
|
||
.mini-btn:hover { background: rgba(255,255,255,0.14); }
|
||
.mini-btn.primary { background: rgba(94,234,212,0.16); border-color: rgba(94,234,212,0.5); }
|
||
.code-input { width: 100%; min-width: 60px; max-width: 90px; padding: 4px 8px; border-radius: 7px; border: 1px solid rgba(255,255,255,0.2);
|
||
background: rgba(255,255,255,0.06); color: inherit; font: inherit; font-size: 13px; }
|
||
.detail-row td { background: rgba(255,255,255,0.03); }
|
||
.detail-box { padding: 6px 4px; }
|
||
.detail-box h4 { margin: 8px 0 4px; font-size: 13px; }
|
||
.detail-box .muted { opacity: 0.65; }
|
||
.ws-line { font-size: 13px; opacity: 0.85; margin: 2px 0 2px 14px; }
|
||
a.plain { color: #7dd3fc; text-decoration: none; }
|
||
a.plain:hover { text-decoration: underline; }
|
||
.admin-note { font-size: 13px; opacity: 0.65; margin: 8px 0 0; }
|
||
.flex-between { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
|
||
.recent-list { list-style: none; margin: 0; padding: 0; }
|
||
.recent-list li { padding: 7px 0; border-bottom: 1px solid rgba(255,255,255,0.07); font-size: 14px; }
|
||
.recent-list li:last-child { border-bottom: none; }
|
||
.two-col { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 14px; }
|
||
|
||
/* Chat */
|
||
.badge-pill {
|
||
display: inline-flex; min-width: 20px; height: 20px; padding: 0 6px;
|
||
align-items: center; justify-content: center; border-radius: 999px;
|
||
background: #f87171; color: #fff; font-size: 12px; font-weight: 700;
|
||
}
|
||
.chat-layout { display: grid; grid-template-columns: 280px 1fr; gap: 14px; min-height: 480px; }
|
||
@media (max-width: 760px) { .chat-layout { grid-template-columns: 1fr; } }
|
||
.chat-list { border: 1px solid rgba(255,255,255,0.1); border-radius: 12px; overflow-y: auto; max-height: 560px; }
|
||
.chat-list-item { padding: 12px 14px; border-bottom: 1px solid rgba(255,255,255,0.07); cursor: pointer; }
|
||
.chat-list-item:hover { background: rgba(255,255,255,0.05); }
|
||
.chat-list-item.active { background: rgba(94,234,212,0.1); }
|
||
.chat-list-item .last { font-size: 12px; opacity: 0.6; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
.chat-thread { display: flex; flex-direction: column; border: 1px solid rgba(255,255,255,0.1); border-radius: 12px; padding: 12px; }
|
||
.chat-messages { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; padding: 4px; max-height: 440px; }
|
||
.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(94,234,212,0.18); border: 1px solid rgba(94,234,212,0.45); 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: 44px; max-height: 120px; padding: 10px 12px;
|
||
border-radius: 12px; border: 1px solid rgba(255,255,255,0.18);
|
||
background: rgba(255,255,255,0.06); color: inherit; font: inherit;
|
||
}
|
||
.chat-empty { display: flex; align-items: center; justify-content: center; flex: 1; opacity: 0.6; }
|
||
</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="/admin.html">Webklar <span style="opacity:.6">Admin</span></a>
|
||
<div class="portal-header-actions">
|
||
<span class="portal-meta" id="admin-meta"></span>
|
||
<button type="button" class="portal-btn-outline" id="logout-btn">Abmelden</button>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="portal-main dashboard-content-reveal">
|
||
<h1 class="portal-title">Admin-Übersicht</h1>
|
||
<p id="admin-error" class="error hidden"></p>
|
||
|
||
<div class="admin-tabs">
|
||
<button class="admin-tab active" data-tab="overview">Übersicht</button>
|
||
<button class="admin-tab" data-tab="projects">Projekte</button>
|
||
<button class="admin-tab" data-tab="customers">Kunden</button>
|
||
<button class="admin-tab" data-tab="chat">Chat <span id="admin-chat-badge" class="badge-pill hidden"></span></button>
|
||
</div>
|
||
|
||
<!-- Übersicht -->
|
||
<section class="admin-section active" id="tab-overview">
|
||
<div class="stat-grid" id="stat-grid"><span class="portal-status">Lade…</span></div>
|
||
<div class="two-col">
|
||
<div class="portal-card">
|
||
<h3>Letzte Portal-Logins</h3>
|
||
<ul class="recent-list" id="recent-logins"><li class="muted">Lade…</li></ul>
|
||
</div>
|
||
<div class="portal-card">
|
||
<h3>Zuletzt aktualisierte Projekte</h3>
|
||
<ul class="recent-list" id="recent-projects"><li class="muted">Lade…</li></ul>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Projekte -->
|
||
<section class="admin-section" id="tab-projects">
|
||
<input class="admin-search" id="project-search" type="search"
|
||
placeholder="Projekte suchen (Name, Subdomain, Repo, Kunde)…">
|
||
<div class="admin-table-wrap">
|
||
<table class="admin-table">
|
||
<thead>
|
||
<tr><th>Projekt</th><th>Subdomain</th><th>Kunde</th><th>Status</th><th>Typ</th><th>Links</th></tr>
|
||
</thead>
|
||
<tbody id="project-rows"><tr><td colspan="6" class="muted">Lade…</td></tr></tbody>
|
||
</table>
|
||
</div>
|
||
<p class="admin-note">Als Admin kannst du jede Projekt-Vorschau direkt öffnen – ohne Kunden-Login.</p>
|
||
</section>
|
||
|
||
<!-- Kunden -->
|
||
<section class="admin-section" id="tab-customers">
|
||
<input class="admin-search" id="customer-search" type="search"
|
||
placeholder="Kunden suchen (Kundennr., Name, E-Mail, Ort)…">
|
||
<div class="admin-table-wrap no-scroll">
|
||
<table class="admin-table">
|
||
<colgroup>
|
||
<col style="width:9%"><col style="width:23%"><col style="width:11%"><col style="width:11%">
|
||
<col style="width:13%"><col style="width:8%"><col style="width:25%">
|
||
</colgroup>
|
||
<thead>
|
||
<tr><th>Kundennr.</th><th>Kunde</th><th>Status</th><th>Portal</th><th>Letzter Login</th><th>Projekte</th><th>Aktionen</th></tr>
|
||
</thead>
|
||
<tbody id="customer-rows"><tr><td colspan="7" class="muted">Lade…</td></tr></tbody>
|
||
</table>
|
||
</div>
|
||
<p class="admin-note">Kundennummer direkt im Feld ändern und mit ✓ speichern. „Als Kunde ansehen“ zeigt dir das Portal genau so, wie der Kunde es sieht.</p>
|
||
</section>
|
||
|
||
<!-- Chat -->
|
||
<section class="admin-section" id="tab-chat">
|
||
<div class="chat-layout">
|
||
<div class="chat-list" id="admin-chat-list">
|
||
<div class="chat-list-item"><span class="muted">Lade Unterhaltungen…</span></div>
|
||
</div>
|
||
<div class="chat-thread" id="admin-chat-thread">
|
||
<div class="chat-empty">Unterhaltung links auswählen</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<script src="/admin.js"></script>
|
||
<script>
|
||
initAdminPage();
|
||
</script>
|
||
</body>
|
||
</html>
|