import { useCallback, useEffect, useRef, useState } from "react"; import { Check, Loader2, NotebookPen, TriangleAlert } from "lucide-react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Textarea } from "@/components/ui/textarea"; import { cn } from "@/lib/utils"; const AUTOSAVE_MS = 700; type Status = "idle" | "saving" | "saved" | "error"; /** * Free-form notes on an asset or loan: who else is involved, what was agreed, * where the paperwork is. There is no Save button: the text is written a moment * after you stop typing, when you click away, and when you leave the page. * * Give it `key={accountId}` so switching accounts starts from that account's * notes instead of carrying the previous text over. */ export function AccountNotes({ value, onSave, className, }: { value: string | null | undefined; onSave: (notes: string) => Promise | void; className?: string; }) { const [text, setText] = useState(value ?? ""); const [status, setStatus] = useState("idle"); const saved = useRef(value ?? ""); const latest = useRef(text); const onSaveRef = useRef(onSave); onSaveRef.current = onSave; const save = useCallback(async (next: string) => { if (next === saved.current) return; setStatus("saving"); try { await onSaveRef.current(next); saved.current = next; // Typing may have moved on while this was in flight; that has its own save queued. setStatus(latest.current === next ? "saved" : "saving"); } catch { setStatus("error"); } }, []); // Write shortly after typing stops. useEffect(() => { latest.current = text; if (text === saved.current) return; const timer = setTimeout(() => void save(text), AUTOSAVE_MS); return () => clearTimeout(timer); }, [text, save]); // Leaving the page with unsaved typing still saves it. useEffect( () => () => { if (latest.current !== saved.current) void onSaveRef.current(latest.current); }, [] ); return ( Notes {status === "saving" && (<> Saving…)} {status === "saved" && (<> Saved)} {status === "error" && (<> Couldn't save, still trying as you type)}