-
-
+
+ {(["pending", "all"] as const).map((f) => (
+
+ ))}
{shown.length === 0 ? (
-
No users in this category.
+
+
+
+
+
No users in this category.
+
) : (
- {shown.map((u) => (
-
approve.mutate(id)}
- onReject={(id) => reject.mutate(id)}
- isActing={approve.isPending || reject.isPending}
- />
+ {shown.map((u, i) => (
+
+ approve.mutate(id)}
+ onReject={(id) => reject.mutate(id)}
+ isActing={approve.isPending || reject.isPending}
+ />
+
))}
)}
diff --git a/web/src/app/(app)/championships/[id]/page.tsx b/web/src/app/(app)/championships/[id]/page.tsx
index 557eab2..d5ddaf9 100644
--- a/web/src/app/(app)/championships/[id]/page.tsx
+++ b/web/src/app/(app)/championships/[id]/page.tsx
@@ -4,22 +4,30 @@ import { use } from "react";
import { useChampionship } from "@/hooks/useChampionships";
import { useMyRegistrations } from "@/hooks/useRegistrations";
import { useRegisterForChampionship } from "@/hooks/useRegistrations";
-import { useAuth } from "@/hooks/useAuth";
import { RegistrationTimeline } from "@/components/registrations/RegistrationTimeline";
import { StatusBadge } from "@/components/shared/StatusBadge";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
+import { MapPin, Building2, Calendar, CreditCard, Film, ExternalLink } from "lucide-react";
export default function ChampionshipDetailPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = use(params);
- const user = useAuth((s) => s.user);
-
const { data: championship, isLoading, error } = useChampionship(id);
const { data: myRegs } = useMyRegistrations();
const registerMutation = useRegisterForChampionship(id);
- if (isLoading) return
Loadingβ¦
;
- if (error || !championship) return
Championship not found.
;
+ if (isLoading) {
+ return (
+
+ );
+ }
+
+ if (error || !championship) return
Championship not found.
;
const myReg = myRegs?.find((r) => r.championship_id === id);
const canRegister = championship.status === "open" && !myReg;
@@ -29,51 +37,77 @@ export default function ChampionshipDetailPage({ params }: { params: Promise<{ i
: null;
return (
-
+
{/* Header image */}
- {championship.image_url ? (
-

- ) : (
-
- π
-
- )}
+
+ {championship.image_url ? (
+

+ ) : (
+
+ π
+
+ )}
+
+
{/* Title + status */}
-
{championship.title}
- {championship.subtitle &&
{championship.subtitle}
}
+
{championship.title}
+ {championship.subtitle &&
{championship.subtitle}
}
- {/* Details */}
-
- {championship.location &&
π {championship.location}
}
- {championship.venue &&
π {championship.venue}
}
- {eventDate &&
π
{eventDate}
}
- {championship.entry_fee != null &&
π³ Entry fee: {championship.entry_fee} β½
}
+ {/* Details grid */}
+
+ {championship.location && (
+
+
+ {championship.location}
+
+ )}
+ {championship.venue && (
+
+
+ {championship.venue}
+
+ )}
+ {eventDate && (
+
+
+ {eventDate}
+
+ )}
+ {championship.entry_fee != null && (
+
+
+ Entry fee: {championship.entry_fee} β½
+
+ )}
{championship.video_max_duration != null && (
-
π¬ Max video: {Math.floor(championship.video_max_duration / 60)}m {championship.video_max_duration % 60}s
+
+
+ Max video: {Math.floor(championship.video_max_duration / 60)}m {championship.video_max_duration % 60}s
+
)}
{championship.description && (
<>
-
-
{championship.description}
+
+
{championship.description}
>
)}
-
+
{/* Registration section */}
{myReg &&
}
{canRegister && (
diff --git a/web/src/app/(app)/championships/page.tsx b/web/src/app/(app)/championships/page.tsx
index b325bcf..b41ccae 100644
--- a/web/src/app/(app)/championships/page.tsx
+++ b/web/src/app/(app)/championships/page.tsx
@@ -2,20 +2,46 @@
import { useChampionships } from "@/hooks/useChampionships";
import { ChampionshipCard } from "@/components/championships/ChampionshipCard";
+import { Trophy } from "lucide-react";
export default function ChampionshipsPage() {
const { data, isLoading, error } = useChampionships();
- if (isLoading) return
Loadingβ¦
;
- if (error) return
Failed to load championships.
;
- if (!data?.length) return
No championships yet.
;
+ if (isLoading) {
+ return (
+
+ );
+ }
+
+ if (error) return
Failed to load championships.
;
+
+ if (!data?.length) {
+ return (
+
+
+
+
+
No championships yet.
+
+ );
+ }
return (
-
-
Championships
-
- {data.map((c) => (
-
+
+
+
Championships
+
Browse upcoming competitions
+
+
+ {data.map((c, i) => (
+
+
+
))}
diff --git a/web/src/app/(app)/layout.tsx b/web/src/app/(app)/layout.tsx
index 6a727ed..067c0c5 100644
--- a/web/src/app/(app)/layout.tsx
+++ b/web/src/app/(app)/layout.tsx
@@ -2,9 +2,9 @@ import { Navbar } from "@/components/layout/Navbar";
export default function AppLayout({ children }: { children: React.ReactNode }) {
return (
- <>
+
{children}
- >
+
);
}
diff --git a/web/src/app/(app)/profile/page.tsx b/web/src/app/(app)/profile/page.tsx
index b68d96b..303aa8c 100644
--- a/web/src/app/(app)/profile/page.tsx
+++ b/web/src/app/(app)/profile/page.tsx
@@ -6,11 +6,12 @@ import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Separator } from "@/components/ui/separator";
+import { Phone, Building2, AtSign, CalendarDays, LogOut } from "lucide-react";
const ROLE_COLORS: Record
= {
- admin: "bg-red-100 text-red-700",
- organizer: "bg-violet-100 text-violet-700",
- member: "bg-green-100 text-green-700",
+ admin: "bg-destructive/15 text-destructive border-destructive/20",
+ organizer: "bg-purple-soft text-purple-accent border-purple-accent/20",
+ member: "bg-rose-soft text-rose-accent border-rose-accent/20",
};
export default function ProfilePage() {
@@ -29,52 +30,73 @@ export default function ProfilePage() {
}
return (
-
-
-
-
- {initials}
-
-
-
-
{user.full_name}
-
{user.email}
+
+
+ {/* Avatar with gradient ring */}
+
-
+
+
+
{user.full_name}
+
{user.email}
+
+
+
{user.role}
-
+
-
+
{user.phone && (
-
-
Phone
-
{user.phone}
+
+
+
+ Phone
+
+
{user.phone}
)}
{user.organization_name && (
-
-
Organization
-
{user.organization_name}
+
+
+
+ Organization
+
+ {user.organization_name}
)}
{user.instagram_handle && (
-
-
Instagram
-
{user.instagram_handle}
+
+
+
+ AtSign
+
+
{user.instagram_handle}
)}
-
-
Member since
-
{joinedDate}
+
+
+
+ Member since
+
+ {joinedDate}
-
-
-
diff --git a/web/src/app/(app)/registrations/page.tsx b/web/src/app/(app)/registrations/page.tsx
index 6f25d7b..c55efb1 100644
--- a/web/src/app/(app)/registrations/page.tsx
+++ b/web/src/app/(app)/registrations/page.tsx
@@ -2,25 +2,46 @@
import { useMyRegistrations } from "@/hooks/useRegistrations";
import { RegistrationCard } from "@/components/registrations/RegistrationCard";
+import { ListChecks } from "lucide-react";
export default function RegistrationsPage() {
const { data, isLoading, error } = useMyRegistrations();
- if (isLoading) return
Loadingβ¦
;
- if (error) return
Failed to load registrations.
;
- if (!data?.length) return (
-
-
π
-
No registrations yet.
-
- );
+ if (isLoading) {
+ return (
+
+ );
+ }
+
+ if (error) return
Failed to load registrations.
;
+
+ if (!data?.length) {
+ return (
+
+
+
+
+
No registrations yet.
+
+ );
+ }
return (
-
-
My Registrations
+
+
+
My Registrations
+
Track your championship progress
+
- {data.map((r) => (
-
+ {data.map((r, i) => (
+
+
+
))}
diff --git a/web/src/app/(auth)/layout.tsx b/web/src/app/(auth)/layout.tsx
index 980fa94..36f7a53 100644
--- a/web/src/app/(auth)/layout.tsx
+++ b/web/src/app/(auth)/layout.tsx
@@ -1,7 +1,38 @@
export default function AuthLayout({ children }: { children: React.ReactNode }) {
return (
-
-
{children}
+
+ {/* Gradient mesh background */}
+
+
+ {/* Decorative flowing lines β pole dance silhouette abstraction */}
+
+
+
{children}
);
}
diff --git a/web/src/app/(auth)/login/page.tsx b/web/src/app/(auth)/login/page.tsx
index 62fe7d7..04b41cd 100644
--- a/web/src/app/(auth)/login/page.tsx
+++ b/web/src/app/(auth)/login/page.tsx
@@ -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 (
-
-
- π
- Welcome back
- Sign in to your account
+
+
+
+
+ Welcome back
+
+
+ Sign in to your account
+