"use client"; import { useState } from "react"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogTitle, } from "@/components/ui/dialog"; import { Toggle } from "@/components/ui/toggle"; import { REPLY_QUALITY_NOTE_MAX, REPLY_QUALITY_REASON_LABELS, REPLY_QUALITY_REASONS } from "@/lib/reply-quality-labels"; import { notifyError, notifySuccess } from "@/lib/notify"; import { saveReplyQualityReason } from "@/lib/reply-ratings"; const REASONS = REPLY_QUALITY_REASONS.map((key) => [key, REPLY_QUALITY_REASON_LABELS[key]] as const); /** * 不满意原因 after a 👎 (compliance round 2026-09-30). Everything here is * optional: the 👎 and the turn's snapshot are already saved when this opens; * closing it keeps them. One line says the turn is sent for review. The thanks * (or a failure) is a toast; the panel closes itself on success (2026-09-30). */ export function ReplyDownReason({ feedbackKey, onClose }: Readonly<{ feedbackKey: string; onClose: () => void }>) { const [picked, setPicked] = useState>(() => new Set()); const [note, setNote] = useState(""); const [state, setState] = useState<"idle" | "sending" | "failed">("idle"); async function submit() { if (state === "sending") return; setState("sending"); const ok = await saveReplyQualityReason(feedbackKey, REASONS.map(([key]) => key).filter((key) => picked.has(key)), note); if (ok) { notifySuccess("已收到,谢谢。"); onClose(); return; } setState("failed"); notifyError("没能提交,再试一次。"); } return ( { if (!next) onClose(); }}> 哪里不满意?可以不选
{REASONS.map(([key, label]) => ( setPicked((current) => { const next = new Set(current); if (next.has(key)) next.delete(key); else next.add(key); return next; })} > {label} ))}
setNote(event.target.value)} />
会把这一轮对话发给我们排查
); }