import { useEffect, useState } from 'react' import { Check, Copy, ExternalLink, Loader2, ShieldCheck, ShieldX } from 'lucide-react' import { api, type Einstellungen } from '../api' import { run, useStore } from '../store' import { Feld, Karte, Knopf, useKopieren } from '../components/Bausteine' /** Die Discord-Anmeldung einrichten — im Panel statt in der .env. * * Der eigentliche Gewinn steht ganz oben in der Karte: die Redirect-URI zum * Kopieren. Sie muss ZEICHEN FÜR ZEICHEN mit dem übereinstimmen, was im * Discord-Portal steht, und daran scheitert der erste Anlauf fast immer. */ export function DiscordKarte() { const note = useStore((s) => s.note) const [daten, setDaten] = useState(null) const [laedt, setLaedt] = useState(true) const [speichert, setSpeichert] = useState(false) const { kopiert, kopieren } = useKopieren() const [clientId, setClientId] = useState('') const [geheimnis, setGeheimnis] = useState('') const [guildId, setGuildId] = useState('') const [rollen, setRollen] = useState('') async function laden() { setLaedt(true) try { const e = await api.einstellungen() setDaten(e) setClientId(e.discord.clientId) setGuildId(e.discord.guildId) setRollen(e.discord.roleIds.join('\n')) } catch (err) { note('fehler', err instanceof Error ? err.message : 'Unbekannt') } finally { setLaedt(false) } } useEffect(() => { void laden() // eslint-disable-next-line react-hooks/exhaustive-deps }, []) async function speichern() { setSpeichert(true) const ergebnis = await run( () => api.einstellungenSpeichern({ clientId, // Leer heißt „nicht anfassen" — sonst würde jedes Speichern // das Geheimnis wegwerfen, weil es nie im Formular steht. ...(geheimnis ? { clientSecret: geheimnis } : {}), guildId, roleIds: rollen, }), (r) => r.bereit ? 'Gespeichert. Die Discord-Anmeldung ist eingerichtet.' : `Gespeichert. Es fehlt noch: ${r.fehlt.join(', ')}.`, ) setSpeichert(false) if (ergebnis) { setGeheimnis('') void laden() } } if (laedt) { return (
) } if (!daten) return null const d = daten.discord return ( eingerichtet ·{' '} {d.roleIds.length === 1 ? '1 Rolle' : `${d.roleIds.length} Rollen`} ) : ( nicht eingerichtet ) } >

Diese Adresse muss im Discord-Portal unter OAuth2 → Redirects stehen — Zeichen für Zeichen:

{d.redirectUri}
setClientId(e.target.value)} /> setGeheimnis(e.target.value)} /> setGuildId(e.target.value)} />