volsu-contests/frontend/src/app/page.tsx

416 lines
18 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 Link from "next/link";
import { motion } from "framer-motion";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { useAuth } from "@/lib/auth-context";
import {
Trophy,
Zap,
Code2,
Users,
ArrowRight,
Terminal,
Timer,
BarChart3,
Cpu,
Shield,
Sparkles,
} from "lucide-react";
import { CyberBrandText, VolguLogo } from "@/components/VolguLogo";
import { GlowOrbs, GlitchText, CornerBrackets, TypewriterText } from "@/components/decorative";
import { HeroIllustration } from "@/components/illustrations";
import { MatrixRain } from "@/components/effects";
const features = [
{
icon: Trophy,
title: "Соревнования",
description: "Участвуйте в контестах и соревнуйтесь с другими программистами",
color: "var(--color-neon-green)",
},
{
icon: Zap,
title: "Автопроверка",
description: "Мгновенная проверка решений с детальными результатами по каждому тесту",
color: "var(--color-neon-cyan)",
},
{
icon: Code2,
title: "30+ языков",
description: "Python, C++, Java, JavaScript, Go, Rust и многие другие языки",
color: "var(--color-neon-purple)",
},
{
icon: Timer,
title: "Real-time таймеры",
description: "Следите за временем контеста и оставшимся временем в реальном времени",
color: "var(--color-neon-orange)",
},
{
icon: BarChart3,
title: "Рейтинг",
description: "Отслеживайте свой прогресс и соревнуйтесь в таблице лидеров",
color: "var(--color-neon-pink)",
},
{
icon: Terminal,
title: "Удобный редактор",
description: "Современный редактор кода с подсветкой синтаксиса и автодополнением",
color: "var(--color-neon-yellow)",
},
];
const stats = [
{ value: "30+", label: "Языков", color: "var(--color-neon-green)" },
{ value: "∞", label: "Контестов", color: "var(--color-neon-cyan)" },
{ value: "100%", label: "Автопроверка", color: "var(--color-neon-purple)" },
{ value: "24/7", label: "Доступность", color: "var(--color-neon-pink)" },
];
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.1,
},
},
};
const itemVariants = {
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 },
};
export default function HomePage() {
const { user } = useAuth();
return (
<div className="min-h-[calc(100vh-4rem)] relative">
{/* Hero Section */}
<section className="relative overflow-hidden min-h-[90vh] flex items-center">
{/* Background Effects */}
<div className="absolute inset-0 overflow-hidden">
<MatrixRain density="light" color="green" speed="slow" />
</div>
<GlowOrbs />
{/* Cyber grid overlay */}
<div className="absolute inset-0 cyber-grid opacity-30" />
{/* Scanline effect */}
<div className="absolute inset-0 pointer-events-none overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-[var(--color-neon-green)]/[0.02] to-transparent animate-scanline" />
</div>
<div className="container mx-auto px-4 py-16 relative z-10">
<div className="grid lg:grid-cols-2 gap-12 items-center">
{/* Left column - Text content */}
<motion.div
initial={{ opacity: 0, x: -30 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6 }}
>
{/* University badge */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.2 }}
className="inline-flex items-center gap-3 px-4 py-2 rounded-lg bg-[var(--color-card)] border border-[var(--color-neon-green)]/30 mb-8"
>
<VolguLogo className="h-5 w-5" animated />
<span className="text-sm font-mono text-[var(--color-neon-green)]">
<TypewriterText text="Волгоградский государственный университет" speed={30} />
</span>
</motion.div>
{/* Main heading */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
className="mb-6"
>
<GlitchText
text=">VOLSU.CONTESTS"
className="text-4xl md:text-5xl lg:text-6xl font-display font-bold"
/>
</motion.div>
{/* Subtitle with terminal style */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4 }}
className="mb-8"
>
<p className="text-lg md:text-xl text-muted-foreground font-mono leading-relaxed">
<span className="text-[var(--color-neon-cyan)]">$</span> Платформа для проведения соревнований по{" "}
<span className="text-[var(--color-neon-green)] text-glow-green">
олимпиадному программированию
</span>
</p>
<p className="text-muted-foreground font-mono mt-2 flex items-center gap-2">
<span className="text-[var(--color-neon-purple)]">&gt;</span>
<span className="animate-blink-cursor">_</span>
</p>
</motion.div>
{/* CTA Buttons */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.5 }}
className="flex flex-col sm:flex-row gap-4"
>
<Button asChild variant="cyber" size="lg" className="group">
<Link href="/contests">
<Trophy className="h-5 w-5 mr-2" />
Перейти к контестам
<ArrowRight className="h-5 w-5 ml-2 transition-transform group-hover:translate-x-1" />
</Link>
</Button>
{!user && (
<Button asChild variant="neon" size="lg">
<Link href="/register">
<Users className="h-5 w-5 mr-2" />
Создать аккаунт
</Link>
</Button>
)}
</motion.div>
{/* Stats */}
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.7 }}
className="mt-12 grid grid-cols-2 md:grid-cols-4 gap-6"
>
{stats.map((stat, index) => (
<div key={index} className="relative group">
<CornerBrackets color={stat.color} size="sm" />
<div className="text-center py-4">
<div
className="text-2xl md:text-3xl font-display font-bold mb-1"
style={{ color: stat.color, textShadow: `0 0 20px ${stat.color}` }}
>
{stat.value}
</div>
<div className="text-xs font-mono text-muted-foreground uppercase tracking-wider">
{stat.label}
</div>
</div>
</div>
))}
</motion.div>
</motion.div>
{/* Right column - Illustration */}
<motion.div
initial={{ opacity: 0, x: 30 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6, delay: 0.3 }}
className="hidden lg:flex justify-center items-center"
>
<HeroIllustration className="w-full max-w-lg" />
</motion.div>
</div>
</div>
{/* Bottom gradient fade */}
<div className="absolute bottom-0 left-0 right-0 h-32 bg-gradient-to-t from-[var(--color-background)] to-transparent" />
</section>
{/* Features Section */}
<section className="py-24 relative">
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-[var(--color-neon-purple)]/5 to-transparent" />
<div className="container mx-auto px-4 relative">
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
className="text-center mb-16"
>
<Badge variant="cyan" className="mb-4 font-mono">
<Cpu className="h-3 w-3 mr-1" />
SYSTEM.FEATURES
</Badge>
<h2 className="text-3xl md:text-4xl font-display font-bold mb-4">
<span className="text-[var(--color-neon-green)]">&lt;</span>
Возможности платформы
<span className="text-[var(--color-neon-green)]">/&gt;</span>
</h2>
<p className="text-lg text-muted-foreground font-mono max-w-2xl mx-auto">
Все необходимые инструменты для проведения и участия в соревнованиях
</p>
</motion.div>
<motion.div
variants={containerVariants}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
className="grid md:grid-cols-2 lg:grid-cols-3 gap-6"
>
{features.map((feature, index) => {
const Icon = feature.icon;
return (
<motion.div key={index} variants={itemVariants}>
<Card variant="cyber" className="h-full group hover:border-[var(--color-neon-green)]/50 transition-all duration-300">
<CardContent className="pt-6 relative">
{/* Icon with glow */}
<div
className="w-14 h-14 rounded-lg flex items-center justify-center mb-4 transition-all duration-300 group-hover:scale-110"
style={{
backgroundColor: `color-mix(in srgb, ${feature.color} 15%, transparent)`,
border: `1px solid ${feature.color}40`,
boxShadow: `0 0 20px ${feature.color}20`
}}
>
<Icon
className="h-7 w-7 transition-all duration-300"
style={{ color: feature.color }}
/>
</div>
{/* Title */}
<h3
className="text-lg font-display font-semibold mb-2 transition-colors duration-300"
style={{ color: feature.color }}
>
{feature.title}
</h3>
{/* Description */}
<p className="text-muted-foreground font-mono text-sm leading-relaxed">
{feature.description}
</p>
{/* Hover effect line */}
<div
className="absolute bottom-0 left-0 right-0 h-[2px] opacity-0 group-hover:opacity-100 transition-opacity duration-300"
style={{
background: `linear-gradient(90deg, transparent, ${feature.color}, transparent)`,
boxShadow: `0 0 10px ${feature.color}`
}}
/>
</CardContent>
</Card>
</motion.div>
);
})}
</motion.div>
</div>
</section>
{/* CTA Section */}
<section className="py-24 relative">
<div className="container mx-auto px-4">
<motion.div
initial={{ opacity: 0, scale: 0.95 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
className="relative overflow-hidden rounded-2xl"
>
{/* Background with cyber styling */}
<div className="absolute inset-0 bg-gradient-to-r from-[var(--color-neon-green)]/10 via-[var(--color-neon-cyan)]/10 to-[var(--color-neon-purple)]/10" />
<div className="absolute inset-0 cyber-grid opacity-20" />
{/* Border glow */}
<div className="absolute inset-0 rounded-2xl border border-[var(--color-neon-green)]/30" />
<div className="absolute inset-[1px] rounded-2xl border border-[var(--color-neon-cyan)]/20" />
{/* Animated corner accents */}
<div className="absolute top-0 left-0 w-20 h-20">
<div className="absolute top-0 left-0 w-full h-[2px] bg-gradient-to-r from-[var(--color-neon-green)] to-transparent" />
<div className="absolute top-0 left-0 h-full w-[2px] bg-gradient-to-b from-[var(--color-neon-green)] to-transparent" />
</div>
<div className="absolute top-0 right-0 w-20 h-20">
<div className="absolute top-0 right-0 w-full h-[2px] bg-gradient-to-l from-[var(--color-neon-cyan)] to-transparent" />
<div className="absolute top-0 right-0 h-full w-[2px] bg-gradient-to-b from-[var(--color-neon-cyan)] to-transparent" />
</div>
<div className="absolute bottom-0 left-0 w-20 h-20">
<div className="absolute bottom-0 left-0 w-full h-[2px] bg-gradient-to-r from-[var(--color-neon-purple)] to-transparent" />
<div className="absolute bottom-0 left-0 h-full w-[2px] bg-gradient-to-t from-[var(--color-neon-purple)] to-transparent" />
</div>
<div className="absolute bottom-0 right-0 w-20 h-20">
<div className="absolute bottom-0 right-0 w-full h-[2px] bg-gradient-to-l from-[var(--color-neon-pink)] to-transparent" />
<div className="absolute bottom-0 right-0 h-full w-[2px] bg-gradient-to-t from-[var(--color-neon-pink)] to-transparent" />
</div>
{/* Content */}
<div className="relative p-12 text-center">
<motion.div
animate={{
boxShadow: [
"0 0 20px var(--color-neon-green)",
"0 0 40px var(--color-neon-green)",
"0 0 20px var(--color-neon-green)"
]
}}
transition={{ duration: 2, repeat: Infinity }}
className="w-16 h-16 mx-auto mb-6 rounded-full border-2 border-[var(--color-neon-green)] flex items-center justify-center"
>
<Sparkles className="h-8 w-8 text-[var(--color-neon-green)]" />
</motion.div>
<h2 className="text-3xl md:text-4xl font-display font-bold mb-4">
<span className="text-[var(--color-neon-green)]">Готовы</span>{" "}
<span className="text-foreground">начать</span>
<span className="text-[var(--color-neon-cyan)]">?</span>
</h2>
<p className="text-lg text-muted-foreground font-mono mb-8 max-w-xl mx-auto">
Присоединяйтесь к платформе{" "}
<span className="text-[var(--color-neon-green)]">&gt;VOLSU.CONTESTS</span>{" "}
и участвуйте в соревнованиях
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Button asChild variant="cyber" size="lg" className="group">
<Link href={user ? "/contests" : "/register"}>
<Shield className="h-5 w-5 mr-2" />
{user ? "Перейти к контестам" : "Начать сейчас"}
<ArrowRight className="h-5 w-5 ml-2 transition-transform group-hover:translate-x-1" />
</Link>
</Button>
</div>
</div>
</motion.div>
</div>
</section>
{/* Footer */}
<footer className="relative border-t border-[var(--color-border)] py-8">
{/* Top border glow */}
<div className="absolute top-0 left-0 right-0 h-[1px] bg-gradient-to-r from-transparent via-[var(--color-neon-green)]/30 to-transparent" />
<div className="container mx-auto px-4">
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
<div className="flex items-center gap-3">
<VolguLogo className="h-6 w-6" />
<CyberBrandText className="text-sm" />
</div>
<p className="text-sm text-muted-foreground font-mono text-center">
<span className="text-[var(--color-neon-green)]">&copy;</span> {new Date().getFullYear()}{" "}
<span className="text-muted-foreground"></span>{" "}
Волгоградский государственный университет
</p>
<div className="flex items-center gap-2 text-xs font-mono text-muted-foreground">
<span className="inline-block w-2 h-2 rounded-full bg-[var(--color-neon-green)] animate-pulse" />
<span>SYSTEM.ONLINE</span>
</div>
</div>
</div>
</footer>
</div>
);
}