文件
tennis-training-hub/client/src/pages/Home.tsx
2026-03-14 21:50:09 +08:00

150 行
6.0 KiB
TypeScript

import { useAuth } from "@/_core/hooks/useAuth";
import { Button } from "@/components/ui/button";
import { useLocation, Redirect } from "wouter";
import {
Target, Video, Award, TrendingUp, Zap, Activity,
ChevronRight, Footprints, BarChart3
} from "lucide-react";
export default function Home() {
const { user, loading, isAuthenticated } = useAuth();
const [, setLocation] = useLocation();
if (loading) return null;
if (isAuthenticated) return <Redirect to="/dashboard" />;
return (
<div className="min-h-screen bg-gradient-to-b from-green-50 via-background to-emerald-50/30">
{/* Hero */}
<header className="container py-6 flex items-center justify-between">
<div className="flex items-center gap-2">
<Target className="h-6 w-6 text-primary" />
<span className="font-bold text-lg tracking-tight">Tennis Hub</span>
</div>
<Button onClick={() => setLocation("/login")} variant="default" size="sm">
使
</Button>
</header>
<section className="container py-16 md:py-24">
<div className="max-w-3xl mx-auto text-center">
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-primary/10 text-primary text-sm font-medium mb-6">
<Zap className="h-3.5 w-3.5" />
</div>
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold tracking-tight leading-tight">
<span className="text-primary block mt-1"></span>
</h1>
<p className="text-lg text-muted-foreground mt-6 max-w-xl mx-auto leading-relaxed">
· 姿 · ·
</p>
<div className="flex items-center justify-center gap-3 mt-8">
<Button onClick={() => setLocation("/login")} size="lg" className="gap-2 h-12 px-6">
<ChevronRight className="h-4 w-4" />
</Button>
</div>
</div>
</section>
{/* Features */}
<section className="container py-16">
<h2 className="text-2xl font-bold text-center mb-12"></h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-5xl mx-auto">
{[
{
icon: Video,
title: "姿势识别",
desc: "使用 MediaPipe 分析 33 个关键点并记录挥拍数据",
color: "bg-blue-50 text-blue-600",
},
{
icon: Target,
title: "训练计划",
desc: "根据水平和分析结果生成训练安排",
color: "bg-green-50 text-green-600",
},
{
icon: Award,
title: "NTRP自动评分",
desc: "按 USTA 维度记录评分结果",
color: "bg-purple-50 text-purple-600",
},
{
icon: Zap,
title: "击球统计",
desc: "记录击球次数、挥拍速度和一致性",
color: "bg-orange-50 text-orange-600",
},
{
icon: Footprints,
title: "运动轨迹",
desc: "记录重心移动轨迹和脚步变化",
color: "bg-teal-50 text-teal-600",
},
{
icon: TrendingUp,
title: "进度追踪",
desc: "查看训练历史、趋势和评分变化",
color: "bg-indigo-50 text-indigo-600",
},
].map((feature) => (
<div key={feature.title} className="p-6 rounded-2xl border bg-card hover:shadow-md transition-shadow">
<div className={`h-12 w-12 rounded-xl ${feature.color} flex items-center justify-center mb-4`}>
<feature.icon className="h-6 w-6" />
</div>
<h3 className="font-semibold text-base mb-2">{feature.title}</h3>
<p className="text-sm text-muted-foreground leading-relaxed">{feature.desc}</p>
</div>
))}
</div>
</section>
{/* How it works */}
<section className="container py-16">
<h2 className="text-2xl font-bold text-center mb-12">使</h2>
<div className="grid grid-cols-1 md:grid-cols-4 gap-6 max-w-4xl mx-auto">
{[
{ step: "1", title: "输入用户名", desc: "用户名登录即可" },
{ step: "2", title: "生成计划", desc: "生成训练安排" },
{ step: "3", title: "上传视频", desc: "录制挥拍并分析" },
{ step: "4", title: "获取反馈", desc: "评分与矫正建议" },
].map((item) => (
<div key={item.step} className="text-center">
<div className="h-12 w-12 rounded-full bg-primary text-primary-foreground flex items-center justify-center text-lg font-bold mx-auto mb-3">
{item.step}
</div>
<h3 className="font-semibold text-sm mb-1">{item.title}</h3>
<p className="text-xs text-muted-foreground">{item.desc}</p>
</div>
))}
</div>
</section>
{/* CTA */}
<section className="container py-16">
<div className="max-w-2xl mx-auto text-center p-8 rounded-2xl bg-primary/5">
<h2 className="text-2xl font-bold mb-3"></h2>
<p className="text-muted-foreground mb-6"></p>
<Button onClick={() => setLocation("/login")} size="lg" className="gap-2">
<ChevronRight className="h-4 w-4" />
</Button>
</div>
</section>
{/* Footer */}
<footer className="container py-8 border-t">
<div className="flex items-center justify-between text-xs text-muted-foreground">
<div className="flex items-center gap-2">
<Target className="h-4 w-4" />
<span>Tennis Hub</span>
</div>
<span></span>
</div>
</footer>
</div>
);
}