"use client"; /** * v1.27.22 (Document vault P2) — the presentational AI panels for the document * detail sheet. Pure (props in, markup out) so the review-first contract and * the session-only note are pinned by static-render tests. * * - `AiUnavailableHint` — the calm "set up an AI provider" pointer shown in * place of the AI actions when no provider is configured (never an error). * - `AssistSuggestionReview` — the reviewed DRAFT card: suggested title / type * / date, each applied only by an explicit tap. Nothing is written until the * user applies it (and the title lands in the editable field, not on disk). * - `DocumentSummaryPanel` — the transient summary / extracted-text panel with * the persistent "not saved · not a diagnosis" note. * - `AiRunPhaseNote` — the calm line under an action while its read runs in * the background (v1.40), shared by every document AI action. */ import { Sparkles } from "lucide-react"; import { Check, FileText, X } from "lucide-react"; import Link from "next/link"; import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; import type { AiRunPhase } from "@/hooks/use-ai-run"; import { useTranslations } from "@/lib/i18n/context"; import { cn } from "@/lib/utils"; import { type DocumentSuggestionDto, type DocumentSummaryMode, } from "@/lib/validations/inbound-documents"; import type { DocumentDescribeResult } from "./use-document-assist"; /** * The line under a document AI action while its read runs in the background, * or nothing when no read is running. * * `outcome` keeps the sentence true: a read whose result lands on the document * (the index, a stored summary, staged facts) tells the person they may leave; * a read whose answer lives only on this screen (suggestions, a transient * summary or transcription) does not promise that, because leaving drops it. */ export function AiRunPhaseNote({ phase, outcome, slot, }: { phase: AiRunPhase; outcome: "savedWithDocument" | "shownHere"; slot: string; }) { const { t } = useTranslations(); if (phase === "idle") return null; return (
{phase === "waitingForWorker" ? t("aiRuns.waitingForWorker") : outcome === "savedWithDocument" ? t("aiRuns.backgroundDocument") : t("aiRuns.backgroundScan")}
); } /** * Calm pointer to the AI settings, shown when assist is unavailable. When the * document is already searchable (auto-indexed locally) the copy stays honest — * it is searchable, an AI provider only adds a richer read. */ export function AiUnavailableHint({ reason, }: { reason: "no-provider" | "enable-local-ocr" | null; }) { const { t } = useTranslations(); const body = reason === "enable-local-ocr" ? t("documents.assist.unavailableLocalOcr") : t("documents.assist.unavailableBody"); return ({body}{" "} {t("documents.assist.unavailableAction")}
{label}
{value}
{t("documents.assist.empty")}
)}
{errorText}
) : body !== null ? ({body}
) : null}