Redesign overview page: hero card, activity sparklines, quick-actions grid, module badges
Some checks failed
Deploy Discord Bot / deploy (push) Has been cancelled

This commit is contained in:
Pepe44DEV
2026-07-01 03:16:21 +02:00
parent f7f43aa52a
commit 17fa8c3edb

View File

@@ -327,16 +327,54 @@ router.get('/', (req, res) => {
.linkish:hover { text-decoration:underline; } .linkish:hover { text-decoration:underline; }
.section-title { font-size:18px; font-weight:800; margin:0; letter-spacing:-0.02em; } .section-title { font-size:18px; font-weight:800; margin:0; letter-spacing:-0.02em; }
.section-sub { color:var(--muted); margin:4px 0 0; font-size:13px; line-height:1.5; } .section-sub { color:var(--muted); margin:4px 0 0; font-size:13px; line-height:1.5; }
.overview-hero { display:flex; gap:16px; align-items:center; justify-content:space-between; padding:22px 24px; }
.overview-hero-main { display:flex; gap:16px; align-items:center; min-width:0; flex:1; }
.overview-avatar { width:64px; height:64px; border-radius:20px; object-fit:cover; border:1px solid rgba(255,255,255,0.12); box-shadow:0 16px 32px rgba(0,0,0,0.3); }
.overview-copy { min-width:0; flex:1; }
.overview-id { color:var(--muted); margin:6px 0 10px; font-size:13px; }
.overview-status { display:flex; align-items:center; gap:10px; white-space:nowrap; color:var(--muted-strong); font-weight:700; }
.status-dot { width:10px; height:10px; border-radius:50%; background:#22c55e; box-shadow:0 0 0 6px rgba(34,197,94,0.12); }
.overview-grid { display:grid; gap:16px; grid-template-columns:1.05fr 1.05fr 1fr; margin-top:16px; }
.overview-panel { min-height:350px; }
.overview-panel .section-title { font-size:17px; }
.overview-panel .detail-grid { margin-top:14px; grid-template-columns:repeat(2, minmax(0, 1fr)); }
.overview-stat { padding:14px 16px; }
.overview-stat-value { font-size:16px; font-weight:800; color:var(--text); }
.activity-list { display:flex; flex-direction:column; gap:12px; margin-top:14px; }
.activity-card { display:flex; align-items:center; justify-content:space-between; gap:14px; padding:16px 18px; border:1px solid rgba(255,255,255,0.08); border-radius:18px; background:linear-gradient(180deg, rgba(255,255,255,0.045), rgba(255,255,255,0.025)); box-shadow:0 16px 32px rgba(0,0,0,0.24); }
.activity-card-main { display:flex; align-items:center; gap:12px; }
.activity-icon { width:42px; height:42px; border-radius:14px; display:flex; align-items:center; justify-content:center; font-size:18px; background:rgba(249,115,22,0.12); border:1px solid rgba(249,115,22,0.18); color:#ffd7b0; }
.activity-icon.commands { background:rgba(234,88,12,0.12); color:#fdba74; }
.activity-icon.automod { background:rgba(21,128,61,0.14); color:#86efac; border-color:rgba(34,197,94,0.16); }
.activity-value { font-size:18px; font-weight:800; color:var(--text); margin-top:2px; }
.activity-spark { width:92px; height:28px; border-radius:999px; position:relative; overflow:hidden; }
.activity-spark::before { content:''; position:absolute; inset:0; border-radius:999px; opacity:0.9; }
.activity-spark.messages::before { background:linear-gradient(135deg, transparent 0 10%, rgba(255,255,255,0) 10% 16%, rgba(255,176,102,0.95) 16% 20%, transparent 20% 36%, rgba(255,176,102,0.95) 36% 44%, transparent 44% 58%, rgba(255,176,102,0.8) 58% 65%, transparent 65%); }
.activity-spark.commands::before { background:linear-gradient(135deg, transparent 0 12%, rgba(168,85,247,0.9) 12% 18%, transparent 18% 34%, rgba(192,132,252,0.92) 34% 46%, transparent 46% 62%, rgba(168,85,247,0.72) 62% 70%, transparent 70%); }
.activity-spark.automod::before { background:linear-gradient(135deg, transparent 0 18%, rgba(74,222,128,0.86) 18% 24%, transparent 24% 42%, rgba(74,222,128,0.95) 42% 51%, transparent 51% 66%, rgba(34,197,94,0.78) 66% 74%, transparent 74%); }
.logs-panel .log-list { margin-top:14px; }
.panel-action { margin-top:18px; width:100%; justify-content:center; }
.panel-action.secondary-btn { display:flex; align-items:center; justify-content:center; gap:10px; }
.quick-actions { margin-top:16px; }
.quick-actions-grid { display:grid; grid-template-columns:repeat(6, minmax(0, 1fr)); gap:14px; margin-top:16px; }
.quick-action { text-align:left; padding:16px 16px 14px; border-radius:18px; border:1px solid rgba(255,255,255,0.08); background:linear-gradient(180deg, rgba(255,255,255,0.045), rgba(255,255,255,0.02)); box-shadow:0 16px 32px rgba(0,0,0,0.22); }
.quick-action-head { display:flex; align-items:center; gap:10px; margin-bottom:8px; font-weight:800; color:var(--text); }
.quick-action-icon { width:38px; height:38px; border-radius:14px; display:flex; align-items:center; justify-content:center; font-size:17px; background:rgba(249,115,22,0.14); color:#ffd7b0; border:1px solid rgba(249,115,22,0.18); }
.quick-action p { margin:0; color:var(--muted); font-size:12px; line-height:1.5; }
.spinner { width:28px; height:28px; border:3px solid rgba(255,255,255,0.12); border-top-color:var(--accent); border-radius:50%; animation:spin .6s linear infinite; margin:12px auto; } .spinner { width:28px; height:28px; border:3px solid rgba(255,255,255,0.12); border-top-color:var(--accent); border-radius:50%; animation:spin .6s linear infinite; margin:12px auto; }
@media (max-width: 1180px) { @media (max-width: 1180px) {
.layout { flex-direction:column; } .layout { flex-direction:column; }
.sidebar { width:100%; min-height:auto; position:relative; } .sidebar { width:100%; min-height:auto; position:relative; }
.content { padding:22px 18px 40px; } .content { padding:22px 18px 40px; }
.overview-grid { grid-template-columns:1fr; }
.quick-actions-grid { grid-template-columns:repeat(3, minmax(0, 1fr)); }
} }
@media (max-width: 900px) { @media (max-width: 900px) {
.topbar { flex-direction:column; } .topbar { flex-direction:column; }
.guild-select-shell { width:100%; min-width:0; } .guild-select-shell { width:100%; min-width:0; }
h1 { font-size:28px; } h1 { font-size:28px; }
.overview-hero { flex-direction:column; align-items:flex-start; }
.overview-hero-main { width:100%; }
} }
@media (max-width: 720px) { @media (max-width: 720px) {
.sidebar { padding:22px 14px 16px; } .sidebar { padding:22px 14px 16px; }
@@ -344,6 +382,9 @@ router.get('/', (req, res) => {
.card { padding:18px; border-radius:20px; } .card { padding:18px; border-radius:20px; }
.grid, .tickets-grid, .detail-grid { grid-template-columns:1fr; } .grid, .tickets-grid, .detail-grid { grid-template-columns:1fr; }
.row, .inline, .form-row { flex-direction:column; align-items:stretch; } .row, .inline, .form-row { flex-direction:column; align-items:stretch; }
.overview-panel .detail-grid, .quick-actions-grid { grid-template-columns:1fr; }
.activity-card { flex-direction:column; align-items:flex-start; }
.activity-spark { width:100%; }
} }
@keyframes spin { to { transform:rotate(360deg); } } @keyframes spin { to { transform:rotate(360deg); } }
.loading-wrap { display:flex; flex-direction:column; align-items:center; gap:6px; padding:24px; color:var(--muted); font-size:13px; } .loading-wrap { display:flex; flex-direction:column; align-items:center; gap:6px; padding:24px; color:var(--muted); font-size:13px; }
@@ -366,40 +407,86 @@ router.get('/', (req, res) => {
</div> </div>
<main> <main>
<div class="section" data-section="overview"> <div class="section" data-section="overview">
<section class="card" style="display:flex; gap:12px; align-items:center;"> <section class="card overview-hero">
<img id="guildIcon" src="https://cdn.discordapp.com/embed/avatars/0.png" alt="icon" style="width:54px;height:54px;border-radius:14px;object-fit:cover;border:1px solid rgba(255,255,255,0.1);" /> <div class="overview-hero-main">
<div style="flex:1;"> <img id="guildIcon" class="overview-avatar" src="https://cdn.discordapp.com/embed/avatars/0.png" alt="icon" />
<p class="section-title" id="guildName">Guild</p> <div class="overview-copy">
<p class="section-sub">ID: <span id="guildIdLabel">-</span></p> <p class="section-title" id="guildName">Guild</p>
<div class="module-badges" id="guildModules"></div> <p class="overview-id">ID: <span id="guildIdLabel">-</span></p>
<div class="module-badges" id="guildModules"></div>
</div>
</div>
<div class="overview-status">
<span class="status-dot"></span>
<span>Bot aktiv</span>
</div> </div>
<div class="pill">Bot aktiv</div>
</section> </section>
<div class="grid"> <div class="overview-grid">
<section class="card"> <section class="card overview-panel">
<p class="section-title">Guild Infos</p> <p class="section-title">Guild Infos</p>
<div class="detail-grid" style="margin-top:8px;"> <div class="detail-grid">
<div class="detail-tile"><div class="detail-label">Owner</div><div class="detail-value" id="guildOwner">-</div></div> <div class="detail-tile overview-stat"><div class="detail-label">Owner</div><div class="overview-stat-value" id="guildOwner">-</div></div>
<div class="detail-tile"><div class="detail-label">Erstellt</div><div class="detail-value" id="guildCreated">-</div></div> <div class="detail-tile overview-stat"><div class="detail-label">Erstellt</div><div class="overview-stat-value" id="guildCreated">-</div></div>
<div class="detail-tile"><div class="detail-label">Member</div><div class="detail-value" id="guildMembers">-</div></div> <div class="detail-tile overview-stat"><div class="detail-label">Member</div><div class="overview-stat-value" id="guildMembers">-</div></div>
<div class="detail-tile"><div class="detail-label">Channels</div><div class="detail-value" id="guildChannels">-</div></div> <div class="detail-tile overview-stat"><div class="detail-label">Channels</div><div class="overview-stat-value" id="guildChannels">-</div></div>
<div class="detail-tile"><div class="detail-label">Tickets offen</div><div class="detail-value" id="openCount">-</div></div> <div class="detail-tile overview-stat"><div class="detail-label">Tickets offen</div><div class="overview-stat-value" id="openCount">-</div></div>
<div class="detail-tile"><div class="detail-label">Tickets IP / Closed</div><div class="detail-value"><span id="ipCount">-</span> / <span id="closedCount">-</span></div></div> <div class="detail-tile overview-stat"><div class="detail-label">Tickets IP / Closed</div><div class="overview-stat-value"><span id="ipCount">-</span> / <span id="closedCount">-</span></div></div>
</div> </div>
<button type="button" class="secondary-btn panel-action" data-nav-target="serverstats">Server Statistiken ansehen</button>
</section> </section>
<section class="card"> <section class="card overview-panel">
<p class="section-title">Activity</p> <p class="section-title">Activity</p>
<div class="detail-grid" style="margin-top:8px;"> <div class="activity-list">
<div class="detail-tile"><div class="detail-label">Messages (24h)</div><div class="detail-value" id="actMessages">-</div></div> <div class="activity-card">
<div class="detail-tile"><div class="detail-label">Commands (24h)</div><div class="detail-value" id="actCommands">-</div></div> <div class="activity-card-main">
<div class="detail-tile"><div class="detail-label">Automod (24h)</div><div class="detail-value" id="actAutomod">-</div></div> <div class="activity-icon">💬</div>
<div>
<div class="detail-label">Messages (24h)</div>
<div class="activity-value" id="actMessages">-</div>
</div>
</div>
<div class="activity-spark messages"></div>
</div>
<div class="activity-card">
<div class="activity-card-main">
<div class="activity-icon commands">⌘</div>
<div>
<div class="detail-label">Commands (24h)</div>
<div class="activity-value" id="actCommands">-</div>
</div>
</div>
<div class="activity-spark commands"></div>
</div>
<div class="activity-card">
<div class="activity-card-main">
<div class="activity-icon automod">🛡</div>
<div>
<div class="detail-label">Automod (24h)</div>
<div class="activity-value" id="actAutomod">-</div>
</div>
</div>
<div class="activity-spark automod"></div>
</div>
</div> </div>
<button type="button" class="secondary-btn panel-action" data-nav-target="settings">Alle Logs anzeigen</button>
</section> </section>
<section class="card"> <section class="card overview-panel logs-panel">
<p class="section-title">Guild Logs</p> <p class="section-title">Guild Logs</p>
<ul class="log-list" id="guildLogs"></ul> <ul class="log-list" id="guildLogs"></ul>
</section> </section>
</div> </div>
<section class="card quick-actions">
<p class="section-title">Schnellzugriff</p>
<p class="section-sub">Wichtige Funktionen auf einen Blick</p>
<div class="quick-actions-grid">
<button type="button" class="quick-action secondary-btn" data-nav-target="tickets"><div class="quick-action-head"><span class="quick-action-icon">🎫</span><span>Ticketsystem</span></div><p>Verwalte Tickets und Support-Flows</p></button>
<button type="button" class="quick-action secondary-btn" data-nav-target="automod"><div class="quick-action-head"><span class="quick-action-icon">🛡</span><span>Automod</span></div><p>Regeln, Filter und Sicherheit anpassen</p></button>
<button type="button" class="quick-action secondary-btn" data-nav-target="welcome"><div class="quick-action-head"><span class="quick-action-icon">👋</span><span>Willkommen</span></div><p>Join-Nachrichten und Embeds konfigurieren</p></button>
<button type="button" class="quick-action secondary-btn" data-nav-target="dynamicvoice"><div class="quick-action-head"><span class="quick-action-icon">🎙</span><span>Dynamic Voice</span></div><p>Voice-Lobbys und Channel-Logik steuern</p></button>
<button type="button" class="quick-action secondary-btn" data-nav-target="reactionroles"><div class="quick-action-head"><span class="quick-action-icon">🎭</span><span>Reaction Roles</span></div><p>Rollen per Nachricht und Emoji verwalten</p></button>
<button type="button" class="quick-action secondary-btn" data-nav-target="statuspage"><div class="quick-action-head"><span class="quick-action-icon">📡</span><span>Statuspage</span></div><p>Services, Checks und Uptime im Blick</p></button>
</div>
</section>
</div> </div>
<div class="section" data-section="tickets"> <div class="section" data-section="tickets">
<div class="card" style="display:flex; gap:10px; flex-wrap:wrap; align-items:center; justify-content:space-between;"> <div class="card" style="display:flex; gap:10px; flex-wrap:wrap; align-items:center; justify-content:space-between;">
@@ -1317,6 +1404,19 @@ router.get('/', (req, res) => {
let editingReactionRole = null; let editingReactionRole = null;
let supportLoginCache = {}; let supportLoginCache = {};
let eventsCache = []; let eventsCache = [];
const MODULE_LABELS = {
ticketsEnabled: 'TICKETS',
automodEnabled: 'AUTOMOD',
musicEnabled: 'MUSIC',
welcomeEnabled: 'WELCOME',
dynamicVoiceEnabled: 'DYNAMICVOICE',
statuspageEnabled: 'STATUSPAGE',
birthdayEnabled: 'BIRTHDAY',
reactionRolesEnabled: 'REACTIONROLES',
serverStatsEnabled: 'SERVERSTATS',
eventsEnabled: 'EVENTS',
adminEnabled: 'ADMIN'
};
function activateSection(key) { function activateSection(key) {
sections.forEach((s) => s.classList.toggle('active', s.dataset.section === key)); sections.forEach((s) => s.classList.toggle('active', s.dataset.section === key));
@@ -1429,7 +1529,7 @@ router.get('/', (req, res) => {
Object.entries(mods).forEach(([key, on]) => { Object.entries(mods).forEach(([key, on]) => {
const badge = document.createElement('span'); const badge = document.createElement('span');
badge.className = 'badge' + (on ? ' active' : ''); badge.className = 'badge' + (on ? ' active' : '');
badge.textContent = key.replace('Enabled', ''); badge.textContent = MODULE_LABELS[key] || key.replace('Enabled', '').toUpperCase();
guildModules.appendChild(badge); guildModules.appendChild(badge);
}); });
} }
@@ -2872,6 +2972,14 @@ router.get('/', (req, res) => {
}); });
}); });
document.querySelectorAll('[data-nav-target]').forEach((button) => {
button.addEventListener('click', () => {
const target = button.getAttribute('data-nav-target') || 'overview';
activateSection(target);
history.replaceState(null, '', '#' + target);
});
});
document.querySelectorAll('.ticket-tab-btn').forEach((btn) => { document.querySelectorAll('.ticket-tab-btn').forEach((btn) => {
btn.addEventListener('click', async () => { btn.addEventListener('click', async () => {
document.querySelectorAll('.ticket-tab-btn').forEach((b) => b.classList.remove('active')); document.querySelectorAll('.ticket-tab-btn').forEach((b) => b.classList.remove('active'));