Files
d4rk_media/server/ui/src/pages/Konto.tsx
T
D4rkst3randClaude Opus 5 32d69c9945 fix: der Inhalt hat ueberall dieselbe Breite
Konto und Einstellungen standen auf max-w-2xl, alle anderen Seiten auf der
Containerbreite -- beim Wechseln sprang der Inhalt sichtbar. Ein Fehler beim
Bauen, kein Entwurf.

Die Breite steht jetzt an EINER Stelle (BREITE in App.tsx) und gilt fuer
Kopfzeile und Inhalt. Vorher stand sie zweimal da, und zwei Seiten setzten
zusaetzlich ihre eigene: drei Orte fuer eine Zahl, die immer gleich sein soll.

Formulare werden stattdessen INNERHALB ihrer Karte begrenzt. Das war der
eigentliche Grund fuer die Ausnahme -- ein Passwortfeld ueber 1280 Pixel sieht
albern aus. Nur gehoert diese Begrenzung ans Formular und nicht an die Seite.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 19:45:37 +02:00

110 lines
4.4 KiB
TypeScript

import { useState, type FormEvent } from 'react'
import { api } from '../api'
import { run, useStore } from '../store'
import { Feld, Karte, Knopf } from '../components/Bausteine'
import { Avatar } from '../components/Avatar'
export function Konto() {
const user = useStore((s) => s.user)
const note = useStore((s) => s.note)
const [aktuell, setAktuell] = useState('')
const [neu, setNeu] = useState('')
const [wieder, setWieder] = useState('')
const [wartet, setWartet] = useState(false)
const zuKurz = neu.length > 0 && neu.length < 8
const ungleich = wieder.length > 0 && neu !== wieder
async function wechseln(e: FormEvent) {
e.preventDefault()
// Die Wiederholung prüft nur diese Seite — der Dienst kennt sie nicht.
// Deshalb hier ein eigener Satz statt einer Anfrage, die nichts
// bewirken kann.
if (neu !== wieder) {
note('fehler', 'Die beiden neuen Passwörter stimmen nicht überein.')
return
}
setWartet(true)
const ok = await run(
() => api.changePassword(aktuell, neu),
'Passwort geändert. Alle anderen Anmeldungen wurden beendet.',
)
setWartet(false)
if (ok) {
setAktuell('')
setNeu('')
setWieder('')
}
}
// Der Discord-Name steht nur daneben, wenn er vom Anzeigenamen abweicht —
// sonst stuende dort zweimal dasselbe.
const herkunft =
user?.discordName && user.discordName !== user.username
? `über Discord angemeldet — dort „${user.discordName}"`
: 'über Discord angemeldet'
return (
<div className="flex flex-col gap-4">
<Karte titel="Konto">
<div className="mb-4 flex items-center gap-3 border-b border-rand pb-4">
<Avatar name={user?.username ?? '?'} url={user?.avatar} groesse={44} />
<div className="min-w-0">
<p className="truncate font-medium">{user?.username ?? '—'}</p>
<p className="text-xs text-schrift-leise">
{user?.discord ? herkunft : 'mit Passwort angemeldet'}
</p>
</div>
</div>
{user?.discord && (
<p className="mb-4 rounded-md border border-rand bg-grund px-3 py-2 text-xs text-schrift-leise">
Dieses Konto hat kein Passwort es kommt ausschließlich über Discord
herein. Das Formular unten wirkt nur für Konten mit Passwort.
</p>
)}
<form onSubmit={wechseln} className="flex max-w-md flex-col gap-3">
<Feld
label="Aktuelles Passwort"
type="password"
autoComplete="current-password"
value={aktuell}
onChange={(e) => setAktuell(e.target.value)}
/>
<Feld
label="Neues Passwort"
type="password"
autoComplete="new-password"
value={neu}
onChange={(e) => setNeu(e.target.value)}
hinweis={zuKurz ? 'Mindestens 8 Zeichen.' : undefined}
/>
<Feld
label="Neues Passwort wiederholen"
type="password"
autoComplete="new-password"
value={wieder}
onChange={(e) => setWieder(e.target.value)}
hinweis={ungleich ? 'Stimmt nicht mit dem neuen Passwort überein.' : undefined}
/>
<p className="text-xs text-schrift-leise">
Ein Wechsel beendet alle anderen Sitzungen. Diese hier bleibt bestehen.
</p>
<div>
<Knopf
art="haupt"
type="submit"
wartet={wartet}
disabled={!aktuell || neu.length < 8 || neu !== wieder}
kind="Passwort ändern"
/>
</div>
</form>
</Karte>
</div>
)
}