Files
2026-03-09 00:05:00 -05:00

164 lines
9.9 KiB
TypeScript
Raw Permalink 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";
type TabType = "friends" | "dating" | "partner" | "roommate" | "cofounder" | "explore";
interface Profile {
id: string;
name: string;
age: number;
location: string;
tags: string[];
bio: string;
gradient: string;
initial: string;
avatarColor: string;
photo: string;
}
interface MatchCard {
id: string;
name: string;
location: string;
timeAgo: string;
initial: string;
color: string;
photo: string;
}
const MOCK_PROFILES: Profile[] = [
{ id: "1", name: "林晓雨", age: 28, location: "大理", tags: ["本科学历", "远程工作者", "数字游民", "咖啡爱好者"], bio: "数字游民三年,目前在云南大理远程做产品设计。喜欢爬山、摄影,周末常去洱海边发呆。", gradient: "from-rose-400 via-pink-400 to-fuchsia-400", initial: "林", avatarColor: "bg-rose-500", photo: "https://i.pravatar.cc/150?img=1" },
{ id: "2", name: "陈浩然", age: 32, location: "成都", tags: ["硕士学历", "独立开发者", "自由职业者", "素食主义"], bio: "在成都住了两年,做独立开发。喜欢冲浪和冥想,寻找志同道合的旅伴一起探索世界。", gradient: "from-amber-400 via-orange-400 to-red-400", initial: "陈", avatarColor: "bg-amber-500", photo: "https://i.pravatar.cc/150?img=3" },
{ id: "3", name: "王思琪", age: 26, location: "深圳", tags: ["本科学历", "内容创作者", "数字游民", "环保主义者"], bio: "自由撰稿人,在深圳写写画画。热爱瑜伽和冥想,相信慢生活才是真正的奢侈。", gradient: "from-emerald-400 via-teal-400 to-cyan-400", initial: "王", avatarColor: "bg-emerald-500", photo: "https://i.pravatar.cc/150?img=5" },
{ id: "4", name: "张明远", age: 30, location: "杭州", tags: ["MBA学历", "创业中", "自由职业者", "徒步爱好者"], bio: "正在杭州创业,做远程团队协作工具。周末喜欢去西湖徒步,偶尔品鉴龙井茶。", gradient: "from-violet-400 via-purple-400 to-indigo-400", initial: "张", avatarColor: "bg-violet-500", photo: "https://i.pravatar.cc/150?img=7" },
{ id: "5", name: "李雅婷", age: 27, location: "厦门", tags: ["本科学历", "UI设计师", "数字游民", "摄影爱好者"], bio: "在厦门远程做UI设计业余时间探索闽南美食。喜欢用相机记录生活寻找一起探店的朋友。", gradient: "from-rose-500 via-red-400 to-orange-500", initial: "李", avatarColor: "bg-rose-500", photo: "https://i.pravatar.cc/150?img=9" },
{ id: "6", name: "刘子轩", age: 33, location: "昆明", tags: ["博士学历", "数据科学家", "远程工作者", "户外爱好者"], bio: "在昆明远程工作,热爱户外运动。正在探索云南各地,希望认识更多志同道合的朋友。", gradient: "from-blue-400 via-indigo-400 to-violet-500", initial: "刘", avatarColor: "bg-blue-500", photo: "https://i.pravatar.cc/150?img=11" },
];
const MOCK_MATCHES: MatchCard[] = [
{ id: "m1", name: "周雨桐", location: "杭州", timeAgo: "2天前", initial: "周", color: "bg-pink-400", photo: "https://i.pravatar.cc/150?img=29" },
{ id: "m2", name: "吴俊杰", location: "成都", timeAgo: "1周前", initial: "吴", color: "bg-amber-400", photo: "https://i.pravatar.cc/150?img=34" },
{ id: "m3", name: "郑诗涵", location: "上海", timeAgo: "3周前", initial: "郑", color: "bg-emerald-400", photo: "https://i.pravatar.cc/150?img=36" },
{ id: "m4", name: "孙宇航", location: "深圳", timeAgo: "1月前", initial: "孙", color: "bg-violet-400", photo: "https://i.pravatar.cc/150?img=38" },
{ id: "m5", name: "赵梦琪", location: "厦门", timeAgo: "1年前", initial: "赵", color: "bg-rose-400", photo: "https://i.pravatar.cc/150?img=41" },
];
const TAB_ORDER: TabType[] = ["friends", "dating", "partner", "roommate", "cofounder", "explore"];
export default function DatingPage() {
const { t } = useTranslation("match");
const [activeTab, setActiveTab] = useState<TabType>("friends");
const [currentIndex, setCurrentIndex] = useState(0);
const currentProfile = MOCK_PROFILES[currentIndex];
const hasMoreProfiles = currentIndex < MOCK_PROFILES.length - 1;
const handleLike = () => {
setCurrentIndex((i) => (hasMoreProfiles ? i + 1 : 0));
};
const handleDislike = () => {
setCurrentIndex((i) => (hasMoreProfiles ? i + 1 : 0));
};
const badgeMap: Record<TabType, string> = {
friends: t("badgeFriends"),
dating: t("badgeDating"),
partner: t("badgePartner"),
roommate: t("badgeRoommate"),
cofounder: t("badgeCofounder"),
explore: t("badgeExplore"),
};
const badgeText = badgeMap[activeTab];
return (
<div className="min-h-screen bg-[#fafafa] dark:bg-gray-950">
<div className="flex justify-center pt-6 pb-4 px-4">
<div className="flex flex-wrap justify-center gap-2 max-w-2xl">
{TAB_ORDER.map((tab) => (
<button
key={tab}
onClick={() => setActiveTab(tab)}
className={`px-4 py-2 rounded-full text-xs sm:text-sm font-medium transition-all duration-200 ${
activeTab === tab
? "bg-[#ff4d4f] text-white shadow-sm"
: "bg-white dark:bg-gray-900 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 border border-gray-100 dark:border-gray-800"
}`}
>
{t(tab)}
</button>
))}
</div>
</div>
<div className="flex flex-col md:flex-row gap-6 max-w-7xl mx-auto px-4 pb-12">
<aside className="hidden md:block w-72 flex-shrink-0">
<div className="sticky top-24">
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-1">{t("title")} 💕</h2>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">{t("likedYou")}</p>
<div className="space-y-3">
{MOCK_MATCHES.map((match) => (
<div key={match.id} className="flex items-center gap-3 p-3 rounded-xl bg-white dark:bg-gray-900 border border-gray-100 dark:border-gray-800 shadow-sm hover:shadow-md transition-shadow cursor-pointer">
<img src={match.photo} alt={match.name} className="w-12 h-12 rounded-full object-cover shadow-sm flex-shrink-0" />
<div className="flex-1 min-w-0">
<p className="font-medium text-gray-900 dark:text-gray-100 truncate">{match.name}</p>
<p className="text-xs text-gray-500 dark:text-gray-400 truncate">{match.location}</p>
</div>
<span className="text-xs text-gray-400 dark:text-gray-500 bg-gray-50 dark:bg-gray-800 px-2 py-1 rounded-full flex-shrink-0">{match.timeAgo}</span>
</div>
))}
</div>
</div>
</aside>
<main className="flex-1 min-w-0 flex flex-col items-center">
<div className="w-full max-w-md mx-auto">
<div className={`relative rounded-2xl overflow-hidden bg-gradient-to-br ${currentProfile.gradient} p-8 pb-6 shadow-xl border border-white/20`}>
<div className="absolute top-4 right-4 flex flex-col items-end gap-1">
<span className="px-3 py-1.5 rounded-full bg-white/90 text-gray-800 text-xs font-medium backdrop-blur-sm">{badgeText}</span>
<a href="#" className="text-[#ff4d4f] hover:text-red-600 text-sm font-medium">{t("report")}</a>
</div>
<div className="flex justify-center mt-12 mb-6">
<img src={currentProfile.photo} alt={currentProfile.name} className="w-28 h-28 rounded-full shadow-lg border-4 border-white/50 object-cover" />
</div>
<div className="text-center mb-4">
<h3 className="text-xl font-bold text-white drop-shadow-sm">{currentProfile.name}{currentProfile.age}</h3>
<p className="text-white/90 text-sm mt-1">📍 {currentProfile.location}</p>
</div>
<div className="mb-4">
<p className="text-white/90 text-xs font-medium mb-2">{t("matchTags")}:</p>
<div className="flex flex-wrap gap-2 justify-center">
{currentProfile.tags.map((tag) => (
<span key={tag} className="px-3 py-1 rounded-full bg-white/80 text-gray-800 text-xs font-medium">{tag}</span>
))}
</div>
</div>
<p className="text-white/95 text-sm leading-relaxed text-center mb-8 px-2">{currentProfile.bio}</p>
<div className="flex items-center justify-center gap-8">
<div className="flex flex-col items-center gap-2">
<button onClick={handleDislike} className="w-16 h-16 rounded-full bg-white shadow-lg flex items-center justify-center text-[#ff4d4f] hover:bg-red-50 hover:scale-105 active:scale-95 transition-all" aria-label={t("dislike")}>
<span className="text-2xl"></span>
</button>
<span className="text-xs text-white/80 font-medium">{t("dislike")}</span>
</div>
<div className="flex flex-col items-center gap-2">
<button onClick={handleLike} className="w-16 h-16 rounded-full bg-[#22c55e] shadow-lg flex items-center justify-center text-white hover:bg-[#16a34a] hover:scale-105 active:scale-95 transition-all" aria-label={t("like")}>
<span className="text-2xl">💚</span>
</button>
<span className="text-xs text-white/80 font-medium">{t("like")}</span>
</div>
</div>
</div>
<p className="text-center text-sm text-gray-500 dark:text-gray-400 mt-4">{currentIndex + 1} / {MOCK_PROFILES.length}</p>
</div>
</main>
<div className="hidden lg:block w-72 flex-shrink-0" />
</div>
<Footer />
</div>
);
}