import { useCallback, useEffect, useState } from 'react' import { Check, Copy, Folder, FolderInput, HardDrive, Images, KeyRound, Loader2, RefreshCw, ShieldCheck, Trash2, TrendingUp, Upload, } from 'lucide-react' import { api, vorschauUrl, type EventKind, type Uebersicht } from '../api' import { useStore } from '../store' import { bytes, zeit } from '../format' import { Karte, Leer, useKopieren } from '../components/Bausteine' import { Avatar } from '../components/Avatar' import { useAuffrischen } from '../auffrischen' import { gehZu } from '../router' const arten: Record = { upload: { text: 'hochgeladen', farbe: 'text-gut', kind: Upload }, replace: { text: 'ersetzt', farbe: 'text-warn', kind: RefreshCw }, delete: { text: 'gelöscht', farbe: 'text-schlecht', kind: Trash2 }, move: { text: 'verschoben', farbe: 'text-akzent', kind: FolderInput }, } /** Die Startseite: was ist da, was ist zuletzt passiert, wohin muss ich. * * Bisher landete man in der Galerie — mit 228 Kacheln und ohne Antwort auf * die erste Frage, die man beim Öffnen hat: läuft alles? Diese Seite * beantwortet sie in einem Blick und verlinkt den Rest. */ export function Start() { const note = useStore((s) => s.note) const user = useStore((s) => s.user) const [daten, setDaten] = useState(null) const [laedt, setLaedt] = useState(true) const { kopiert, kopieren } = useKopieren() const laden = useCallback(async () => { try { setDaten(await api.uebersicht()) } catch (err) { note('fehler', err instanceof Error ? err.message : 'Unbekannt') } finally { setLaedt(false) } }, [note]) useEffect(() => { void laden() }, [laden]) // Hier zieht nichts weg: die Seite hat keine Auswahl und kein offenes // Fenster, sie darf sich jederzeit erneuern. useAuffrischen({ laden: () => void laden(), blockiert: false }) if (laedt) { return (
) } if (!daten) return // Die eingetragenen Vorlagen — und solange keine da ist, die eine, die // dieses Projekt ohnehin benutzt. Eine leere Karte waere hier nur ein // Loch. const vorlagen = daten.vorlagen.length > 0 ? daten.vorlagen : [{ name: 'Fahrzeuge', muster: 'vehicles/{model}.webp' }] return (

Hallo {user?.discordName ?? user?.username ?? ''}

{daten.files} Dateien · {bytes(daten.bytes)} belegt

} was="Dateien" wert={String(daten.files)} onClick={() => gehZu('/galerie')} /> } was="Belegt" wert={bytes(daten.bytes)} /> } was="Neu heute" wert={String(daten.heuteHoch)} unten={`${daten.wocheHoch} in sieben Tagen`} onClick={() => gehZu('/verlauf')} /> } was="Token" wert={String(daten.tokens.length)} onClick={() => gehZu('/tokens')} />
{/* Die Vorlage, die im Handy steht — die haeufigste Frage ueberhaupt */} gehZu('/einstellungen')} className="text-xs text-schrift-leise hover:text-schrift" > verwalten } >
{vorlagen.map((v, i) => { const voll = `${daten.publicUrl}${daten.filePrefix}/${v.muster}` return (
{v.name} {voll}
) })}
{daten.bilder.length === 0 ? ( ) : (
{daten.bilder.map((b) => ( ))}
)}
{daten.letzte.length === 0 ? ( ) : (
    {daten.letzte.map((e) => { const a = arten[e.kind] const Kind = a.kind return (
  • {e.path} {zeit(e.at)}
  • ) })}
)}
}> {daten.ordner.length === 0 ? ( ) : (
    {daten.ordner.map((o) => (
  • {o.folder} {o.files} Dateien {bytes(o.bytes)}
  • ))}
)}
    {daten.tokens.map((t) => (
  • {t.name} {t.last_used_at ? `zuletzt ${zeit(t.last_used_at)}` : 'nie benutzt'}
  • ))}
  • Discord-Anmeldung {daten.discord ? 'eingerichtet' : 'nicht eingerichtet'}
) } function Kachel({ kind, was, wert, unten, onClick, }: { kind: React.ReactNode was: string wert: string unten?: string onClick?: () => void }) { const inhalt = ( <>
{kind} {was}

{wert}

{unten &&

{unten}

} ) // Nur was wirklich irgendwohin fuehrt, wird ein Knopf. Eine Kachel, die // aussieht wie ein Knopf und nichts tut, ist der Anfang des Misstrauens. return onClick ? ( ) : (
{inhalt}
) }