@@ -13,15 +13,49 @@ import RankCard from "@/components/RankCard";
1313import { Profile } from "@/lib/types" ;
1414import { leaderboard } from "@/config/axios/Breakpoints" ;
1515import { useRouter } from "next/navigation" ;
16- import { ChevronLeft , ChevronRight } from "lucide-react" ;
16+ import { ChevronLeft , ChevronRight , Search , SearchIcon , X } from "lucide-react" ;
1717import { useSelector } from "react-redux" ;
18+ import LoginButton from "@/components/Button/LoginButton" ;
19+ import { Input } from "@/components/ui/input" ;
1820
1921const Leaderboard = ( ) => {
2022 const router = useRouter ( ) ;
2123 const [ profile , setProfile ] = useState < Profile [ ] > ( [ ] ) ;
2224 const user = useSelector ( ( state : any ) => state . user ) ;
2325 const [ currentPage , setCurrentPage ] = useState ( 1 ) ;
2426 const recordsPerPage = 15 ;
27+ const [ isOpen , setIsOpen ] = useState ( false ) ;
28+ const [ search , setSearch ] = useState ( "" ) ;
29+ const [ filteredProfiles , setFilteredProfiles ] = useState < Profile [ ] > ( [ ] ) ;
30+
31+ useEffect ( ( ) => {
32+ const fetchProfiles = async ( ) => {
33+ const { response } = await POST ( leaderboard , { } ) ;
34+ setProfile ( response ?. data ) ;
35+ setFilteredProfiles ( response ?. data ) ;
36+ } ;
37+ fetchProfiles ( ) ;
38+ } , [ ] ) ;
39+
40+ useEffect ( ( ) => {
41+ if ( search ) {
42+ const rankedProfiles = profile . map ( ( p , index ) => ( {
43+ ...p ,
44+ rank : index + 1 ,
45+ } ) ) ;
46+ setFilteredProfiles (
47+ rankedProfiles . filter ( ( p ) =>
48+ p . githubUsername . toLowerCase ( ) . includes ( search . toLowerCase ( ) )
49+ )
50+ ) ;
51+ } else {
52+ setFilteredProfiles ( [ ] ) ;
53+ }
54+ } , [ search , profile ] ) ;
55+
56+ const toggleSearch = ( ) => {
57+ setIsOpen ( ! isOpen ) ;
58+ } ;
2559
2660 const response = async ( ) => {
2761 const { response } = await POST ( leaderboard , { } ) ;
@@ -60,7 +94,7 @@ const Leaderboard = () => {
6094
6195 return (
6296 < >
63- < div className = "w-full flex justify-center items-center text-3xl font-bold tracking-widest" >
97+ < div className = "w-full hidden md: flex justify-center items-center text-3xl font-bold tracking-widest" >
6498 LEADERBOARD
6599 </ div >
66100 < div className = "w-full h-fit pt-4" >
@@ -79,7 +113,67 @@ const Leaderboard = () => {
79113 </ div >
80114 </ div >
81115
82- < div className = "flex flex-col justify-center items-center container max-w-5xl" >
116+ < div className = "absolute bottom-[82vh] md:bottom-10 right-[10px] z-30 max-w-[500px]" >
117+ < div >
118+ < button
119+ onClick = { toggleSearch }
120+ className = "px-4 py-3 border-[1px] rounded-full border-slate-800 bg-black flex justify-center items-center gap-4"
121+ >
122+ < SearchIcon size = { 20 } />
123+ < p className = "hidden md:flex" > Search</ p >
124+ </ button >
125+ </ div >
126+
127+ < div
128+ className = { `fixed w-full md:w-1/2 lg:w-1/3 h-4/6 bottom-0 right-0 z-30 border-[1px] bg-black border-slate-800 transition-transform duration-500 ease-in-out rounded-lg ${
129+ isOpen ? "translate-x-0" : "translate-x-full"
130+ } `}
131+ >
132+ < div className = "p-4 flex flex-col gap-4" >
133+ < div className = "flex justify-between px-4 items-center" >
134+ < h2 className = "text-xl font-bold" > Search Panel</ h2 >
135+ < X size = { 20 } onClick = { toggleSearch } className = "cursor-pointer" />
136+ </ div >
137+ < hr />
138+ < div >
139+ < Input
140+ id = "first-name"
141+ placeholder = "Enter name"
142+ name = "name"
143+ value = { search }
144+ onChange = { ( e ) => setSearch ( e . target . value ) }
145+ />
146+ </ div >
147+ < div className = "mt-4 max-h-[430px] overflow-y-auto" >
148+ { search && filteredProfiles . length > 0 ? (
149+ < ul >
150+ { filteredProfiles . map ( ( item ) => (
151+ < li
152+ key = { item . githubUsername }
153+ className = "p-2 border-b cursor-pointer hover:bg-gray-700"
154+ onClick = { ( ) => userProfile ( item . githubUsername ) }
155+ >
156+ < div className = "flex justify-between" >
157+ < p className = "w-[60px]" > { item . rank } </ p >
158+ < p className = "w-[210px] flex justify-start" >
159+ { item . githubUsername }
160+ </ p >
161+ < p className = "w-[80px] flex justify-end" >
162+ { item . totalPoints }
163+ </ p >
164+ </ div >
165+ </ li >
166+ ) ) }
167+ </ ul >
168+ ) : search ? (
169+ < p className = "text-center text-gray-400" > No user found</ p >
170+ ) : null }
171+ </ div >
172+ </ div >
173+ </ div >
174+ </ div >
175+
176+ < div className = "flex flex-col justify-center items-center px-4 md:container md:max-w-5xl" >
83177 < Table >
84178 < TableHeader >
85179 < TableRow >
@@ -124,12 +218,13 @@ const Leaderboard = () => {
124218 </ Table >
125219 </ div >
126220 ) }
127- < div className = "flex justify-between items-center py-6 w-full" >
221+ < div className = "flex justify-between items-center pt-6 pb-6 md:pb-16 w-full" >
128222 < button
129223 onClick = { handlePreviousPage }
130224 disabled = { currentPage === 1 }
131- className = { `px-4 py-2 rounded ${ currentPage === 1 ? "opacity-50 cursor-not-allowed" : ""
132- } `}
225+ className = { `px-4 py-2 rounded ${
226+ currentPage === 1 ? "opacity-50 cursor-not-allowed" : ""
227+ } `}
133228 >
134229 < ChevronLeft color = "white" size = { 40 } />
135230 </ button >
@@ -141,15 +236,14 @@ const Leaderboard = () => {
141236 < button
142237 onClick = { handleNextPage }
143238 disabled = { currentPage === totalPages }
144- className = { `px-4 py-2 rounded ${ currentPage === totalPages ? "opacity-50 cursor-not-allowed" : ""
145- } `}
239+ className = { `px-4 py-2 rounded ${
240+ currentPage === totalPages ? "opacity-50 cursor-not-allowed" : ""
241+ } `}
146242 >
147243 < ChevronRight color = "white" size = { 40 } />
148244 </ button >
149245 </ div >
150246 </ div >
151-
152- { /* Pagination controls */ }
153247 </ >
154248 ) ;
155249} ;
0 commit comments