mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-25 23:18:44 -07:00
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:
@@ -10,8 +10,10 @@ import { useToast } from '../components/Toast';
|
||||
import { Empty } from '../components/Empty';
|
||||
import { PlayerAvatar } from '../components/PlayerAvatar';
|
||||
import { RefreshCw, Search } from '../components/Icons';
|
||||
import { GiftPanel } from './Gift';
|
||||
import { PasswordResetCard } from './Passwords';
|
||||
|
||||
export function Players() {
|
||||
export function Players({ embedded }: { embedded?: boolean } = {}) {
|
||||
const [params] = useSearchParams();
|
||||
const [query, setQuery] = useState(params.get('query') ?? '');
|
||||
const [rows, setRows] = useState<Player[] | null>(null);
|
||||
@@ -45,18 +47,24 @@ export function Players() {
|
||||
if (next !== query) setQuery(next);
|
||||
}, [params, query]);
|
||||
|
||||
const refreshBtn = (
|
||||
<button onClick={() => search(query)} className="btn-secondary text-xs" disabled={loading}>
|
||||
<RefreshCw className={loading ? 'animate-spin' : ''} />
|
||||
Refresh
|
||||
</button>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<PageHeader
|
||||
title="Players"
|
||||
blurb="Search and moderate every account in the database."
|
||||
actions={
|
||||
<button onClick={() => search(query)} className="btn-secondary text-xs" disabled={loading}>
|
||||
<RefreshCw className={loading ? 'animate-spin' : ''} />
|
||||
Refresh
|
||||
</button>
|
||||
}
|
||||
/>
|
||||
{embedded ? (
|
||||
<div className="flex justify-end mb-3">{refreshBtn}</div>
|
||||
) : (
|
||||
<PageHeader
|
||||
title="Players"
|
||||
blurb="Search and moderate every account in the database."
|
||||
actions={refreshBtn}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="card overflow-hidden">
|
||||
<div className="border-b border-ink-800 p-3 flex items-center gap-2">
|
||||
@@ -153,7 +161,7 @@ export function Players() {
|
||||
function PlayerDetail({ id, onClose, onChanged }: { id: number; onClose: () => void; onChanged: () => void }) {
|
||||
const [data, setData] = useState<PlayerDetail | null>(null);
|
||||
const [err, setErr] = useState<string | null>(null);
|
||||
const [tab, setTab] = useState<'overview' | 'mod' | 'grants' | 'profile'>('overview');
|
||||
const [tab, setTab] = useState<'overview' | 'mod' | 'grants' | 'gift' | 'profile'>('overview');
|
||||
|
||||
const reload = () => {
|
||||
setErr(null);
|
||||
@@ -196,7 +204,7 @@ function PlayerDetail({ id, onClose, onChanged }: { id: number; onClose: () => v
|
||||
</div>
|
||||
|
||||
<div className="flex border-b border-ink-800 text-sm">
|
||||
{(['overview', 'mod', 'grants', 'profile'] as const).map(t => (
|
||||
{(['overview', 'mod', 'grants', 'gift', 'profile'] as const).map(t => (
|
||||
<button
|
||||
key={t}
|
||||
onClick={() => setTab(t)}
|
||||
@@ -210,6 +218,7 @@ function PlayerDetail({ id, onClose, onChanged }: { id: number; onClose: () => v
|
||||
{tab === 'overview' && <OverviewTab data={data} />}
|
||||
{tab === 'mod' && <ModerationTab data={data} onChanged={onChanged} />}
|
||||
{tab === 'grants' && <GrantsTab data={data} onChanged={reload} />}
|
||||
{tab === 'gift' && <GiftPanel playerId={data.id} />}
|
||||
{tab === 'profile' && <ProfileTab data={data} onChanged={reload} />}
|
||||
</div>
|
||||
)}
|
||||
@@ -576,6 +585,8 @@ function ProfileTab({ data, onChanged }: { data: PlayerDetail; onChanged: () =>
|
||||
className="btn-danger text-xs"
|
||||
>Reset to starter</button>
|
||||
</div>
|
||||
|
||||
<PasswordResetCard playerId={data.id} username={data.username} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user