Files
gitlab-instance-0a899031_cn…/app/dating/page.tsx
2026-03-07 12:33:14 -06:00

305 lines
11 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";
type TabType = "friends" | "dating";
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" },
];
export default function DatingPage() {
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 = () => {
if (hasMoreProfiles) {
setCurrentIndex((i) => i + 1);
} else {
setCurrentIndex(0);
}
};
const handleDislike = () => {
if (hasMoreProfiles) {
setCurrentIndex((i) => i + 1);
} else {
setCurrentIndex(0);
}
};
const badgeText =
activeTab === "dating"
? "你们都在寻找 🌹 约会"
: "你们都在寻找 🤝 交友";
return (
<div className="min-h-screen bg-[#fafafa]">
{/* Tabs */}
<div className="flex justify-center pt-6 pb-4 px-4">
<div className="inline-flex rounded-full bg-white p-1 shadow-sm border border-gray-100">
<button
onClick={() => setActiveTab("friends")}
className={`px-6 py-2.5 rounded-full text-sm font-medium transition-all duration-200 ${
activeTab === "friends"
? "bg-[#ff4d4f] text-white shadow-sm"
: "text-gray-600 hover:text-gray-900"
}`}
>
</button>
<button
onClick={() => setActiveTab("dating")}
className={`px-6 py-2.5 rounded-full text-sm font-medium transition-all duration-200 ${
activeTab === "dating"
? "bg-[#ff4d4f] text-white shadow-sm"
: "text-gray-600 hover:text-gray-900"
}`}
>
</button>
</div>
</div>
<div className="flex flex-col md:flex-row gap-6 max-w-7xl mx-auto px-4 pb-12">
{/* Left Sidebar - hidden on mobile */}
<aside className="hidden md:block w-72 flex-shrink-0">
<div className="sticky top-24">
<h2 className="text-lg font-semibold text-gray-900 mb-1">
💕
</h2>
<p className="text-sm text-gray-500 mb-4"></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 border border-gray-100 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 truncate">
{match.name}
</p>
<p className="text-xs text-gray-500 truncate">
{match.location}
</p>
</div>
<span className="text-xs text-gray-400 bg-gray-50 px-2 py-1 rounded-full flex-shrink-0">
{match.timeAgo}
</span>
</div>
))}
</div>
</div>
</aside>
{/* Center - Main Card */}
<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`}
>
{/* Top right: badge + report */}
<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"
>
</a>
</div>
{/* Avatar */}
<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>
{/* Name, age, location */}
<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>
{/* Tags */}
<div className="mb-4">
<p className="text-white/90 text-xs font-medium mb-2">
:
</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>
{/* Bio */}
<p className="text-white/95 text-sm leading-relaxed text-center mb-8 px-2">
{currentProfile.bio}
</p>
{/* Action buttons */}
<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="不感兴趣"
>
<span className="text-2xl"></span>
</button>
<span className="text-xs text-white/80 font-medium">
</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="喜欢"
>
<span className="text-2xl">💚</span>
</button>
<span className="text-xs text-white/80 font-medium"></span>
</div>
</div>
</div>
{/* Progress indicator */}
<p className="text-center text-sm text-gray-500 mt-4">
{currentIndex + 1} / {MOCK_PROFILES.length}
</p>
</div>
</main>
{/* Right spacer for desktop balance */}
<div className="hidden lg:block w-72 flex-shrink-0" />
</div>
</div>
);
}