Auf 360px (Galaxy Z Flip 7 aufgeklappt) brauchten zwei Spalten 2x160 + 12 = 332px, verfuegbar waren nach 20px Innenrand aber nur 320px - also fiel das Raster auf eine Spalte zurueck. Schmal jetzt 132px Mindestbreite, 10px Abstand, 12px Innenrand. Damit stehen zwei Spalten ab 300px Fensterbreite, ohne dass breite Schirme sich aendern (dort weiter 160px und 20px). Raster und Innenrand stehen als Klassen in index.css: inline gesetzt haette die Media-Query sie nicht erreicht - derselbe Fehler wie zuletzt in der Kopfleiste. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
55 lines
2.0 KiB
TypeScript
55 lines
2.0 KiB
TypeScript
import { useState, useEffect } from 'react'
|
||
import { adminApi, type AdminUser } from '../api/client'
|
||
import PageHeader from '../components/PageHeader'
|
||
import Tabs from '../components/Tabs'
|
||
type Tab = 'users' | 'groups' | 'theming' | 'audit'
|
||
|
||
import UsersTab from './admin/UsersTab'
|
||
import GroupsTab from './admin/GroupsTab'
|
||
import ThemingTab from './admin/ThemingTab'
|
||
import AuditTab from './admin/AuditTab'
|
||
|
||
export default function AdminPage() {
|
||
const [tab, setTab] = useState<Tab>('users')
|
||
const [allUsers, setAllUsers] = useState<AdminUser[]>([])
|
||
|
||
useEffect(() => {
|
||
adminApi.listUsers().then(data => setAllUsers(data ?? [])).catch(() => {})
|
||
}, [])
|
||
|
||
const tabs: { id: Tab; label: string }[] = [
|
||
{ id: 'users', label: 'Users' },
|
||
{ id: 'groups', label: 'Groups' },
|
||
{ id: 'theming', label: 'Theming' },
|
||
// „Activity" statt „Audit log": Der Reiter zeigt nicht mehr nur das
|
||
// Protokoll, sondern davor auch den Stand der Texterkennung und die
|
||
// Speicherbereinigung – alles, was im Hintergrund läuft. Die Kennung
|
||
// bleibt 'audit', sie steht in keiner Adresse und muss nicht wandern.
|
||
{ id: 'audit', label: 'Activity' },
|
||
]
|
||
|
||
return (
|
||
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
|
||
<PageHeader
|
||
icon={
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||
<path d="M12 2l8 4v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6z" />
|
||
<path d="M9.5 12.5l1.8 1.8 3.4-3.6" />
|
||
</svg>
|
||
}
|
||
title="Admin panel"
|
||
meta="Users, groups, appearance and activity"
|
||
/>
|
||
|
||
<div className="aether-content" style={{ flex: 1, overflowY: 'auto' }}>
|
||
<Tabs tabs={tabs} active={tab} onChange={setTab} />
|
||
|
||
{tab === 'users' && <UsersTab />}
|
||
{tab === 'groups' && <GroupsTab allUsers={allUsers} />}
|
||
{tab === 'theming' && <ThemingTab />}
|
||
{tab === 'audit' && <AuditTab />}
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|