Files
gitlab-instance-0a899031_cn…/app/[locale]/feedback/page.tsx
2026-06-06 04:29:46 -05:00

159 lines
6.5 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 { useTranslation } from "@/i18n/navigation";
import Footer from "@/app/components/Footer";
import { apiFetch } from "@/app/lib/api-client";
export default function FeedbackPage() {
const { t } = useTranslation("feedback");
const [submitted, setSubmitted] = useState(false);
const [form, setForm] = useState({
type: "suggestion" as "suggestion" | "bug",
email: "",
title: "",
content: "",
});
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
await apiFetch("/api/feedback", {
method: "POST",
body: JSON.stringify(form),
});
setSubmitted(true);
};
return (
<div className="min-h-screen bg-[#fafafa] dark:bg-gray-950">
<main className="max-w-[640px] mx-auto px-4 sm:px-6 py-8 sm:py-12">
<header className="mb-8">
<h1 className="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100 flex items-center gap-2">
<span className="w-1 h-8 bg-[#ff4d4f] rounded-full" />
{t("title")}
</h1>
<p className="text-gray-500 dark:text-gray-400 mt-1 text-sm sm:text-base">
{t("subtitle")}
</p>
</header>
{submitted ? (
<div className="bg-white dark:bg-gray-900 rounded-2xl shadow-sm border border-gray-100 dark:border-gray-800 p-8 text-center">
<span className="text-5xl mb-4 block">🙏</span>
<h2 className="text-xl font-bold text-gray-900 dark:text-gray-100 mb-2">
{t("successTitle")}
</h2>
<p className="text-gray-500 dark:text-gray-400 mb-6">
{t("successDesc")}
</p>
<button
onClick={() => {
setSubmitted(false);
setForm({ type: "suggestion", email: "", title: "", content: "" });
}}
className="px-6 py-2.5 rounded-xl border border-gray-200 dark:border-gray-700 text-gray-700 dark:text-gray-300 font-medium hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
>
{t("submitAnother")}
</button>
</div>
) : (
<form
onSubmit={handleSubmit}
className="bg-white dark:bg-gray-900 rounded-2xl shadow-sm border border-gray-100 dark:border-gray-800 p-6 sm:p-8 space-y-6"
>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
{t("type")} *
</label>
<div className="flex gap-3">
<label className="flex-1 flex items-center justify-center gap-2 p-3 rounded-xl border cursor-pointer transition-colors has-[:checked]:border-[#ff4d4f] has-[:checked]:bg-[#ff4d4f]/5">
<input
type="radio"
name="type"
value="suggestion"
checked={form.type === "suggestion"}
onChange={(e) =>
setForm((f) => ({ ...f, type: e.target.value as "suggestion" }))
}
className="sr-only"
/>
<span>💡</span>
<span>{t("suggestion")}</span>
</label>
<label className="flex-1 flex items-center justify-center gap-2 p-3 rounded-xl border cursor-pointer transition-colors has-[:checked]:border-[#ff4d4f] has-[:checked]:bg-[#ff4d4f]/5">
<input
type="radio"
name="type"
value="bug"
checked={form.type === "bug"}
onChange={(e) =>
setForm((f) => ({ ...f, type: e.target.value as "bug" }))
}
className="sr-only"
/>
<span>🐛</span>
<span>{t("bug")}</span>
</label>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
{t("email")} *
</label>
<input
type="email"
required
value={form.email}
onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}
placeholder={t("emailPlaceholder")}
className="w-full px-4 py-3 rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20 focus:border-[#ff4d4f]"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
{t("titleLabel")} *
</label>
<input
type="text"
required
value={form.title}
onChange={(e) => setForm((f) => ({ ...f, title: e.target.value }))}
placeholder={t("titlePlaceholder")}
className="w-full px-4 py-3 rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20 focus:border-[#ff4d4f]"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
{t("content")} *
</label>
<textarea
required
rows={5}
value={form.content}
onChange={(e) => setForm((f) => ({ ...f, content: e.target.value }))}
placeholder={t("contentPlaceholder")}
className="w-full px-4 py-3 rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20 focus:border-[#ff4d4f] resize-none"
/>
</div>
<p className="text-xs text-gray-400 dark:text-gray-500">
已接入本地 FastAPI + PocketBase,提交后会写入 feedback 集合。
</p>
<button
type="submit"
className="w-full py-3.5 rounded-xl bg-[#ff4d4f] text-white font-semibold hover:bg-[#ff7a45] transition-colors"
>
{t("submit")}
</button>
</form>
)}
</main>
<Footer />
</div>
);
}