"use client"; import { useState } from "react"; import { badgeVariants } from "@/components/ui/badge"; import type { Note, NoteOp } from "@/lib/annotations/types"; // One note: its text, who wrote it, its status, the replies, and what can be // done to it. Shared by the timed notes, the row notes and the take notes. const STATUS_TONE = { open: "open", resolved: "info", wontfix: "info" } as const; export function NoteThread({ note, write, busy, head, }: { note: Note; write: (op: NoteOp) => Promise; busy: boolean; /** What the note is on, drawn before its text (a timestamp, an entry id). */ head?: React.ReactNode; }) { const [reply, setReply] = useState(null); const open = note.status === "open"; return (
{head} {note.author === "agent" && agent} {!open && {note.status}} {note.text} {open ? ( <> ) : ( )} {note.author === "operator" && ( )}
{note.replies.map((r, i) => (
{r.author === "agent" && agent} {r.text}
))} {reply !== null && ( setReply(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter" && reply.trim()) { void write({ op: "reply", id: note.id, text: reply }); setReply(null); } if (e.key === "Escape") setReply(null); }} placeholder="reply — Enter to send" className="ml-4 w-[calc(100%-1rem)] rounded border border-[var(--color-line)] bg-[var(--color-ink)] px-1.5 py-0.5 text-[12px] text-[var(--color-text)] outline-none focus:border-[var(--color-sel)]" /> )}
); } /** A one-line composer: Enter adds, Escape cancels. */ export function NoteComposer({ onAdd, onCancel, busy, placeholder, head, testId, }: { onAdd: (text: string) => void; onCancel?: () => void; busy: boolean; placeholder: string; head?: React.ReactNode; testId?: string; }) { const [text, setText] = useState(""); const add = () => { if (!text.trim()) return; onAdd(text); setText(""); }; return (
{head} setText(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") add(); if (e.key === "Escape") onCancel?.(); }} placeholder={placeholder} className="min-w-[14rem] flex-1 rounded border border-[var(--color-line)] bg-[var(--color-ink)] px-1.5 py-0.5 text-[12px] text-[var(--color-text)] outline-none focus:border-[var(--color-sel)]" />
); }