281 lines
10 KiB
TypeScript
281 lines
10 KiB
TypeScript
"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>
|
||
);
|
||
}
|