import React, { useEffect, useState } from 'react' import { Users, Library, Settings, Trash2, Plus, RefreshCw, Loader2, Check, X } from 'lucide-react' import { getUsers, createUser, deleteUser, getSettings, updateSettings } from '../api/me' import { getLibraries, scanLibrary, createLibrary, deleteLibrary } from '../api/libraries' type Tab = 'users' | 'libraries' | 'settings' export default function Admin() { const [tab, setTab] = useState('users') return (

Administration

{(['users', 'libraries', 'settings'] as Tab[]).map((t) => ( ))}
{tab === 'users' && } {tab === 'libraries' && } {tab === 'settings' && }
) } function UsersPanel() { const [users, setUsers] = useState([]) const [loading, setLoading] = useState(true) const [showCreate, setShowCreate] = useState(false) const [form, setForm] = useState({ username: '', password: '', isAdmin: false }) useEffect(() => { getUsers().then(setUsers).finally(() => setLoading(false)) }, []) const handleCreate = async () => { await createUser(form) const updated = await getUsers() setUsers(updated) setShowCreate(false) setForm({ username: '', password: '', isAdmin: false }) } const handleDelete = async (id: string) => { if (!confirm('Benutzer wirklich löschen?')) return await deleteUser(id) setUsers(users.filter((u) => u.id !== id)) } return (

{users.length} Benutzer

{showCreate && (

Neuer Benutzer

setForm({ ...form, username: e.target.value })} className="w-full bg-white/5 border border-white/10 rounded-lg px-3 py-2 text-sm text-white placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-primary" /> setForm({ ...form, password: e.target.value })} className="w-full bg-white/5 border border-white/10 rounded-lg px-3 py-2 text-sm text-white placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-primary" />
)} {loading ? : (
{users.map((u: any) => (

{u.username}

{u.email || 'Keine E-Mail'} · {u.isAdmin ? 'Admin' : 'Benutzer'}

))}
)}
) } function LibrariesPanel() { const [libraries, setLibraries] = useState([]) const [loading, setLoading] = useState(true) const [scanning, setScanning] = useState(null) const [showCreate, setShowCreate] = useState(false) const [form, setForm] = useState({ name: '', path: '', mediaType: 'book' }) useEffect(() => { getLibraries().then(setLibraries).finally(() => setLoading(false)) }, []) const handleScan = async (id: string) => { setScanning(id) await scanLibrary(id).catch(() => {}) setTimeout(() => setScanning(null), 5000) } const handleCreate = async () => { await createLibrary({ name: form.name, folders: [{ fullPath: form.path }], media_type: form.mediaType }) const libs = await getLibraries() setLibraries(libs) setShowCreate(false) setForm({ name: '', path: '', mediaType: 'book' }) } const handleDelete = async (id: string) => { if (!confirm('Bibliothek wirklich löschen?')) return await deleteLibrary(id) setLibraries(libs => libs.filter((l) => l.id !== id)) } return (

{libraries.length} Bibliotheken

{showCreate && (

Neue Bibliothek

setForm({ ...form, name: e.target.value })} className="w-full bg-white/5 border border-white/10 rounded-lg px-3 py-2 text-sm text-white placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-primary" /> setForm({ ...form, path: e.target.value })} className="w-full bg-white/5 border border-white/10 rounded-lg px-3 py-2 text-sm text-white placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-primary" />
)} {loading ? : (
{libraries.map((lib: any) => (

{lib.name}

{lib.folders?.[0]?.fullPath || ''} · {lib.mediaType}

))}
)}
) } function SettingsPanel() { const [settings, setSettings] = useState(null) const [loading, setLoading] = useState(true) const [saved, setSaved] = useState(false) useEffect(() => { getSettings().then(setSettings).finally(() => setLoading(false)) }, []) const save = async (key: string, value: any) => { await updateSettings({ [key]: value }) setSettings((s: any) => ({ ...s, [key]: value })) setSaved(true) setTimeout(() => setSaved(false), 2000) } if (loading) return const toggle = (key: string) => ( ) return (
{saved && (
Gespeichert
)} {[ { key: 'autoMatchBooks', label: 'Auto-Match Hörbücher' }, { key: 'autoMatchPodcasts', label: 'Auto-Match Podcasts' }, ].map(({ key, label }) => (

{label}

{toggle(key)}
))}

Feed-Update Intervall (Stunden)

save('podcastUpdateIntervalHours', parseInt(e.target.value))} className="w-16 bg-white/5 border border-white/10 rounded-lg px-2 py-1 text-sm text-white text-center focus:outline-none focus:ring-1 focus:ring-primary" />
) }