"use client"; import { windowIntervalsLabel } from "@/lib/rectification-agentic/core/candidate-window"; import type { RectificationCandidateResult } from "@/lib/rectification-candidate-result"; import { RECTIFICATION_USER_COPY, REPRESENTATIVE_MINUTE_DISCLAIMER, rangeDeliveryEventCopy, rangeDeliveryMostLikely, rangeDeliveryShowsPercents, } from "@/lib/rectification-agentic/user-copy"; import type { RangeDeliveryProjection } from "@/lib/rectification-agentic/v9/divergence-panel"; import { SWITCH_TO_RECTIFIED_LABEL, switchToRectifiedConfirmCopy, } from "@/lib/rectification-agentic/birth-time-provenance"; import { RectificationVerificationReport } from "@/components/rectification-verification-report"; function columnHasTraits(column: RangeDeliveryProjection["columns"][number]): boolean { return Boolean(column.traits.d9 || column.traits.d10 || column.traits.nakshatra.length > 0); } export function RectificationRangeDelivery({ result, acceptingCandidateId, readonly, onAccept, adoptLocked, }: Readonly<{ result: RectificationCandidateResult; acceptingCandidateId: string | null; readonly: boolean; onAccept: (candidateId: string) => void; adoptLocked?: boolean; }>) { const delivery: RangeDeliveryProjection | null = result.rangeDelivery; const range = delivery?.range ?? result.credibleRange; const eventCount = delivery?.event_count ?? 0; const selected = result.selectedTime; const busy = Boolean(acceptingCandidateId) || readonly || adoptLocked; const columns = delivery?.columns ?? []; const rangeLabel = result.credibleIntervals?.length ? windowIntervalsLabel(result.credibleIntervals, result.declaredBirthDate) : range ? `${range[0]}–${range[1]}` : null; const title = rangeLabel ? eventCount > 0 ? `${RECTIFICATION_USER_COPY.rangeDeliveryTitle} ${rangeLabel}(${rangeDeliveryEventCopy(eventCount)})` : `${RECTIFICATION_USER_COPY.rangeDeliveryTitle} ${rangeLabel}` : RECTIFICATION_USER_COPY.rangeDeliveryTitle; const markdown = delivery?.verification_markdown ?? result.verificationReportMarkdown; const sharedTraits = delivery?.shared_traits ?? []; // BUG-691: while the birth record disagrees with the range the adopt entry says what // it actually does — swap the charting clock — instead of the neutral 「更像这个」. const recordConflict = delivery?.record_conflict ?? null; const caption = delivery?.narrow_hint ?? null; // D3: the range is the title; the representative minute is the subtitle. // Hidden when the columns are indistinct (D4): 「最可能」 next to 「区分不开」 // would claim a lead the numbers do not have. const mostLikely = delivery?.representative_time ?? result.representativeTime; // D4: per-column numbers only when the first column leads by ≥ 5 points. const showPercents = rangeDeliveryShowsPercents(columns); const indistinct = columns.length >= 2 && !showPercents; return (
{title} {mostLikely && !indistinct ? ( {rangeDeliveryMostLikely(mostLikely)} ) : null}
{caption ? (

{caption}

) : null} {delivery?.provenance_line ? (

{delivery.provenance_line}

) : null} {adoptLocked ? (

{RECTIFICATION_USER_COPY.rangeDeliveryAdoptLocked}

) : null} {delivery?.tie_break_note ? (

{delivery.tie_break_note}

) : null} {indistinct ? (

{RECTIFICATION_USER_COPY.rangeDeliveryIndistinct}

) : null} {sharedTraits.length > 0 ? ( ) : null} {delivery?.more_label ? (

{delivery.more_label}

) : null}

{delivery?.boundary ?? REPRESENTATIVE_MINUTE_DISCLAIMER}

); }