@@ -3,9 +3,10 @@ import { useEffect, useState } from "react";
33import dynamic from "next/dynamic" ;
44import { Item } from "../typings/types" ;
55import { LeaderboardTable } from "../components/leaderboard/LeaderboardTable" ;
6- import { TopThree } from "../components/leaderboard/TopThree" ;
6+ import { TopThree } from "../components/leaderboard/TopThree" ;
77import PageLayout from "../components/layout/PageLayout" ;
88import snowman from "../public/assets/animations/snowman.json" ;
9+ import { motion , AnimatePresence } from "framer-motion" ;
910
1011// Dynamically import Lottie to prevent SSR issues
1112const Lottie = dynamic ( ( ) => import ( "lottie-react" ) , { ssr : false } ) ;
@@ -14,9 +15,11 @@ const Leaderboard: NextPage = () => {
1415 const [ leaderboard , setLeaderboard ] = useState < Item [ ] > ( [ ] ) ;
1516 const [ loading , setLoading ] = useState < boolean > ( true ) ;
1617 const [ isClient , setIsClient ] = useState ( false ) ;
18+ const [ showNotification , setShowNotification ] = useState < boolean > ( false ) ;
1719
1820 useEffect ( ( ) => {
19- setIsClient ( true ) ; // Ensure animations only run on the client
21+ setIsClient ( true ) ;
22+
2023 const fetchLeaderboard = async ( ) => {
2124 try {
2225 const baseURL = process . env . NEXT_PUBLIC_API_BASE_URL ;
@@ -32,11 +35,42 @@ const Leaderboard: NextPage = () => {
3235 setLoading ( false ) ;
3336 }
3437 } ;
38+
39+ // Initial fetch
3540 fetchLeaderboard ( ) ;
41+
42+ // Show notification on page load
43+ setShowNotification ( true ) ;
44+ setTimeout ( ( ) => setShowNotification ( false ) , 4000 ) ;
45+
46+ // Refresh leaderboard every 5 minutes and show notification
47+ const interval = setInterval ( ( ) => {
48+ fetchLeaderboard ( ) ;
49+ setShowNotification ( true ) ;
50+ setTimeout ( ( ) => setShowNotification ( false ) , 4000 ) ;
51+ } , 5 * 60 * 1000 ) ; // 5 minutes
52+
53+ return ( ) => clearInterval ( interval ) ;
3654 } , [ ] ) ;
3755
3856 return (
3957 < PageLayout title = "PWOC | Leaderboard" description = "Leaderboard of PWoC" >
58+ { /* 🔔 Notification Popup */ }
59+ < AnimatePresence >
60+ { showNotification && (
61+ < motion . div
62+ initial = { { opacity : 0 , x : 50 } }
63+ animate = { { opacity : 1 , x : 0 } }
64+ exit = { { opacity : 0 , x : 50 } }
65+ transition = { { duration : 0.5 } }
66+ className = "fixed top-6 right-6 bg-white/20 text-white py-3 px-5 rounded-lg shadow-lg backdrop-blur-md border border-gray-400 z-50"
67+ >
68+ < p className = "text-sm font-medium" > 🔄 Leaderboard refreshes every 5 minutes.</ p >
69+ </ motion . div >
70+ ) }
71+ </ AnimatePresence >
72+
73+ { /* Leaderboard Content */ }
4074 < div className = "flex items-center flex-col" >
4175 { leaderboard . length > 2 ? (
4276 < >
@@ -56,4 +90,4 @@ const Leaderboard: NextPage = () => {
5690 ) ;
5791} ;
5892
59- export default Leaderboard ;
93+ export default Leaderboard ;
0 commit comments