Files
gitlab-instance-0a899031_salon/app/page.tsx
2026-03-15 23:44:40 -05:00

230 lines
13 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 Link from "next/link";
import HeroSection from "./components/HeroSection";
import SessionCoverImage from "./components/SessionCoverImage";
import Footer from "./components/Footer";
import Header from "./components/Header";
import AvatarStack from "./components/AvatarStack";
import { SESSIONS, ACTIVITY_TYPES, SESSION_TAGS } from "@/config/home.config";
export default function Home() {
return (
<div className="min-h-screen bg-[#faf8f5] dark:bg-stone-950 pb-20 sm:pb-12">
<Header />
<HeroSection />
<main className="max-w-[900px] mx-auto px-4 sm:px-6 md:px-8 py-8 sm:py-12 md:py-14 space-y-10 sm:space-y-14">
{/* 是什么 / 不是什么 · 适合谁 / 不适合谁 - 合并一套 */}
<section>
<div className="rounded-xl sm:rounded-2xl bg-white dark:bg-stone-900/80 border border-stone-200/80 dark:border-stone-700/80 p-4 sm:p-6 overflow-hidden">
<div className="grid sm:grid-cols-2 gap-6 sm:gap-8">
<div>
<h3 className="text-base sm:text-lg font-semibold text-stone-800 dark:text-stone-100 mb-3 flex items-center gap-2">
<span className="text-amber-600 dark:text-amber-400"></span> ·
</h3>
<ul className="space-y-1.5 text-sm text-stone-600 dark:text-stone-400">
<li>· 68 </li>
<li>· </li>
<li>· </li>
</ul>
</div>
<div>
<h3 className="text-base sm:text-lg font-semibold text-stone-800 dark:text-stone-100 mb-3 flex items-center gap-2">
<span className="text-stone-400 dark:text-stone-500"></span> ·
</h3>
<ul className="space-y-1.5 text-sm text-stone-600 dark:text-stone-400">
<li>· </li>
<li>· 线</li>
<li>· </li>
</ul>
</div>
</div>
</div>
</section>
{/* 报名流程 - 3 步 */}
<section>
<h2 className="text-lg sm:text-xl font-semibold text-stone-800 dark:text-stone-100 mb-4 sm:mb-5 flex items-center gap-2">
<span>📋</span>
</h2>
<div className="rounded-xl sm:rounded-2xl bg-white dark:bg-stone-900/80 border border-stone-200/80 dark:border-stone-700/80 p-4 sm:p-6 md:p-8">
<div className="grid sm:grid-cols-3 gap-6 sm:gap-8">
<div className="flex flex-col items-center text-center">
<div className="w-10 h-10 rounded-full bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300 font-bold text-lg flex items-center justify-center mb-3">1</div>
<h4 className="font-semibold text-stone-800 dark:text-stone-100 text-sm sm:text-base"></h4>
<p className="mt-1 text-xs sm:text-sm text-stone-500 dark:text-stone-400"></p>
</div>
<div className="flex flex-col items-center text-center">
<div className="w-10 h-10 rounded-full bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300 font-bold text-lg flex items-center justify-center mb-3">2</div>
<h4 className="font-semibold text-stone-800 dark:text-stone-100 text-sm sm:text-base"></h4>
<p className="mt-1 text-xs sm:text-sm text-stone-500 dark:text-stone-400"></p>
</div>
<div className="flex flex-col items-center text-center">
<div className="w-10 h-10 rounded-full bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300 font-bold text-lg flex items-center justify-center mb-3">3</div>
<h4 className="font-semibold text-stone-800 dark:text-stone-100 text-sm sm:text-base">/</h4>
<p className="mt-1 text-xs sm:text-sm text-stone-500 dark:text-stone-400"></p>
</div>
</div>
<p className="mt-6 pt-6 border-t border-stone-100 dark:border-stone-700 text-xs sm:text-sm text-stone-500 dark:text-stone-400 text-center">
</p>
</div>
</section>
{/* 信任标签 + 最近报名意向 */}
<div className="flex flex-col gap-4 sm:gap-6">
<div className="flex flex-wrap justify-center gap-x-6 gap-y-1.5 sm:gap-x-8 text-xs sm:text-sm text-stone-600 dark:text-stone-400">
<span>📍 </span>
<span>👥 68 </span>
<span> </span>
<span>🆓 </span>
</div>
<div className="rounded-xl sm:rounded-2xl bg-white dark:bg-stone-900/80 border border-stone-200/80 dark:border-stone-700/80 p-4 sm:p-6">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 sm:gap-4">
<div className="min-w-0">
<p className="text-[10px] sm:text-xs font-medium text-amber-600 dark:text-amber-400/90 uppercase tracking-wider mb-1.5 sm:mb-2">
👋
</p>
<AvatarStack />
</div>
</div>
</div>
</div>
{/* 本周场次 */}
<section>
<h2 className="text-lg sm:text-xl font-semibold text-stone-800 dark:text-stone-100 mb-4 sm:mb-5 flex items-center gap-2">
<span>📅</span>
</h2>
<div className="grid gap-3 sm:gap-4 sm:grid-cols-2">
{SESSIONS.map((s, i) => (
<Link
key={s.id}
href={`/join?session=${encodeURIComponent(s.id)}`}
className="group flex flex-col sm:flex-row gap-3 sm:gap-4 p-4 sm:p-5 rounded-xl sm:rounded-2xl bg-white dark:bg-stone-900/80 border border-stone-200/80 dark:border-stone-700/80 hover:border-amber-200 dark:hover:border-amber-900/50 hover:shadow-lg hover:shadow-amber-900/5 transition-all"
>
<div className="relative w-full sm:w-24 sm:h-24 shrink-0 aspect-[16/10] sm:aspect-square rounded-lg sm:rounded-xl overflow-hidden bg-stone-100 dark:bg-stone-800">
{s.coverImage ? (
<SessionCoverImage src={s.coverImage} alt={s.title} type={s.type} fill sizes="(max-width: 640px) 100vw, 96px" className="object-cover" />
) : (
<div className="absolute inset-0 flex items-center justify-center text-2xl">
{s.type === "skill-exchange" ? "🔄" : "☕"}
</div>
)}
</div>
<div className="min-w-0 flex-1">
<div className="flex flex-wrap gap-1 mb-1.5">
{s.tags?.map((tag) => (
<span key={tag} className="inline-block text-[9px] sm:text-[10px] font-medium text-amber-600 dark:text-amber-400/90 bg-amber-50 dark:bg-amber-900/20 px-1.5 py-0.5 rounded">
{SESSION_TAGS[tag]}
</span>
))}
{i === 0 && (
<span className="inline-block text-[9px] sm:text-[10px] font-medium text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/20 px-1.5 py-0.5 rounded">
</span>
)}
</div>
<span className="text-[10px] sm:text-xs text-amber-600 dark:text-amber-400/90">
{ACTIVITY_TYPES[s.type]} · {s.city}
</span>
<h3 className="font-semibold text-stone-800 dark:text-stone-100 text-sm sm:text-base group-hover:text-amber-700 dark:group-hover:text-amber-400 mt-0.5">
{s.title}
</h3>
<p className="text-xs sm:text-sm text-stone-500 dark:text-stone-400 mt-0.5">
{s.date} {s.time} · {s.place}
</p>
<span className="inline-flex items-center gap-1 mt-2 sm:mt-3 text-amber-600 dark:text-amber-400 text-xs sm:text-sm font-medium">
</span>
</div>
</Link>
))}
</div>
</section>
{/* 为什么来 */}
<section>
<h2 className="text-lg sm:text-xl font-semibold text-stone-800 dark:text-stone-100 mb-4 sm:mb-5 flex items-center gap-2">
<span>💡</span>
</h2>
<div className="rounded-xl sm:rounded-2xl bg-white dark:bg-stone-900/80 border border-stone-200/80 dark:border-stone-700/80 p-4 sm:p-6 md:p-8">
<div className="grid sm:grid-cols-2 gap-4 sm:gap-6">
{[
{ icon: "😌", title: "氛围轻松", desc: "咖啡馆、书店里的线下小聚,不用尬聊,聊得来就多聊几句。" },
{ icon: "🛡️", title: "安全靠谱", desc: "公开场地,地址提前告知。尊重边界,不追问隐私。" },
{ icon: "👍", title: "第一次来也 OK", desc: "很多人都是第一次参加,小组活动人数可控,不会尴尬。" },
{ icon: "✍️", title: "填表就行", desc: "无需注册登录,不用先付款,填个表单即可。" },
].map((item) => (
<div key={item.title} className="flex gap-2.5 sm:gap-3">
<span className="text-xl sm:text-2xl shrink-0">{item.icon}</span>
<div>
<p className="font-medium text-stone-800 dark:text-stone-100 text-sm sm:text-base">{item.title}</p>
<p className="text-xs sm:text-sm text-stone-500 dark:text-stone-400 mt-0.5 leading-relaxed">{item.desc}</p>
</div>
</div>
))}
</div>
</div>
</section>
{/* FAQ */}
<section id="faq">
<h2 className="text-lg sm:text-xl font-semibold text-stone-800 dark:text-stone-100 mb-4 sm:mb-5 flex items-center gap-2">
<span></span>
</h2>
<div className="space-y-2 sm:space-y-3">
{[
{ q: "提交后多久会收到确认?", a: "活动前 12 天根据场次与匹配度联系,通过微信/短信确认。不匹配不会反复打扰。", icon: "⏱️" },
{ q: "第一次参加可以吗?", a: "可以很多人都是第一次来。68 人小组、公开场地,聊得来就多聊几句。", icon: "✨" },
{ q: "临时有事怎么办?", a: "随时可退出,提前告知即可。", icon: "🔄" },
].map((faq) => (
<details
key={faq.q}
className="group rounded-lg sm:rounded-xl bg-white dark:bg-stone-900/80 border border-stone-200/80 dark:border-stone-700/80 overflow-hidden"
>
<summary className="flex items-center gap-2.5 sm:gap-3 p-3 sm:p-4 cursor-pointer list-none [&::-webkit-details-marker]:hidden select-none">
<span className="text-base sm:text-lg shrink-0">{faq.icon}</span>
<p className="font-medium text-stone-800 dark:text-stone-100 text-xs sm:text-sm flex-1">{faq.q}</p>
<span className="shrink-0 text-stone-400 text-xs transition-transform duration-200 group-open:rotate-180"></span>
</summary>
<div className="px-3 pb-3 sm:px-4 sm:pb-4 pt-0 flex gap-2.5 sm:gap-3">
<span className="w-[1.25rem] sm:w-[1.5rem] shrink-0" aria-hidden />
<p className="text-xs sm:text-sm text-stone-500 dark:text-stone-400 leading-relaxed">{faq.a}</p>
</div>
</details>
))}
</div>
</section>
{/* CTA */}
<section className="pt-2 sm:pt-4">
<Link
href="/join"
className="block w-full bg-amber-600 hover:bg-amber-700 text-white text-center py-3.5 sm:py-4 rounded-xl font-semibold text-sm sm:text-base shadow-lg shadow-amber-900/20 transition-all"
>
</Link>
<p className="mt-3 text-center text-xs sm:text-sm text-stone-500 dark:text-stone-400">
·
</p>
</section>
</main>
{/* 移动端悬浮 CTA */}
<div className="fixed bottom-0 left-0 right-0 p-3 sm:p-4 bg-white/95 dark:bg-stone-900/95 backdrop-blur border-t border-stone-200 dark:border-stone-800 sm:hidden z-50 safe-area-pb">
<Link
href="/join"
className="block w-full bg-amber-600 hover:bg-amber-700 text-white text-center py-3 rounded-xl font-medium text-sm"
>
</Link>
</div>
<Footer />
</div>
);
}