import type { Metadata } from 'next'; import Link from 'next/link'; import { ActionButton, AdminFilters, AdminTitle, JsonPre, KindChip, Mono, Notice, StatusChip, Trunc } from '@/components/admin/ui'; import { EntityBadge, TierBadge } from '@/components/ui/badges'; import { LiveAgo } from '@/components/ui/live'; import { Pagination, withParams } from '@/components/ui/pagination'; import { EmptyState, Unavailable } from '@/components/ui/unavailable'; import { keepConflictSideAction, reviewAction } from '@/lib/admin/actions'; import { adminApi, load, requireAdmin } from '@/lib/admin/admin-api'; import type { ReviewItem } from '@/lib/admin/types'; import { fmtDateTime, fmtInt, fmtValue, num } from '@/lib/format'; import { propertyLabel, routes } from '@/lib/site'; export const metadata: Metadata = { title: 'Review queue', robots: { index: false, follow: false } }; export const dynamic = 'force-dynamic'; const LIMIT = 25; const STATUSES = ['pending', 'approved', 'rejected', 'edited', 'all']; const KINDS = ['conflict', 'merge_candidate', 'parser_breakage', 'blocked_source']; function host(url: unknown): string { if (typeof url !== 'string') return '—'; try { return new URL(url).hostname.replace(/^www\./, ''); } catch { return url; } } /** Conflict payload `{ property, current, claimed, current_source, claimed_source, tier }` rendered as two columns, each with a "Keep" button. */ function ConflictView({ item, ret }: { item: ReviewItem; ret: string }) { const p = item.payload ?? {}; const property = typeof p.property === 'string' ? p.property : null; const entity = item.entities?.[0]; const sides = [ { key: 'current', title: 'Current value', value: p.current, source: p.current_source, tier: p.current_tier ?? null }, { key: 'claimed', title: 'Claimed by new source', value: p.claimed, source: p.claimed_source, tier: p.tier ?? p.claimed_tier ?? null }, ]; return (
{s.title}
{fmtValue(s.value, property ?? undefined)}
{typeof s.source === 'string' ? (
{host(s.source)}
) : (
source unknown
)}
{num(s.tier) !== null &&
Approve merges