From 9597bfba4039ba6811fe12fd31392299d206886d Mon Sep 17 00:00:00 2001 From: Arpit Sarang Date: Sun, 12 Oct 2025 23:12:50 +0530 Subject: [PATCH] Add Loading States for Tournament Data in TournamentHub and TournamentBracketPage --- frontend/index.html | 2 +- frontend/src/Pages/TournamentBracketPage.tsx | 239 +++++++++++-------- frontend/src/Pages/TournamentHub.tsx | 45 +++- frontend/src/index.css | 24 +- 4 files changed, 210 insertions(+), 100 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index 423cb44..3e8831f 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -4,7 +4,7 @@ - Vite + React + TS + DebateAI diff --git a/frontend/src/Pages/TournamentBracketPage.tsx b/frontend/src/Pages/TournamentBracketPage.tsx index 2272323..ab6e005 100644 --- a/frontend/src/Pages/TournamentBracketPage.tsx +++ b/frontend/src/Pages/TournamentBracketPage.tsx @@ -1,104 +1,157 @@ +// TournamentBracketPage.tsx +import React, { useState, useEffect } from 'react'; + +interface Participant { + id: number; + name: string; + avatar: string; +} + export default function TournamentBracket() { - const participants = [ - { id: 1, name: "Rishit Tiwari", avatar: `https://i.pravatar.cc/32?u=1` }, - { id: 2, name: "Aarav Singh", avatar: `https://i.pravatar.cc/32?u=2` }, - { id: 3, name: "Ishaan Mehta", avatar: `https://i.pravatar.cc/32?u=3` }, - { id: 4, name: "Vihaan Kapoor", avatar: `https://i.pravatar.cc/32?u=4` }, - { id: 5, name: "Ayaan Khanna", avatar: `https://i.pravatar.cc/32?u=5` }, - { id: 6, name: "Vivaan Sharma", avatar: `https://i.pravatar.cc/32?u=6` }, - { id: 7, name: "Devansh Joshi", avatar: `https://i.pravatar.cc/32?u=7` }, - { id: 8, name: "Kabir Malhotra", avatar: `https://i.pravatar.cc/32?u=8` }, - ]; - const round1Winners = [participants[0], participants[2], participants[4], participants[7]]; - const semiFinalWinners = [round1Winners[0], round1Winners[3]]; - const champion = semiFinalWinners[1]; - const winnerHighlight = "ring-4 ring-yellow-400 shadow-lg transition-all duration-300"; - + const [isLoading, setIsLoading] = useState(true); + const [participants, setParticipants] = useState([]); + + useEffect(() => { + // Simulate API call + const timer = setTimeout(() => { + const data: Participant[] = [ + { id: 1, name: "Rishit Tiwari", avatar: `https://i.pravatar.cc/32?u=1` }, + { id: 2, name: "Aarav Singh", avatar: `https://i.pravatar.cc/32?u=2` }, + { id: 3, name: "Ishaan Mehta", avatar: `https://i.pravatar.cc/32?u=3` }, + { id: 4, name: "Vihaan Kapoor", avatar: `https://i.pravatar.cc/32?u=4` }, + { id: 5, name: "Ayaan Khanna", avatar: `https://i.pravatar.cc/32?u=5` }, + { id: 6, name: "Vivaan Sharma", avatar: `https://i.pravatar.cc/32?u=6` }, + { id: 7, name: "Devansh Joshi", avatar: `https://i.pravatar.cc/32?u=7` }, + { id: 8, name: "Kabir Malhotra", avatar: `https://i.pravatar.cc/32?u=8` }, + ]; + setParticipants(data); + setIsLoading(false); + }, 1000); + + return () => clearTimeout(timer); + }, []); + + if (isLoading) { return ( -
-

Tournament Bracket

