"use client"; import { useState } from "react"; import type { ForeshadowView } from "@/lib/api/types"; import type { ForeshadowStatus } from "@/lib/foreshadow/board"; interface ForeshadowCardProps { item: ForeshadowView; overdue: boolean; busy: boolean; onTransition: ( code: string, toStatus: ForeshadowStatus | null, progressNote: string, ) => void; } const NEXT_STATUS: Record = { OPEN: ["PARTIAL", "CLOSED"], PARTIAL: ["CLOSED"], OVERDUE: ["PARTIAL", "CLOSED"], CLOSED: [], }; // 伏笔卡(UX §6.8):code/title/回收窗口/importance/progress 时间线 + 状态变更/加进展。 // OVERDUE 用琥珀强调(不单靠色:加 ⚠ 图标 + 文案,a11y §10)。 export function ForeshadowCard({ item, overdue, busy, onTransition, }: ForeshadowCardProps) { const [note, setNote] = useState(""); const transitions = NEXT_STATUS[item.status] ?? []; const windowText = recoveryWindow(item); return (
  • {item.code} {overdue ? ( ⚠ 逾期 ) : null}

    {item.title}

    {typeof item.planted_at === "number" ? (
    埋于 {item.planted_at} 章
    ) : null} {windowText ?
    窗口 {windowText}
    : null} {item.importance ?
    {item.importance}
    : null}
    {item.progress && item.progress.length > 0 ? ( ) : null} {transitions.length > 0 || item.status !== "CLOSED" ? (
    {transitions.length > 0 ? (
    {transitions.map((to) => ( ))}
    ) : null} {item.status !== "CLOSED" ? (
    setNote(e.target.value)} placeholder="加进展(如:23章发光)" className="min-w-0 flex-1 rounded border border-line bg-bg px-2 py-0.5 text-xs text-ink focus:border-cinnabar focus:outline-none" />
    ) : null}
    ) : null}
  • ); } function recoveryWindow(item: ForeshadowView): string | null { const from = item.expected_close_from; const to = item.expected_close_to; if (typeof from === "number" && typeof to === "number") return `${from}-${to}`; if (typeof to === "number") return `≤${to}`; if (typeof from === "number") return `≥${from}`; return null; } function progressLabel(entry: Record): string { const chapter = entry["chapter"]; const note = entry["note"]; const noteStr = typeof note === "string" ? note : JSON.stringify(entry); return typeof chapter === "number" ? `${chapter}章:${noteStr}` : noteStr; }