Public Access
feat(admin): accept, deny and pending count
This commit is contained in:
1 parent
b8f70e7578
commit
f4e69e1a94
10 files changed
+230
-38
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import {useEffect, useState} from 'react';
|
||||
import {Link, NavLink, useLocation, useNavigate} from 'react-router-dom';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {ChartColumn, Dices, Eye, Languages, LayoutDashboard, Library, LogOut, Megaphone, Moon, Settings, Shield, Sun} from 'lucide-react';
|
||||
@@ -22,7 +23,7 @@ import PageContainer from './PageContainer.jsx';
|
||||
import SteamAvatar from './SteamAvatar.jsx';
|
||||
import useCurrentUser from '../hooks/useCurrentUser.js';
|
||||
import useSteamProfile from '../hooks/useSteamProfile.js';
|
||||
import {ROLES, viewAs} from '../utils/admin.js';
|
||||
import {fetchPendingCount, ROLES, viewAs} from '../utils/admin.js';
|
||||
import {expireSession, markSession} from '../utils/auth.js';
|
||||
|
||||
const NAV_ITEMS = [
|
||||
@@ -49,6 +50,24 @@ export default function AppHeader({isAuthenticated, onLogout}) {
|
||||
const navigate = useNavigate();
|
||||
const isAdmin = currentUser?.role === 'PLATFORM_ADMIN';
|
||||
const viewingAs = currentUser && currentUser.activeRole !== currentUser.role ? currentUser.activeRole : null;
|
||||
const seesAdminPage = isAdmin && !viewingAs;
|
||||
const [pendingCount, setPendingCount] = useState(0);
|
||||
const [menuOpenings, setMenuOpenings] = useState(0);
|
||||
|
||||
// Loaded again on every page change and menu opening, so a decision on the admin page shows soon.
|
||||
useEffect(() => {
|
||||
if (!seesAdminPage) return undefined;
|
||||
let current = true;
|
||||
fetchPendingCount()
|
||||
.then(async (response) => {
|
||||
if (current && response.ok) setPendingCount((await response.json()).count);
|
||||
})
|
||||
.catch((err) => console.error('Pending count error:', err));
|
||||
return () => {
|
||||
current = false;
|
||||
};
|
||||
}, [seesAdminPage, pathname, menuOpenings]);
|
||||
const shownCount = seesAdminPage ? pendingCount : 0;
|
||||
|
||||
const switchRole = async (role) => {
|
||||
try {
|
||||
@@ -108,20 +127,30 @@ export default function AppHeader({isAuthenticated, onLogout}) {
|
||||
<Badge variant="secondary" className="mr-1">{t('NAV.VIEW_AS.BADGE', {role: t(`ROLES.${viewingAs}`)})}</Badge>
|
||||
)}
|
||||
{isAuthenticated ? (
|
||||
<DropdownMenu>
|
||||
<DropdownMenu onOpenChange={(open) => open && setMenuOpenings((count) => count + 1)}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon" aria-label={t('NAV.MENU')} title={steamProfile?.personaName ?? undefined}>
|
||||
<Button variant="ghost" size="icon" aria-label={t('NAV.MENU')} title={steamProfile?.personaName ?? undefined}
|
||||
className="relative">
|
||||
<SteamAvatar url={steamProfile?.avatarUrl}/>
|
||||
{shownCount > 0 && (
|
||||
<span aria-label={t('NAV.PENDING_REQUESTS', {count: shownCount})}
|
||||
className="absolute -top-1 -right-1 flex size-4 items-center justify-center rounded-full bg-primary text-[10px] font-bold text-primary-foreground">
|
||||
{shownCount > 9 ? '9+' : shownCount}
|
||||
</span>
|
||||
)}
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-52">
|
||||
<DropdownMenuItem asChild>
|
||||
<Link to="/settings"><Settings/>{t('NAV.SETTINGS')}</Link>
|
||||
</DropdownMenuItem>
|
||||
{isAdmin && !viewingAs && (
|
||||
{seesAdminPage && (
|
||||
<>
|
||||
<DropdownMenuItem asChild>
|
||||
<Link to="/admin/users"><Shield/>{t('NAV.ADMIN')}</Link>
|
||||
<Link to="/admin/users">
|
||||
<Shield/>{t('NAV.ADMIN')}
|
||||
{shownCount > 0 && <Badge className="ml-auto">{shownCount}</Badge>}
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem asChild>
|
||||
<Link to="/admin/hints"><Megaphone/>{t('NAV.ADMIN_HINTS')}</Link>
|
||||
|
||||
Reference in new issue
Block a user