This commit is contained in:
eric
2026-03-09 03:45:10 -05:00
parent 7638e4032e
commit 52da06789b
9 changed files with 896 additions and 79 deletions

View File

@@ -0,0 +1,236 @@
"use client";
import { useState } from "react";
import { useTranslation, Link } from "@/i18n/navigation";
import Footer from "@/app/components/Footer";
interface Topic {
id: string;
title: string;
author: string;
avatar: string;
views: number;
replies: number;
likes: number;
category: string;
lastActive: string;
pinned: boolean;
}
const MOCK_TOPICS: Topic[] = [
{
id: "1",
title: "大理最佳共享办公空间推荐 Top 10",
author: "林晓",
avatar: "https://i.pravatar.cc/150?img=5",
views: 2340,
replies: 56,
likes: 128,
category: "资源共享",
lastActive: "2小时前",
pinned: true,
},
{
id: "2",
title: "2026年数字游民友好城市排名",
author: "张浩",
avatar: "https://i.pravatar.cc/150?img=3",
views: 1890,
replies: 42,
likes: 95,
category: "城市测评",
lastActive: "5小时前",
pinned: true,
},
{
id: "3",
title: "远程工作者的税务规划指南",
author: "陈悦",
avatar: "https://i.pravatar.cc/150?img=9",
views: 1560,
replies: 38,
likes: 87,
category: "税务签证",
lastActive: "1天前",
pinned: false,
},
{
id: "4",
title: "成都 vs 大理:哪个更适合游民?",
author: "周杰",
avatar: "https://i.pravatar.cc/150?img=7",
views: 1230,
replies: 67,
likes: 54,
category: "城市对比",
lastActive: "3小时前",
pinned: false,
},
{
id: "5",
title: "新手游民必备工具与装备清单",
author: "吴婷",
avatar: "https://i.pravatar.cc/150?img=1",
views: 980,
replies: 29,
likes: 76,
category: "经验分享",
lastActive: "1天前",
pinned: false,
},
{
id: "6",
title: "如何在泰国办理长期签证?",
author: "杨帅",
avatar: "https://i.pravatar.cc/150?img=12",
views: 2150,
replies: 89,
likes: 156,
category: "税务签证",
lastActive: "30分钟前",
pinned: false,
},
{
id: "7",
title: "数字游民保险选择指南",
author: "赵琪",
avatar: "https://i.pravatar.cc/150?img=16",
views: 1780,
replies: 45,
likes: 112,
category: "安全保障",
lastActive: "6小时前",
pinned: false,
},
{
id: "8",
title: "东南亚最佳数字游民目的地",
author: "黄磊",
avatar: "https://i.pravatar.cc/150?img=11",
views: 3210,
replies: 78,
likes: 234,
category: "目的地",
lastActive: "1小时前",
pinned: false,
},
];
const CATEGORIES = [
{ key: "all", zh: "全部", en: "All" },
{ key: "城市测评", zh: "城市测评", en: "City Review" },
{ key: "城市对比", zh: "城市对比", en: "City Comparison" },
{ key: "税务签证", zh: "税务签证", en: "Tax & Visa" },
{ key: "资源共享", zh: "资源共享", en: "Resource Sharing" },
{ key: "经验分享", zh: "经验分享", en: "Experience" },
{ key: "安全保障", zh: "安全保障", en: "Safety & Insurance" },
{ key: "目的地", zh: "目的地", en: "Destinations" },
];
export default function DiscussPage() {
const { t } = useTranslation("discuss");
const [activeCategory, setActiveCategory] = useState("all");
const [searchQuery, setSearchQuery] = useState("");
const filteredTopics = MOCK_TOPICS.filter((topic) => {
const matchesCategory = activeCategory === "all" || topic.category === activeCategory;
const matchesSearch = topic.title.toLowerCase().includes(searchQuery.toLowerCase());
return matchesCategory && matchesSearch;
});
return (
<div className="min-h-screen bg-[#fafafa] dark:bg-gray-950">
<main className="max-w-[1200px] mx-auto px-4 sm:px-6 py-6 sm:py-8">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6">
<div>
<h1 className="text-2xl sm:text-3xl font-bold text-gray-900 dark:text-gray-100">
{t("title")}
</h1>
<p className="text-gray-500 dark:text-gray-400 mt-1 text-sm sm:text-base">
{t("subtitle")}
</p>
</div>
<button className="bg-[#ff4d4f] text-white px-4 sm:px-6 py-2 sm:py-2.5 rounded-full font-medium text-sm hover:bg-[#ff7a45] transition-colors">
{t("newPost")}
</button>
</div>
<div className="mb-6">
<input
type="text"
placeholder={t("searchPlaceholder")}
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full px-4 py-3 rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 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 className="flex flex-wrap gap-2 mb-6">
{CATEGORIES.map((cat) => (
<button
key={cat.key}
onClick={() => setActiveCategory(cat.key)}
className={`px-3 sm:px-4 py-1.5 sm:py-2 rounded-full text-xs sm:text-sm font-medium transition-colors ${
activeCategory === cat.key
? "bg-[#ff4d4f] text-white"
: "bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700"
}`}
>
{cat.zh}
</button>
))}
</div>
<div className="space-y-3 sm:space-y-4">
{filteredTopics.map((topic) => (
<div
key={topic.id}
className="bg-white dark:bg-gray-900 rounded-xl p-4 sm:p-5 shadow-sm border border-gray-100 dark:border-gray-800 hover:shadow-md transition-shadow cursor-pointer"
>
<div className="flex items-start gap-3 sm:gap-4">
<img
src={topic.avatar}
alt={topic.author}
className="w-10 h-10 sm:w-12 sm:h-12 rounded-full object-cover shrink-0"
/>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1">
{topic.pinned && (
<span className="text-[#ff4d4f] text-xs font-medium">📌</span>
)}
<span className="text-xs text-[#ff4d4f] bg-red-50 dark:bg-red-900/20 px-2 py-0.5 rounded-full">
{topic.category}
</span>
</div>
<h3 className="font-semibold text-gray-900 dark:text-gray-100 text-sm sm:text-base mb-2 line-clamp-2">
{topic.title}
</h3>
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-gray-500 dark:text-gray-400">
<span>{topic.author}</span>
<span className="hidden sm:inline">·</span>
<span>{topic.lastActive}</span>
<span className="hidden sm:inline">·</span>
<span>👁 {topic.views}</span>
<span>💬 {topic.replies}</span>
<span> {topic.likes}</span>
</div>
</div>
</div>
</div>
))}
</div>
{filteredTopics.length === 0 && (
<div className="text-center py-12 sm:py-16">
<span className="text-4xl sm:text-5xl mb-4 block">💬</span>
<p className="text-gray-500 dark:text-gray-400 text-base sm:text-lg">
{t("noResults")}
</p>
</div>
)}
</main>
<Footer />
</div>
);
}