This commit is contained in:
eric
2026-03-07 12:33:14 -06:00
parent 8b034e255b
commit 9bb8bcdf0b
28 changed files with 7231 additions and 78 deletions

280
app/join/page.tsx Normal file
View File

@@ -0,0 +1,280 @@
"use client";
import { useState } from "react";
type FormState = {
nickname: string;
gender: string;
city: string;
occupation: string;
education: string;
wechat: string;
phone: string;
intro: string;
};
const OCCUPATIONS = [
"自由职业者",
"远程工程师",
"设计师",
"内容创作者",
"创业者",
"其他",
] as const;
const EDUCATIONS = ["高中", "大专", "本科", "硕士", "博士"] as const;
const initialForm: FormState = {
nickname: "",
gender: "",
city: "",
occupation: "",
education: "",
wechat: "",
phone: "",
intro: "",
};
export default function JoinPage() {
const [form, setForm] = useState<FormState>(initialForm);
const updateField = (field: keyof FormState, value: string) => {
setForm((prev) => ({ ...prev, [field]: value }));
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!form.nickname.trim()) {
alert("请填写昵称");
return;
}
if (!form.wechat.trim()) {
alert("请填写微信号");
return;
}
alert("提交成功!我们将通过微信联系你。");
setForm(initialForm);
};
return (
<div className="min-h-screen bg-[#fafafa]">
{/* Top Section: Gradient Hero */}
<section className="relative overflow-hidden bg-gradient-to-br from-orange-400 via-orange-500 to-rose-500 px-4 pt-12 pb-16 sm:pt-16 sm:pb-20">
<div className="mx-auto max-w-2xl text-center">
<h1 className="text-3xl font-bold tracking-tight text-white drop-shadow-sm sm:text-4xl md:text-5xl">
</h1>
<p className="mt-3 text-base text-white/95 sm:text-lg md:text-xl">
</p>
</div>
</section>
{/* Form Card */}
<section className="relative z-10 mx-auto -mt-8 max-w-lg px-4 pb-12 sm:-mt-10 sm:px-6">
<div className="rounded-2xl bg-white p-6 shadow-lg sm:p-8">
<form onSubmit={handleSubmit} className="space-y-5">
{/* 昵称 */}
<div>
<label
htmlFor="nickname"
className="mb-1.5 block text-sm font-medium text-gray-700"
>
<span className="text-[#ff4d4f]">*</span>
</label>
<input
id="nickname"
type="text"
value={form.nickname}
onChange={(e) => updateField("nickname", e.target.value)}
required
placeholder="请输入你的昵称"
className="w-full rounded-xl border border-gray-200 px-4 py-3 text-gray-900 placeholder-gray-400 transition-colors focus:border-[#ff4d4f] focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20"
/>
</div>
{/* 性别 */}
<div>
<label className="mb-2 block text-sm font-medium text-gray-700">
</label>
<div className="flex gap-6">
{["男", "女", "其他"].map((g) => (
<label
key={g}
className="flex cursor-pointer items-center gap-2"
>
<input
type="radio"
name="gender"
value={g}
checked={form.gender === g}
onChange={(e) => updateField("gender", e.target.value)}
className="h-4 w-4 border-gray-300 text-[#ff4d4f] focus:ring-[#ff4d4f]/20"
/>
<span className="text-sm text-gray-700">{g}</span>
</label>
))}
</div>
</div>
{/* 当前所在城市 */}
<div>
<label
htmlFor="city"
className="mb-1.5 block text-sm font-medium text-gray-700"
>
</label>
<input
id="city"
type="text"
value={form.city}
onChange={(e) => updateField("city", e.target.value)}
placeholder="如:清迈、曼谷、大理"
className="w-full rounded-xl border border-gray-200 px-4 py-3 text-gray-900 placeholder-gray-400 transition-colors focus:border-[#ff4d4f] focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20"
/>
</div>
{/* 职业 */}
<div>
<label
htmlFor="occupation"
className="mb-1.5 block text-sm font-medium text-gray-700"
>
</label>
<select
id="occupation"
value={form.occupation}
onChange={(e) => updateField("occupation", e.target.value)}
className="w-full rounded-xl border border-gray-200 px-4 py-3 text-gray-900 transition-colors focus:border-[#ff4d4f] focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20"
>
<option value=""></option>
{OCCUPATIONS.map((o) => (
<option key={o} value={o}>
{o}
</option>
))}
</select>
</div>
{/* 学历 */}
<div>
<label
htmlFor="education"
className="mb-1.5 block text-sm font-medium text-gray-700"
>
</label>
<select
id="education"
value={form.education}
onChange={(e) => updateField("education", e.target.value)}
className="w-full rounded-xl border border-gray-200 px-4 py-3 text-gray-900 transition-colors focus:border-[#ff4d4f] focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20"
>
<option value=""></option>
{EDUCATIONS.map((e) => (
<option key={e} value={e}>
{e}
</option>
))}
</select>
</div>
{/* 微信号 */}
<div>
<label
htmlFor="wechat"
className="mb-1.5 block text-sm font-medium text-gray-700"
>
<span className="text-[#ff4d4f]">*</span>
</label>
<input
id="wechat"
type="text"
value={form.wechat}
onChange={(e) => updateField("wechat", e.target.value)}
required
placeholder="用于联系你加入社群"
className="w-full rounded-xl border border-gray-200 px-4 py-3 text-gray-900 placeholder-gray-400 transition-colors focus:border-[#ff4d4f] focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20"
/>
</div>
{/* 手机号 */}
<div>
<label
htmlFor="phone"
className="mb-1.5 block text-sm font-medium text-gray-700"
>
</label>
<div className="flex rounded-xl border border-gray-200 bg-white transition-colors focus-within:border-[#ff4d4f] focus-within:ring-2 focus-within:ring-[#ff4d4f]/20">
<span className="flex items-center border-r border-gray-200 px-4 py-3 text-sm text-gray-500">
+86
</span>
<input
id="phone"
type="tel"
value={form.phone}
onChange={(e) => updateField("phone", e.target.value)}
placeholder="选填"
className="flex-1 rounded-r-xl border-0 px-4 py-3 text-gray-900 placeholder-gray-400 focus:ring-0"
/>
</div>
</div>
{/* 简单介绍自己 */}
<div>
<label
htmlFor="intro"
className="mb-1.5 block text-sm font-medium text-gray-700"
>
</label>
<textarea
id="intro"
rows={3}
value={form.intro}
onChange={(e) => updateField("intro", e.target.value)}
placeholder="简单介绍一下你的背景、兴趣或加入原因..."
className="w-full resize-none rounded-xl border border-gray-200 px-4 py-3 text-gray-900 placeholder-gray-400 transition-colors focus:border-[#ff4d4f] focus:outline-none focus:ring-2 focus:ring-[#ff4d4f]/20"
/>
</div>
{/* Submit */}
<div className="pt-2">
<button
type="submit"
className="w-full rounded-xl bg-[#ff4d4f] px-4 py-3.5 font-semibold text-white transition-colors hover:bg-[#e64547] active:bg-[#cc3d3f]"
>
</button>
<p className="mt-3 text-center text-xs text-gray-500">
24
</p>
</div>
</form>
</div>
</section>
{/* Bottom: Trust Indicators */}
<section className="border-t border-gray-200 bg-white px-4 py-10">
<div className="mx-auto flex max-w-lg flex-wrap items-center justify-center gap-8 sm:gap-12">
<div className="flex items-center gap-2">
<span className="text-2xl font-bold text-gray-900">2,860+</span>
<span className="text-sm text-gray-600"></span>
</div>
<div className="flex items-center gap-2">
<span className="text-2xl font-bold text-gray-900">30+</span>
<span className="text-sm text-gray-600"></span>
</div>
<div className="flex items-center gap-2">
<span className="text-2xl font-bold text-gray-900"> 8+</span>
<span className="text-sm text-gray-600"></span>
</div>
</div>
</section>
</div>
);
}