import type { Metadata } from 'next';
import Link from 'next/link';
import { ReviewDecisionButtons } from '@/components/admin/actions';
import type { ReviewItem } from '@/components/admin/types';
import { AdminError, AdminHeader, JsonInline } from '@/components/admin/ui';
import { StatusBadge } from '@/components/ui/badges';
import { Pagination } from '@/components/ui/pagination';
import { adminApi, safeAdmin } from '@/lib/admin-api';
import { fmtAgo, fmtDateTime, fmtInt } from '@/lib/format';
export const metadata: Metadata = { title: 'Entity resolution' };
const STATUSES = ['open', 'merged', 'kept_separate', 'dismissed'] as const;
function Entity({ label, slug, name, norad, cospar, status }: { label: string; slug: string | null; name: string | null; norad: number | null; cospar: string | null; status: string | null }) {
return (
{label}
{slug ? (
{name ?? slug}
) : (
— (entity no longer exists)
)}
- NORAD
- {norad ?? '—'}
- COSPAR
- {cospar ?? '—'}
);
}
function ReviewCard({ item, now }: { item: ReviewItem; now: number }) {
return (
#{item.id}
{item.kind.replace(/_/g, ' ')}
confidence {item.confidence === null ? '—' : item.confidence.toFixed(2)}
raised {fmtAgo(item.created_at, now)}
{item.resolved_at && (
resolved {fmtAgo(item.resolved_at, now)} by {item.resolved_by ?? '?'}
)}
{item.detail && (
)}
{item.status === 'open' && }
);
}
export default async function AdminEntityResolutionPage({ searchParams }: { searchParams: Promise<{ page?: string; status?: string }> }) {
const sp = await searchParams;
const page = Math.max(1, Number(sp.page) || 1);
const status = (STATUSES as readonly string[]).includes(sp.status ?? '') ? (sp.status as (typeof STATUSES)[number]) : 'open';
const res = await safeAdmin(adminApi.review(page, status, 25));
const now = Date.now();
const href = (p: number, s: string = status) => `/admin/entity-resolution?${new URLSearchParams({ ...(s !== 'open' ? { status: s } : {}), ...(p > 1 ? { page: String(p) } : {}) }).toString()}`;
return (
<>
{STATUSES.map((s) => (
{s.replace('_', ' ')}
))}
{res.error !== null ? (
) : (
<>
{fmtInt(res.data.pagination.total)} {status.replace('_', ' ')} item{res.data.pagination.total === 1 ? '' : 's'}
{res.data.data.length === 0 ? (
Queue is empty
) : (
{res.data.data.map((item) => (
))}
)}
href(p)} />
>
)}
>
);
}