nomadweb/frontend/src/components/FeedbackWidget.tsx
eric d1bc4af87f Add jet lag, housing guide, phrasebook, and feedback widget
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-28 23:28:52 -05:00

89 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"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>
)}
</>
);
}