89 lines
2.8 KiB
TypeScript
89 lines
2.8 KiB
TypeScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
import { useToast } from "@/lib/toast";
|
||
|
||
const TYPES = [
|
||
{ key: "idea", label: "💡 想法" },
|
||
{ key: "bug", label: "🐛 问题" },
|
||
{ key: "love", label: "❤️ 喜欢" },
|
||
];
|
||
|
||
export default function FeedbackWidget() {
|
||
const { toast } = useToast();
|
||
const [open, setOpen] = useState(false);
|
||
const [type, setType] = useState("idea");
|
||
const [msg, setMsg] = useState("");
|
||
const [sending, setSending] = useState(false);
|
||
|
||
const submit = async (e: React.FormEvent) => {
|
||
e.preventDefault();
|
||
if (!msg.trim()) return;
|
||
setSending(true);
|
||
// Persist locally for demo; can wire to API later
|
||
try {
|
||
const key = "nomadro-feedback";
|
||
const prev = JSON.parse(localStorage.getItem(key) || "[]");
|
||
prev.push({ type, msg: msg.trim(), at: new Date().toISOString() });
|
||
localStorage.setItem(key, JSON.stringify(prev.slice(-50)));
|
||
toast("感谢反馈!我们会认真看的 🙏");
|
||
setMsg("");
|
||
setOpen(false);
|
||
} finally {
|
||
setSending(false);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<>
|
||
<button
|
||
className="feedback-fab"
|
||
onClick={() => setOpen(true)}
|
||
aria-label="反馈"
|
||
title="反馈建议"
|
||
>
|
||
💬
|
||
</button>
|
||
|
||
{open && (
|
||
<div className="modal-overlay open" onClick={(e) => e.target === e.currentTarget && setOpen(false)}>
|
||
<div className="modal feedback-modal">
|
||
<button className="modal-close" onClick={() => setOpen(false)} aria-label="关闭">✕</button>
|
||
<div className="feedback-body">
|
||
<span className="section-tag">💬 FEEDBACK</span>
|
||
<h2>给 nomadro 提建议</h2>
|
||
<p>功能想法、体验问题,或只是想说喜欢</p>
|
||
<form onSubmit={submit}>
|
||
<div className="feedback-types">
|
||
{TYPES.map((t) => (
|
||
<button
|
||
key={t.key}
|
||
type="button"
|
||
className={`filter-btn${type === t.key ? " active" : ""}`}
|
||
onClick={() => setType(t.key)}
|
||
>
|
||
{t.label}
|
||
</button>
|
||
))}
|
||
</div>
|
||
<textarea
|
||
className="feedback-textarea"
|
||
rows={4}
|
||
placeholder="写下你的想法…"
|
||
value={msg}
|
||
onChange={(e) => setMsg(e.target.value)}
|
||
required
|
||
maxLength={500}
|
||
/>
|
||
<button type="submit" className="btn btn-primary" disabled={sending || !msg.trim()} style={{ width: "100%" }}>
|
||
{sending ? "发送中…" : "发送反馈 🚀"}
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</>
|
||
);
|
||
}
|