"use client"; import { useEffect, useRef, useState } from "react"; import { NOTE_LIMIT, type NoteEntry } from "@/lib/note-types"; // A generous note, on anything. // // GENEROUS IS THE POINT. This is a textarea with an 8000-character budget, not // a one-line "why" field -- the verdict chip already has one of those, and its // terseness is exactly why the reasoning kept ending up in chat instead. What // gets written here is meant to survive being handed to somebody else cold. // // Collapsed until there is something to show or somebody asks for it, because a // page with fifteen open textareas on it is unreadable. type Props = { /** Where to POST. One of these two shapes. */ song?: string; target?: string; set?: string; hook?: string; initial: NoteEntry | null; label?: string; /** Start open, for the one place per page that is the obvious one to write in. */ open?: boolean; rows?: number; }; export default function NoteField({ song, target, set, hook, initial, label = "note", open = false, rows = 4, }: Props) { const [entry, setEntry] = useState(initial); const [draft, setDraft] = useState(initial?.note ?? ""); const [editing, setEditing] = useState(open); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); const [ready, setReady] = useState(false); const ta = useRef(null); useEffect(() => setReady(true), []); useEffect(() => { setEntry(initial); setDraft(initial?.note ?? ""); }, [initial]); const dirty = draft !== (entry?.note ?? ""); const save = async () => { setSaving(true); setError(null); try { const res = await fetch("/api/browse/notes", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(set ? { set, hook, note: draft } : { song, target, note: draft }), cache: "no-store", }); const j = await res.json(); if (!res.ok) throw new Error(j.error || `HTTP ${res.status}`); const next = draft.trim() ? { note: draft.replace(/\s+$/, ""), at: new Date().toISOString() } : null; setEntry(next); if (!next) setDraft(""); setEditing(false); } catch (e) { setError(e instanceof Error ? e.message : String(e)); } finally { setSaving(false); } }; if (!editing) { return ( ); } return (