- {/* Champion */} -
-
-
🏆 Champion
-
- Champion +
+
+ {/* Champion Skeleton */} +
+
+
+
+
-
{champion.name}
-
- {/* Finalists */} -
- {semiFinalWinners.map((finalist, index) => ( -
-
- {finalist.name} + + {/* Finalists Skeleton */} +
+ {[1, 2].map((i) => ( +
+
+
-
{finalist.name}
-
-
- ))} -
-
+ ))} +
- {/* Semifinals */} -
- {[0, 1].map((matchIndex) => { - const player1 = round1Winners[matchIndex * 2]; - const player2 = round1Winners[matchIndex * 2 + 1]; - const winner = semiFinalWinners[matchIndex]; - return ( -
-
- {[player1, player2].map((player) => ( -
-
- {player.name} -
-
{player.name}
-
+
+ ); + } + + // Bracket logic + const round1Winners = [participants[0], participants[2], participants[4], participants[7]]; + const semiFinalWinners = [round1Winners[0], round1Winners[3]]; + const champion = semiFinalWinners[1]; + const winnerHighlight = "ring-4 ring-yellow-400 shadow-lg transition-all duration-300"; + + return ( +
+

Tournament Bracket

+ {/* Champion */} +
+
+
🏆 Champion
+
+ Champion +
+
{champion.name}
+
+
+ + {/* Finalists */} +
+ {semiFinalWinners.map((finalist, index) => ( +
+
+ {finalist.name} +
+
{finalist.name}
+
+
+ ))} +
+
+
+ + {/* Semifinals */} +
+ {[0, 1].map((matchIndex) => { + const player1 = round1Winners[matchIndex * 2]; + const player2 = round1Winners[matchIndex * 2 + 1]; + const winner = semiFinalWinners[matchIndex]; + return ( +
+
+ {[player1, player2].map((player) => ( +
+
+ {player.name}
- ))} -
-
-
+
{player.name}
+
+
+ ))}
- ); - })} -
- {/* First Round */} -
- {[0, 1, 2, 3].map((matchIndex) => { - const player1 = participants[matchIndex * 2]; - const player2 = participants[matchIndex * 2 + 1]; - const winner = round1Winners[matchIndex]; - return ( -
-
- {[player1, player2].map((player) => ( -
-
- {player.name} -
-
{player.name}
-
+
+
+
+ ); + })} +
+ + {/* First Round */} +
+ {[0, 1, 2, 3].map((matchIndex) => { + const player1 = participants[matchIndex * 2]; + const player2 = participants[matchIndex * 2 + 1]; + const winner = round1Winners[matchIndex]; + return ( +
+
+ {[player1, player2].map((player) => ( +
+
+ {player.name}
- ))} -
-
-
+
{player.name}
+
+
+ ))}
- ); - })} -
- {/* Match Labels */} -
-
Match 1
-
Match 2
-
Match 3
-
Match 4
-
+
+
+
+ ); + })}
- ); - } - \ No newline at end of file + + {/* Match Labels */} +
+
Match 1
+
Match 2
+
Match 3
+
Match 4
+
+
+ ); +} diff --git a/frontend/src/Pages/TournamentHub.tsx b/frontend/src/Pages/TournamentHub.tsx index 5652e83..65b11f8 100644 --- a/frontend/src/Pages/TournamentHub.tsx +++ b/frontend/src/Pages/TournamentHub.tsx @@ -1,4 +1,5 @@ -import React, { useState, FormEvent } from 'react'; +// TournamentHub.tsx +import React, { useState, useEffect, FormEvent } from 'react'; import { Users, Calendar, Eye } from 'lucide-react'; import { useNavigate } from 'react-router-dom'; @@ -42,13 +43,24 @@ export default function TournamentPage() { }, ]; - const [tournaments, setTournaments] = useState(initialTournaments); + const [tournaments, setTournaments] = useState([]); + const [isLoading, setIsLoading] = useState(true); const [name, setName] = useState(''); const [date, setDate] = useState(''); const [description, setDescription] = useState(''); const [error, setError] = useState(''); const navigate = useNavigate(); + useEffect(() => { + // Simulate API call + const timer = setTimeout(() => { + setTournaments(initialTournaments); + setIsLoading(false); + }, 1000); + + return () => clearTimeout(timer); + }, []); + const handleCreate = (e: FormEvent) => { e.preventDefault(); if (!name) { @@ -118,12 +130,38 @@ export default function TournamentPage() { return avatars; }; + if (isLoading) { + // Skeleton Loader + return ( +
+

+ Tournament Arena +

+
+
+ {[1, 2, 3, 4, 5, 6].map((i) => ( +
+
+
+
+
+
+
+ ))} +
+
+
+ ); + } + + // Actual Tournament Hub Page return (

Tournament Arena

+ {/* Tournament Cards */}
{tournaments.length === 0 ? (

@@ -143,7 +181,6 @@ export default function TournamentPage() {

)}
+ + {/* Create Tournament Form */}

Create New Tournament

diff --git a/frontend/src/index.css b/frontend/src/index.css index 42fc935..0c40f5f 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -1,8 +1,10 @@ +/* Tailwind base setup */ @tailwind base; @tailwind components; @tailwind utilities; + +/* Custom CSS variables and dark/contrast modes */ @layer base { - :root { --background: 0 0% 100%; --foreground: 20 14.3% 4.1%; @@ -84,17 +86,33 @@ --chart-4: 300 100% 50%; --chart-5: 180 100% 50%; } -} -@layer base { + /* Apply border color globally */ * { @apply border-border; } + + /* Body background and text color */ body { @apply bg-background text-foreground; } } +/* Pulse animation */ +@keyframes pulse { + 0%, 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + +.animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; +} + +/* Floating animation */ @keyframes floatUp { 0% { transform: translateY(0);