import { useState } from "react"; import { notebooksApi } from "../api/endpoints"; import type { AnswerFeedback as Feedback } from "../api/types"; const REASONS: { id: string; label: string }[] = [ { id: "forgot_chat", label: "Forgot something we said" }, { id: "mixed_chat", label: "Mixed up an earlier chat" }, { id: "wrong", label: "Wrong or made up" }, { id: "missed", label: "Missed something in my posts" }, { id: "bad_sources", label: "Bad sources" }, { id: "other", label: "Something else" }, ]; export const Thumb = ({ down }: { down?: boolean }) => ( ); const CopyGlyph = ({ done }: { done?: boolean }) => ( ); /** The answer as plain text for pasting: the [1] citation markers are left out. */ const forCopy = (text: string) => text.replace(/\s*\[\d+\](?:\[\d+\])*/g, "").trim(); /** Copy, thumbs up and thumbs down under an answer. A thumbs down opens a few reasons and an optional note. Saved as soon as it is chosen. */ export function AnswerFeedback({ messageId, initial, text }: { messageId: string; initial?: Feedback | null; text?: string }) { const [fb, setFb] = useState(initial ?? null); const [open, setOpen] = useState(false); const [reasons, setReasons] = useState(initial?.reasons ?? []); const [comment, setComment] = useState(initial?.comment ?? ""); const [error, setError] = useState(false); const [thanks, setThanks] = useState(false); const [copied, setCopied] = useState(false); const copy = async () => { try { await navigator.clipboard.writeText(forCopy(text ?? "")); setCopied(true); setTimeout(() => setCopied(false), 1600); } catch { setError(true); // the browser refused the clipboard } }; const save = async (rating: "up" | "down" | null, r: string[] = [], c = "") => { const before = fb; setError(false); setFb(rating ? { rating, reasons: r, comment: c || null } : null); // shows at once; undone if the save fails try { const res = await notebooksApi.rate(messageId, { rating, reasons: r, comment: c || undefined }); setFb(res.feedback); } catch { setFb(before); setError(true); } }; const choose = (rating: "up" | "down") => { setThanks(false); if (fb?.rating === rating) { setOpen(false); void save(null); return; } setOpen(rating === "down"); if (rating === "up") { setReasons([]); setComment(""); } void save(rating, rating === "down" ? reasons : []); }; return (
{text && ( )} {thanks && Thanks, saved.} {error && Could not save that. Try again.}
{open && fb?.rating === "down" && (

What went wrong? (optional)

{REASONS.map((r) => ( ))}