60 lines
2.5 KiB
TypeScript
60 lines
2.5 KiB
TypeScript
import { Link } from 'react-router-dom';
|
|
import { useMemo } from 'react';
|
|
import { ShieldAlert, ArrowRight, Activity } from 'lucide-react';
|
|
import { useCurrentUser } from '@/hooks/useCurrentUser';
|
|
import { useSkateSpots } from '@/hooks/useSkateSpots';
|
|
import { isAdminPubkey } from '@/lib/admins';
|
|
import { isFlagged } from '@/lib/spotQuality';
|
|
import { useTranslation } from '@/contexts/language';
|
|
|
|
/**
|
|
* Admin-only entry point for the review queue. Renders nothing for everyone
|
|
* else, so it can sit in Settings → Advanced beside the other owner cards.
|
|
*/
|
|
export function AdminReviewCard() {
|
|
const { user } = useCurrentUser();
|
|
const isAdmin = isAdminPubkey(user?.pubkey);
|
|
const { data: spots } = useSkateSpots(300);
|
|
const { t } = useTranslation();
|
|
|
|
// Cheap signals only here (no per-spot trust/status queries just to draw a
|
|
// badge) — the review page does the deeper pass.
|
|
const flaggedCount = useMemo(() => (spots ?? []).filter(isFlagged).length, [spots]);
|
|
|
|
if (!isAdmin) return null;
|
|
|
|
return (
|
|
<div className="space-y-2">
|
|
<Link
|
|
to="/review"
|
|
className="block rounded-2xl border border-amber-500/20 bg-white/[0.02] transition-colors hover:border-amber-500/40"
|
|
>
|
|
<div className="flex items-center gap-3 px-4 py-3.5">
|
|
<ShieldAlert className="h-5 w-5 shrink-0 text-amber-400" />
|
|
<div className="min-w-0 flex-1">
|
|
<p className="text-sm font-bold text-amber-400">{t('settingsUi.adminReview.title')}</p>
|
|
<p className="mt-0.5 text-xs text-muted-foreground">
|
|
{flaggedCount > 0
|
|
? t('settingsUi.adminReview.flagged', { count: flaggedCount, s: flaggedCount === 1 ? '' : 's' })
|
|
: t('settingsUi.adminReview.clean')}
|
|
</p>
|
|
</div>
|
|
<ArrowRight className="h-4 w-4 shrink-0 text-gray-500" />
|
|
</div>
|
|
</Link>
|
|
<Link
|
|
to="/ops"
|
|
className="block rounded-2xl border border-cyan-500/20 bg-white/[0.02] transition-colors hover:border-cyan-500/40"
|
|
>
|
|
<div className="flex items-center gap-3 px-4 py-3.5">
|
|
<Activity className="h-5 w-5 shrink-0 text-cyan-400" />
|
|
<div className="min-w-0 flex-1">
|
|
<p className="text-sm font-bold text-cyan-400">Operator status</p>
|
|
<p className="mt-0.5 text-xs text-muted-foreground">Read-only relay, Cordn, storage and TLS health.</p>
|
|
</div>
|
|
<ArrowRight className="h-4 w-4 shrink-0 text-gray-500" />
|
|
</div>
|
|
</Link>
|
|
</div>
|
|
);
|
|
}
|