@@ -39,6 +39,18 @@ <h1 class="page-title">Leaderboard</h1>
3939 < button class ="tab " data-tab ="daily "> Daily</ button >
4040 </ div >
4141
42+
43+
44+ < div class ="search-container ">
45+ < input
46+ type ="text "
47+ id ="leaderboard-search "
48+ class ="search-input "
49+ placeholder ="./search_by_name_or_leetcode_id "
50+ autocomplete ="off "
51+ >
52+ </ div >
53+
4254 < div class ="leaderboard ">
4355 < div class ="leaderboard-header ">
4456 < div > Rank</ div >
@@ -94,13 +106,21 @@ <h1 class="page-title">Leaderboard</h1>
94106 } ) ;
95107 } ) ;
96108
109+ const searchInput = document . getElementById ( 'leaderboard-search' ) ;
110+
111+ searchInput . addEventListener ( 'input' , ( e ) => {
112+ currentSearchTerm = e . target . value . toLowerCase ( ) . trim ( ) ;
113+ applyFiltersAndRender ( ) ;
114+ } ) ;
115+
97116 fetchLeaderboardData ( ) ;
98117 } ) ;
99118
100119 const leaderboardData = { } ;
101120 let currentDisplayLimit = 0 ;
102121 let activeDatasetType = 'overall' ;
103122 let fetchMoreClicks = 0 ;
123+ let currentSearchTerm = '' ;
104124
105125 function getInitialLimit ( ) {
106126 return window . innerWidth <= 768 ? 12 : 25 ;
@@ -177,7 +197,30 @@ <h1 class="page-title">Leaderboard</h1>
177197 document . getElementById ( 'next-sync-time' ) . style . color = "var(--red)" ;
178198 }
179199
180- setActiveTab ( 'overall' ) ;
200+ applyFiltersAndRender ( ) ;
201+ }
202+
203+ function applyFiltersAndRender ( ) {
204+ if ( currentDisplayLimit === 0 ) {
205+ currentDisplayLimit = getInitialLimit ( ) ;
206+ }
207+ if ( ! leaderboardData [ activeDatasetType ] ) return ;
208+
209+ const originalData = leaderboardData [ activeDatasetType ] ;
210+
211+ const rankedData = originalData . map ( ( user , index ) => ( {
212+ ...user ,
213+ originalRank : index + 1
214+ } ) ) ;
215+
216+ const filteredData = rankedData . filter ( user => {
217+ return (
218+ user . name . toLowerCase ( ) . includes ( currentSearchTerm ) ||
219+ user . id . toLowerCase ( ) . includes ( currentSearchTerm )
220+ ) ;
221+ } ) ;
222+
223+ renderLeaderboard ( filteredData ) ;
181224 }
182225
183226 function getRankTag ( rank ) {
@@ -196,10 +239,33 @@ <h1 class="page-title">Leaderboard</h1>
196239 body . innerHTML = '' ;
197240 mobileCards . innerHTML = '' ;
198241
199- const displayData = data . slice ( 0 , currentDisplayLimit ) ;
242+ const isSearching = currentSearchTerm . length > 0 ;
243+
244+ const displayData = isSearching
245+ ? data
246+ : data . slice ( 0 , currentDisplayLimit ) ;
247+
248+ if ( displayData . length === 0 ) {
249+ body . innerHTML = `
250+ <div class="no-results">
251+ [SYS]: NO_MATCHING_USERS_FOUND
252+ </div>
253+ ` ;
254+
255+ mobileCards . innerHTML = `
256+ <div class="no-results">
257+ [SYS]: NO_MATCHING_USERS_FOUND
258+ </div>
259+ ` ;
260+
261+ document . getElementById ( 'load-more-btn' ) . style . display = 'none' ;
262+ document . getElementById ( 'scroll-top-btn' ) . style . display = 'none' ;
263+
264+ return ;
265+ }
200266
201267 displayData . forEach ( ( user , index ) => {
202- const rank = index + 1 ;
268+ const rank = user . originalRank || index + 1 ;
203269 const tag = getRankTag ( rank ) ;
204270 const leetcodeUrl = `https://leetcode.com/u/${ user . id } ` ;
205271
@@ -276,7 +342,7 @@ <h1 class="page-title">Leaderboard</h1>
276342 activeDatasetType = activeTab ;
277343 currentDisplayLimit = getInitialLimit ( ) ;
278344 fetchMoreClicks = 0 ;
279- renderLeaderboard ( leaderboardData [ activeTab ] ) ;
345+ applyFiltersAndRender ( ) ;
280346 }
281347
282348 </ script >
0 commit comments