Webinterface: Emojis durch Lucide-Icons ersetzt
Deploy / check (push) Has been cancelled
Deploy / deploy (push) Has been cancelled

Emojis werden vom Betriebssystem gerendert — auf Windows, Mac und Android
sehen sie unterschiedlich aus, und sie sind bunt. Im streng zweifarbigen
D4RKST3R-Look stachen sie entsprechend heraus.

Jetzt kommen die Symbole aus einem einzigen Set (Lucide, dünne Outlines),
zentral in src/icons.jsx gebündelt: eine Größe, eine Strichstärke, überall
gleich — und sie erben die Textfarbe, sind also Teil der Marke statt
Fremdkörper. Betroffen sind Navigation, Startseite, Server, Roadmap,
Profil, Level, Galerie, Devlogs, Lightbox, Composer und alle Setup-Tabs.

Bewusst Emojis geblieben sind:
- die Spiel-Presets der Server (landen als Icon im Discord-Embed)
- Rollen-Menü-Emojis und Platzhalter für Discord-Inhalte
- beschreibende Hinweise wie „🔔-Button am Post" oder „🟢/🔴 im Embed",
  die zeigen, wie etwas in Discord aussehen wird
- die selbst gepflegten Dienst-Icons im Portal

Dazu Detailarbeit: Server-Status als farbiger Punkt statt Emoji, Platz 1–3
der Bestenliste als Pokal in Gold/Silber/Bronze, Pagination mit Chevrons.
Bundle wächst um 19 kB (Tree-Shaking greift, nur die ~70 genutzten Icons).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 14:37:25 +02:00
co-authored by Claude Fable 5
parent 6daa1f7d43
commit 1afbe9d238
20 changed files with 295 additions and 79 deletions
+24 -19
View File
@@ -1,6 +1,11 @@
import { useEffect, useRef, useState } from 'react';
import { apiGet, apiPut, apiPost, apiDelete } from '../api.js';
import EmbedComposer from '../components/EmbedComposer.jsx';
import {
IconStatus, IconBrand, IconFeeds, IconCommunity, IconRoles, IconSupport,
IconApplications, IconComposer, IconServer, IconSystem, IconApi, IconTeam,
IconLock, IconBot, IconUpload, IconChevronDown, IconKey,
} from '../icons.jsx';
const API_SCOPES = [
{ id: 'message', label: 'message', hint: 'Nachrichten/Embeds in Kanäle posten' },
@@ -10,18 +15,18 @@ const API_SCOPES = [
];
const TABS = [
{ id: 'status', icon: '📊', label: 'Status' },
{ id: 'brand', icon: '🎨', label: 'Brand' },
{ id: 'feeds', icon: '📔', label: 'Feeds' },
{ id: 'community', icon: '🙌', label: 'Community' },
{ id: 'rollen', icon: '🎭', label: 'Rollen' },
{ id: 'support', icon: '📬', label: 'Support' },
{ id: 'bewerbungen', icon: '📋', label: 'Bewerbungen' },
{ id: 'composer', icon: '📝', label: 'Composer' },
{ id: 'server', icon: '🎮', label: 'Server' },
{ id: 'system', icon: '⚙️', label: 'System' },
{ id: 'api', icon: '🔑', label: 'API' },
{ id: 'team', icon: '👥', label: 'Team' },
{ id: 'status', Icon: IconStatus, label: 'Status' },
{ id: 'brand', Icon: IconBrand, label: 'Brand' },
{ id: 'feeds', Icon: IconFeeds, label: 'Feeds' },
{ id: 'community', Icon: IconCommunity, label: 'Community' },
{ id: 'rollen', Icon: IconRoles, label: 'Rollen' },
{ id: 'support', Icon: IconSupport, label: 'Support' },
{ id: 'bewerbungen', Icon: IconApplications, label: 'Bewerbungen' },
{ id: 'composer', Icon: IconComposer, label: 'Composer' },
{ id: 'server', Icon: IconServer, label: 'Server' },
{ id: 'system', Icon: IconSystem, label: 'System' },
{ id: 'api', Icon: IconApi, label: 'API' },
{ id: 'team', Icon: IconTeam, label: 'Team' },
];
// Welcher Team-Scope schaltet welchen Tab frei (null = nur Owner)
@@ -574,7 +579,7 @@ export default function Settings({ me }) {
{header}
<section className="content">
<div className="notice center">
<p>🔒 Nur für den Admin.</p>
<p className="with-icon"><IconLock /> Nur für den Admin.</p>
{!me.user && <a className="btn" href="/auth/login">Login mit Discord</a>}
</div>
</section>
@@ -622,15 +627,15 @@ export default function Settings({ me }) {
<div className="bot-avatar-wrap">
{data.status.botAvatar
? <img className="bot-avatar" src={data.status.botAvatar} alt="Bot-Avatar" />
: <div className="bot-avatar bot-avatar-empty">🤖</div>}
: <div className="bot-avatar bot-avatar-empty"><IconBot size={30} /></div>}
<span className="bot-dot" style={{ background: statusDot }} />
</div>
<label className="btn btn-upload">
Bild ändern
<IconUpload size={14} /> Bild ändern
<input type="file" accept="image/*" hidden onChange={(e) => uploadImage('avatar', e.target.files?.[0])} />
</label>
<label className="btn btn-upload btn-ghost">
🖼 Banner
<IconUpload size={14} /> Banner
<input type="file" accept="image/*" hidden onChange={(e) => uploadImage('banner', e.target.files?.[0])} />
</label>
</div>
@@ -844,7 +849,7 @@ export default function Settings({ me }) {
onClick={distributeKeys}
disabled={!alphaKeys || alphaKeys.free === 0 || alphaKeys.playtestersWithout.length === 0}
>
🎟️ An {alphaKeys?.playtestersWithout?.length ?? 0} Playtester verteilen
<IconKey size={14} /> An {alphaKeys?.playtestersWithout?.length ?? 0} Playtester verteilen
</button>
</div>
{alphaKeys?.assigned?.length > 0 && (
@@ -937,7 +942,7 @@ export default function Settings({ me }) {
<div className="settings-section">
<h2 className="settings-title">// Rollen-Menüs</h2>
<p className="section-intro">
Selbstbedienungs-Rollen wie bei Carl-bot nur ohne Paywall. 😄 Der Bot postet
Selbstbedienungs-Rollen wie bei Carl-bot nur ohne Paywall. Der Bot postet
ein Embed mit Buttons; Klick = Rolle nehmen, nochmal = abgeben. Menüs sind
jederzeit editierbar, der Discord-Post zieht automatisch mit.
</p>
@@ -1712,7 +1717,7 @@ export default function Settings({ me }) {
className={`settings-nav-item ${tab === t.id ? 'active' : ''}`}
onClick={() => setTab(t.id)}
>
<span className="settings-nav-icon">{t.icon}</span>
<span className="settings-nav-icon"><t.Icon /></span>
{t.label}
</button>
))}