POL-125: Frontend visual upgrade — dark luxury pole dance theme

- New dark theme with rose/purple/gold accent palette
- Premium typography: Cormorant Garamond (display) + Outfit (body)
- Glassmorphism cards, gradient mesh backgrounds, glow effects
- CSS split into theme.css, utilities.css, animations.css
- Staggered fade-in animations on list pages
- Redesigned all pages: auth, championships, registrations, profile, admin
- Lucide icons replace emoji throughout
- Responsive mobile nav with hamburger menu

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dianaka123
2026-02-27 13:56:45 +03:00
parent cf4104069e
commit 6fbd0326fa
24 changed files with 882 additions and 342 deletions

View File

@@ -1,7 +1,38 @@
export default function AuthLayout({ children }: { children: React.ReactNode }) {
return (
<div className="flex min-h-screen items-center justify-center bg-gradient-to-br from-violet-50 to-purple-100 p-4">
<div className="w-full max-w-md">{children}</div>
<div className="relative flex min-h-screen items-center justify-center overflow-hidden p-4">
{/* Gradient mesh background */}
<div className="fixed inset-0 bg-background bg-mesh-strong" />
{/* Decorative flowing lines — pole dance silhouette abstraction */}
<svg
className="fixed inset-0 h-full w-full opacity-[0.04]"
viewBox="0 0 1200 800"
fill="none"
preserveAspectRatio="xMidYMid slice"
>
<path
d="M-100,400 C100,200 300,600 500,350 C700,100 900,500 1100,300 C1300,100 1400,400 1400,400"
stroke="url(#line-grad)"
strokeWidth="2"
strokeLinecap="round"
/>
<path
d="M-100,500 C200,300 400,700 600,450 C800,200 1000,600 1300,350"
stroke="url(#line-grad)"
strokeWidth="1.5"
strokeLinecap="round"
/>
<defs>
<linearGradient id="line-grad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#E91E63" />
<stop offset="50%" stopColor="#9C27B0" />
<stop offset="100%" stopColor="#D4A843" />
</linearGradient>
</defs>
</svg>
<div className="relative z-10 w-full max-w-md animate-fade-in-up">{children}</div>
</div>
);
}

View File

