import type { Metadata } from 'next'; import Link from 'next/link'; import { ActionButton, AdminFilters, AdminTitle, Mono, Notice } from '@/components/admin/ui'; import { EntityBadge } from '@/components/ui/badges'; import { DataTable, EmptyRow, Td, Th } from '@/components/ui/data-table'; import { Unavailable } from '@/components/ui/unavailable'; import { mergeAction } from '@/lib/admin/actions'; import { adminApi, load, requireAdmin } from '@/lib/admin/admin-api'; import type { DuplicateSide } from '@/lib/admin/types'; import { fmtDate, fmtInt, fmtPct, num } from '@/lib/format'; import { routes } from '@/lib/site'; export const metadata: Metadata = { title: 'Duplicates', robots: { index: false, follow: false } }; export const dynamic = 'force-dynamic'; const TYPES = ['model', 'company', 'organization', 'lab', 'paper', 'provider', 'benchmark', 'hardware', 'framework', 'library', 'dataset', 'tool', 'repository', 'researcher']; function Side({ s, type }: { s: DuplicateSide; type: string }) { return (
{s.name}

{s.slug} {s.organization && · {s.organization}}

{fmtInt(s.claims)} claims · first seen {fmtDate(s.first_seen_at)}

); } export default async function AdminDuplicatesPage({ searchParams }: { searchParams: Promise> }) { await requireAdmin(); const sp = await searchParams; const type = sp.type ?? 'model'; const ret = `/admin/entities/duplicates?type=${encodeURIComponent(type)}`; const res = await load(adminApi.duplicates({ type, limit: 200 })); return ( <> ({ value: t, label: t })) }]} /> {!res.ok ? ( ) : ( A B Similarity Merge {res.data.items.length === 0 && No candidate pairs for this type.} {res.data.items.map((d) => { const aClaims = num(d.a.claims) ?? 0; const bClaims = num(d.b.claims) ?? 0; // Default suggestion: the record with fewer claims (or the newer one) is the source, the richer one the target. const preferAB = aClaims < bClaims || (aClaims === bClaims && (d.a.first_seen_at ?? '') > (d.b.first_seen_at ?? '')); return (
{fmtPct((num(d.similarity) ?? 0) * 100, 0)}
Merge A → B{preferAB ? ' · suggested' : ''}
Merge B → A{preferAB ? '' : ' · suggested'}
); })}
)} ); }