Refactor admin UI for consolidated navigation and improved moderation workflow

- Updated Sidebar component to consolidate navigation items under new categories: Moderation, Content, and Operations.
- Removed outdated pages and integrated their functionalities into tabs under Players, Activity, Content, and Settings.
- Introduced new Activity and Content pages to house Audit, Player Logs, Community Board, and Loading Tips with tabbed navigation.
- Created a unified Moderation page combining Players, Bans, and Reports with tabbed navigation.
- Refactored individual pages (e.g., Audit, Bans, CommunityBoard, etc.) to support embedded mode for better integration within modals.
- Added Tabs component for consistent tab navigation across multiple pages.
- Updated README to reflect changes in navigation and settings structure.
- Removed Grants page as it is not yet implemented.
This commit is contained in:
Alexa
2026-06-02 10:49:35 +03:00
parent 24c8a920e4
commit 7535cd823f
21 changed files with 400 additions and 249 deletions
+23 -15
View File
@@ -6,26 +6,34 @@ import { Empty } from '../components/Empty';
import { absoluteTime, clip, relativeTime } from '../lib/format';
import { RefreshCw } from '../components/Icons';
export function Audit() {
export function Audit({ embedded }: { embedded?: boolean } = {}) {
const [take, setTake] = useState(200);
const { data, loading, error, refresh } = useApi<AuditEntry[]>(`/audit?take=${take}`);
const controls = (
<>
<select value={take} onChange={e => setTake(parseInt(e.target.value))} className="input w-24 text-xs !py-1.5">
<option value={100}>last 100</option>
<option value={200}>last 200</option>
<option value={500}>last 500</option>
</select>
<button onClick={refresh} className="btn-secondary text-xs" disabled={loading}>
<RefreshCw className={loading ? 'animate-spin' : ''} /> Refresh
</button>
</>
);
return (
<div>
<PageHeader
title="Audit log"
blurb="Every admin action with actor, target, and reason. Newest first."
actions={<>
<select value={take} onChange={e => setTake(parseInt(e.target.value))} className="input w-24 text-xs !py-1.5">
<option value={100}>last 100</option>
<option value={200}>last 200</option>
<option value={500}>last 500</option>
</select>
<button onClick={refresh} className="btn-secondary text-xs" disabled={loading}>
<RefreshCw className={loading ? 'animate-spin' : ''} /> Refresh
</button>
</>}
/>
{embedded ? (
<div className="flex justify-end gap-2 mb-3">{controls}</div>
) : (
<PageHeader
title="Audit log"
blurb="Every admin action with actor, target, and reason. Newest first."
actions={controls}
/>
)}
{error && <div className="card border-danger/30 bg-danger/5 px-4 py-3 text-sm text-danger">{error}</div>}