@@ -1,6 +1,7 @@
"use client";
import Link from "next/link";
import { Eye, EyeOff } from "lucide-react";
import { useLoginForm } from "@/hooks/useAuthForms";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
@@ -8,37 +9,77 @@ import { Label } from "@/components/ui/label";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
export default function LoginPage() {
const { email, setEmail, password, setPassword, error, isLoading, submit } = useLoginForm();
const { email, setEmail, password, setPassword, showPassword, setShowPassword, error, isLoading, submit } = useLoginForm();
return (
<Card>
<CardHeader className="text-center">
<div className="mx-auto mb-2 text-4xl">🏆</div>
<CardTitle className="text-2xl">Welcome back</CardTitle>
<CardDescription>Sign in to your account</CardDescription>
<Card className="glass-strong glow-rose overflow-hidden">
<CardHeader className="text-center pb-2">
<div className="mx-auto mb-4 h-px w-16 bg-gradient-to-r from-transparent via-rose-accent to-transparent" />
<CardTitle className="font-display text-3xl font-semibold tracking-wide">
Welcome back
</CardTitle>
<CardDescription className="text-muted-foreground">
Sign in to your account
</CardDescription>
</CardHeader>
<form onSubmit={submit}>
<CardContent className="space-y-4">
{error && <p className="rounded-md bg-red-50 px-3 py-2 text-sm text-red-600">{error}</p>}
{error && (
<p className="rounded-lg bg-destructive/10 border border-destructive/20 px-3 py-2 text-sm text-destructive">
{error}
</p>
)}
<div className="space-y-1">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" value={email} onChange={(e) => setEmail(e.target.value)} required />
<div className="space-y-2">
<Label htmlFor="email" className="text-xs uppercase tracking-widest text-dim">
Email
</Label>
<Input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
className="bg-surface border-border/60 focus:border-rose-accent focus:ring-rose-accent/30 placeholder:text-dim"
placeholder="your@email.com"
/>
</div>
<div className="space-y-1">
<Label htmlFor="password">Password</Label>
<Input id="password" type="password" value={password} onChange={(e) => setPassword(e.target.value)} required />
<div className="space-y-2">
<Label htmlFor="password" className="text-xs uppercase tracking-widest text-dim">
Password
</Label>
<div className="relative">
<Input
id="password"
type={showPassword ? "text" : "password"}
value={password}
onChange={(e) => setPassword(e.target.value)}
required
className="bg-surface border-border/60 pr-10 focus:border-rose-accent focus:ring-rose-accent/30"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 -translate-y-1/2 text-dim hover:text-foreground transition-colors"
>
{showPassword ? <EyeOff size={16} /> : <Eye size={16} />}
</button>
</div>
</div>
</CardContent>
<CardFooter className="flex flex-col gap-3">
<Button type="submit" className="w-full bg-violet-600 hover:bg-violet-700" disabled={isLoading}>
<CardFooter className="flex flex-col gap-4 pt-2">
<Button
type="submit"
className="w-full bg-rose-accent hover:bg-rose-accent/90 text-white font-medium tracking-wide"
disabled={isLoading}
>
{isLoading ? "Signing in…" : "Sign in"}
</Button>
<p className="text-center text-sm text-gray-500">
<p className="text-center text-sm text-muted-foreground">
No account?{" "}
<Link href="/register" className="font-medium text-violet-600 hover:underline">
<Link href="/register" className="font-medium text-rose-accent hover:text-rose-accent/80 transition-colors">
Register
</Link>
</p>

View File

@@ -1,22 +1,27 @@
import Link from "next/link";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Clock } from "lucide-react";
export default function PendingPage() {
return (
<Card className="text-center">
<Card className="glass-strong glow-purple text-center overflow-hidden">
<CardHeader>
<div className="mx-auto mb-2 text-5xl"></div>
<CardTitle className="text-2xl">Awaiting approval</CardTitle>
<CardDescription>
<div className="mx-auto mb-3 flex h-14 w-14 items-center justify-center rounded-full bg-purple-accent/10 border border-purple-accent/20">
<Clock className="h-7 w-7 text-purple-accent" />
</div>
<CardTitle className="font-display text-3xl font-semibold tracking-wide">
Awaiting approval
</CardTitle>
<CardDescription className="text-muted-foreground">
Your organizer account has been submitted. An admin will review it shortly.
</CardDescription>
</CardHeader>
<CardContent>
<p className="mb-6 text-sm text-gray-500">
<p className="mb-6 text-sm text-dim">
Once approved you can log in and start creating championships.
</p>
<Button asChild variant="outline" className="w-full">
<Button asChild variant="outline" className="w-full border-border/60 hover:bg-surface-hover">
<Link href="/login">Back to login</Link>
</Button>
</CardContent>

View File

@@ -11,16 +11,24 @@ export default function RegisterPage() {
const { role, setRole, form, update, error, isLoading, submit } = useRegisterForm();
return (
<Card>
<CardHeader className="text-center">
<div className="mx-auto mb-2 text-4xl">🏅</div>
<CardTitle className="text-2xl">Create account</CardTitle>
<CardDescription>Join the pole dance community</CardDescription>
<Card className="glass-strong glow-rose overflow-hidden">
<CardHeader className="text-center pb-2">
<div className="mx-auto mb-4 h-px w-16 bg-gradient-to-r from-transparent via-purple-accent to-transparent" />
<CardTitle className="font-display text-3xl font-semibold tracking-wide">
Create account
</CardTitle>
<CardDescription className="text-muted-foreground">
Join the pole dance community
</CardDescription>
</CardHeader>
<form onSubmit={submit}>
<CardContent className="space-y-4">
{error && <p className="rounded-md bg-red-50 px-3 py-2 text-sm text-red-600">{error}</p>}
{error && (
<p className="rounded-lg bg-destructive/10 border border-destructive/20 px-3 py-2 text-sm text-destructive">
{error}
</p>
)}
<div className="grid grid-cols-2 gap-2">
{(["member", "organizer"] as const).map((r) => (
@@ -28,11 +36,13 @@ export default function RegisterPage() {
key={r}
type="button"
onClick={() => setRole(r)}
className={`rounded-lg border-2 p-3 text-sm font-medium transition-colors ${
role === r ? "border-violet-600 bg-violet-50 text-violet-700" : "border-gray-200 text-gray-600 hover:border-gray-300"
className={`rounded-xl border-2 p-3 text-sm font-medium transition-all duration-200 ${
role === r
? "border-rose-accent bg-rose-accent/10 text-foreground glow-rose"
: "border-border/40 text-muted-foreground hover:border-border hover:text-foreground"
}`}
>
{r === "member" ? "🏅 Athlete" : "🏆 Organizer"}
{r === "member" ? "Athlete" : "Organizer"}
</button>
))}
</div>
@@ -54,13 +64,17 @@ export default function RegisterPage() {
)}
</CardContent>
<CardFooter className="flex flex-col gap-3">
<Button type="submit" className="w-full bg-violet-600 hover:bg-violet-700" disabled={isLoading}>
<CardFooter className="flex flex-col gap-4 pt-2">
<Button
type="submit"
className="w-full bg-rose-accent hover:bg-rose-accent/90 text-white font-medium tracking-wide"
disabled={isLoading}
>
{isLoading ? "Creating…" : role === "member" ? "Create account" : "Submit for approval"}
</Button>
<p className="text-center text-sm text-gray-500">
<p className="text-center text-sm text-muted-foreground">
Have an account?{" "}
<Link href="/login" className="font-medium text-violet-600 hover:underline">
<Link href="/login" className="font-medium text-rose-accent hover:text-rose-accent/80 transition-colors">
Sign in
</Link>
</p>