"use client"; import { useState, useEffect } from "react"; import Link from "next/link"; import { cn } from "@/lib/utils"; import type { ClaimSummary, SourceRecordDto } from "@/lib/api/types"; import { StemeDBClient } from "@/lib/api"; import { SourceTierBadge } from "./source-tier-badge"; import { WeightBar } from "./weight-bar"; import { HashDisplay } from "./hash-display"; import { TrustBar } from "./trust-bar"; import { statusColors, statusIcons, type SourceStatus } from "./constants"; interface ClaimRowProps { claim: ClaimSummary; isLeading: boolean; isExpanded: boolean; onToggle: () => void; } function formatValue(value: ClaimSummary["value"]): string { if (typeof value.value === "string") { return value.value; } return String(value.value); } export function ClaimRow({ claim, isLeading, isExpanded, onToggle }: ClaimRowProps) { const tier = claim.source.source_metadata?.tier ?? 5; const sourceLabel = claim.source.source_metadata?.label ?? "Unknown Source"; const tierLabel = claim.source.source_metadata?.tier_label ?? "Unknown"; const sourceUrl = claim.source.source_metadata?.url; const rawStatus = claim.source.source_metadata?.status ?? "active"; const status = (rawStatus === "active" || rawStatus === "deprecated" || rawStatus === "quarantined" ? rawStatus : "active") as SourceStatus; const valueStr = formatValue(claim.value); // Fetch full source record when expanded const [sourceRecord, setSourceRecord] = useState(null); const [sourceLoading, setSourceLoading] = useState(false); useEffect(() => { if (!isExpanded || sourceRecord || sourceLoading) return; setSourceLoading(true); const client = new StemeDBClient(); client .getSource(claim.source.source_hash) .then(setSourceRecord) .catch(() => { // Source may not be in registry — that's fine }) .finally(() => setSourceLoading(false)); }, [isExpanded, claim.source.source_hash, sourceRecord, sourceLoading]); return (
{/* Collapsed row header */} {/* Expanded details */} {isExpanded && (
{/* Full value */}
Value

{valueStr}

Type: {claim.value.type}
{/* Source info */}
Source
{sourceLabel}
{statusIcons[status]} {status} · {tierLabel} (T{tier})
{sourceUrl && ( {sourceUrl} )} {/* Source registry details (fetched) */} {sourceLoading && (
Loading source details...
)} {sourceRecord && (
{sourceRecord.notes && (

{sourceRecord.notes}

)}
Created: {new Date(sourceRecord.created_at).toLocaleDateString()} {sourceRecord.updated_at !== sourceRecord.created_at && ( Updated: {new Date(sourceRecord.updated_at).toLocaleDateString()} )}
View in Source Registry →
)}
{/* Supporting agents */} {claim.supporting_agents.length > 0 && (
Supporting Agents ({claim.supporting_agents.length})
{claim.supporting_agents.map((agent, j) => (
{agent.agent_id.slice(0, 8)}...
))}
)} {/* Provenance hashes */}
Provenance
{claim.source.visual_hash && ( )}
)}
); }