@@ -2,11 +2,13 @@ import { useState, useCallback, useMemo, useEffect, useRef } from 'react';
22import { useSelector } from 'react-redux' ;
33import { Link , useSearchParams } from 'react-router-dom' ;
44import { Trans , useTranslation } from 'react-i18next' ;
5- import { Turnstile } from '@marsidev/react-turnstile'
5+ import { Turnstile } from '@marsidev/react-turnstile' ;
66import Select from 'react-select' ;
77import { Icon } from '@mdi/react' ;
88import { mdiAccountSearch } from '@mdi/js' ;
99
10+ import LoadingSmall from '../../components/loading-small/index.js' ;
11+
1012import useKeyPress from '../../hooks/useKeyPress.jsx' ;
1113
1214import SEO from '../../components/SEO.jsx' ;
@@ -18,7 +20,7 @@ import gameModes from '../../data/game-modes.json';
1820import './index.css' ;
1921
2022function Players ( ) {
21- const [ searchParams , setSearchParams ] = useSearchParams ( ) ;
23+ const [ searchParams , setSearchParams ] = useSearchParams ( ) ;
2224 const turnstileRef = useRef ( ) ;
2325 const turnstileToken = useRef ( false ) ;
2426
@@ -30,23 +32,26 @@ function Players() {
3032 const defaultGameMode = useMemo ( ( ) => {
3133 return searchParams . get ( 'gameMode' ) ?? gameModeSetting ;
3234 } , [ searchParams , gameModeSetting ] ) ;
33- const [ gameMode , setGameMode ] = useState ( defaultGameMode ) ;
34- const lastSearch = useRef ( { name : '' , gameMode} ) ;
35+ const [ gameMode , setGameMode ] = useState ( defaultGameMode ) ;
36+ const lastSearch = useRef ( { name : '' , gameMode } ) ;
3537
3638 const [ nameFilter , setNameFilter ] = useState ( '' ) ;
3739 const [ nameResults , setNameResults ] = useState ( [ ] ) ;
3840 const [ nameResultsError , setNameResultsError ] = useState ( false ) ;
3941
4042 const [ isButtonDisabled , setButtonDisabled ] = useState ( true ) ;
4143 const [ searched , setSearched ] = useState ( false ) ;
44+ const [ searching , setSearching ] = useState ( false ) ;
4245 const [ tokenState , setTokenState ] = useState ( false ) ;
4346
4447 const searchTextValid = useMemo ( ( ) => {
4548 const charactersValid = ! ! nameFilter . match ( / ^ [ a - z A - Z 0 - 9 - _ ] * $ / ) ;
4649 const lengthValid = ! ! nameFilter . match ( / ^ [ a - z A - Z 0 - 9 - _ ] { 3 , 15 } $ | ^ T a r k o v C i t i z e n \d { 1 , 10 } $ / i) ;
4750 setNameResultsError ( false ) ;
4851 if ( ! charactersValid ) {
49- setNameResultsError ( `Names can only contain letters, numbers, dashes (-), and underscores (_)` ) ;
52+ setNameResultsError (
53+ `Names can only contain letters, numbers, dashes (-), and underscores (_)` ,
54+ ) ;
5055 }
5156 return charactersValid && lengthValid ;
5257 } , [ nameFilter , setNameResultsError ] ) ;
@@ -75,8 +80,13 @@ function Players() {
7580 return ;
7681 }
7782 try {
83+ setSearching ( true ) ;
7884 setNameResultsError ( false ) ;
79- setNameResults ( ( await playerStats . searchPlayers ( nameFilter , gameMode , turnstileToken . current ) ) . sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) ) ;
85+ setNameResults (
86+ (
87+ await playerStats . searchPlayers ( nameFilter , gameMode , turnstileToken . current )
88+ ) . sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) ,
89+ ) ;
8090 setSearched ( true ) ;
8191 lastSearch . current . name = nameFilter ;
8292 lastSearch . current . gameMode = gameMode ;
@@ -85,12 +95,22 @@ function Players() {
8595 lastSearch . current . name = '' ;
8696 setNameResults ( [ ] ) ;
8797 setNameResultsError ( error . message ) ;
98+ } finally {
99+ setSearching ( false ) ;
88100 }
89101 setTokenState ( false ) ;
90102 if ( turnstileRef . current ?. reset ) {
91103 turnstileRef . current . reset ( ) ;
92104 }
93- } , [ nameFilter , searchTextValid , setNameResults , setNameResultsError , turnstileToken , turnstileRef , gameMode ] ) ;
105+ } , [
106+ nameFilter ,
107+ searchTextValid ,
108+ setNameResults ,
109+ setNameResultsError ,
110+ turnstileToken ,
111+ turnstileRef ,
112+ gameMode ,
113+ ] ) ;
94114
95115 const searchResults = useMemo ( ( ) => {
96116 if ( ! searched ) {
@@ -101,18 +121,18 @@ function Players() {
101121 }
102122 let morePlayers = '' ;
103123 if ( nameResults . length >= 5 ) {
104- morePlayers = < p > { t ( 'Refine your search to get better results' ) } </ p >
124+ morePlayers = < p > { t ( 'Refine your search to get better results' ) } </ p > ;
105125 }
106126 return (
107127 < div >
108128 { morePlayers }
109129 < ul className = "name-results-list" >
110- { nameResults . map ( result => {
111- return < li key = { `account- ${ result . aid } ` } >
112- < Link to = { `/players/ ${ gameMode } / ${ result . aid } ` } >
113- { result . name }
114- </ Link >
115- </ li >
130+ { nameResults . map ( ( result ) => {
131+ return (
132+ < li key = { `account- ${ result . aid } ` } >
133+ < Link to = { `/players/ ${ gameMode } / ${ result . aid } ` } > { result . name } </ Link >
134+ </ li >
135+ ) ;
116136 } ) }
117137 </ ul >
118138 </ div >
@@ -128,7 +148,10 @@ function Players() {
128148 return [
129149 < SEO
130150 title = { `${ t ( 'Players' ) } - ${ t ( 'Escape from Tarkov' ) } - ${ t ( 'Tarkov.dev' ) } ` }
131- description = { t ( 'players-page-description' , 'Search Escape from Tarkov players. View player profiles and see their stats.' ) }
151+ description = { t (
152+ 'players-page-description' ,
153+ 'Search Escape from Tarkov players. View player profiles and see their stats.' ,
154+ ) }
132155 key = "seo-wrapper"
133156 /> ,
134157 < div className = { 'page-wrapper' } key = "players-page-wrapper" >
@@ -140,35 +163,37 @@ function Players() {
140163 </ div >
141164 < div >
142165 < Trans i18nKey = { 'players-page-p' } >
143- < p >
144- Search for Escape From Tarkov players and view their profiles.
145- </ p >
166+ < p > Search for Escape From Tarkov players and view their profiles.</ p >
146167 </ Trans >
147168 </ div >
148- < label className = { 'single-filter-wrapper' } style = { { marginBottom : '1em' } } >
169+ < label className = { 'single-filter-wrapper' } style = { { marginBottom : '1em' } } >
149170 < span className = { 'single-filter-label' } > { t ( 'Game mode' ) } </ span >
150171 < Select
151172 label = { t ( 'Game mode' ) }
152173 placeholder = { t ( `game_mode_${ defaultGameMode } ` ) }
153174 defaultValue = { defaultGameMode }
154- options = { gameModes . map ( m => {
175+ options = { gameModes . map ( ( m ) => {
155176 return {
156177 label : t ( `game_mode_${ m } ` ) ,
157178 value : m ,
158- }
179+ } ;
159180 } ) }
160181 className = "basic-multi-select game-mode"
161182 classNamePrefix = "select"
162183 onChange = { ( event ) => {
163- setSearchParams ( { gameMode : event . value } ) ;
164- if ( searchTextValid && gameMode !== event . value && ! ! turnstileToken . current ) {
184+ setSearchParams ( { gameMode : event . value } ) ;
185+ if (
186+ searchTextValid &&
187+ gameMode !== event . value &&
188+ ! ! turnstileToken . current
189+ ) {
165190 setButtonDisabled ( false ) ;
166191 }
167192 setGameMode ( event . value ) ;
168193 } }
169194 />
170195 </ label >
171- < div className = ' search-controls' >
196+ < div className = " search-controls" >
172197 < InputFilter
173198 label = { t ( 'Player Name' ) }
174199 defaultValue = { nameFilter }
@@ -180,31 +205,39 @@ function Players() {
180205 } }
181206 className = "player-name-search"
182207 />
183- < button className = "search-button" onClick = { searchForName } disabled = { isButtonDisabled } > { t ( 'Search' ) } </ button >
208+ < button
209+ className = "search-button"
210+ onClick = { searchForName }
211+ disabled = { isButtonDisabled }
212+ >
213+ { searching ? < LoadingSmall /> : t ( 'Search' ) }
214+ </ button >
184215 </ div >
185216 { ! ! nameResultsError && (
186217 < div >
187218 < p className = "error" > { nameResultsError } </ p >
188219 </ div >
189220 ) }
190- < Turnstile
221+ < Turnstile
191222 ref = { turnstileRef }
192223 className = "turnstile-widget"
193- siteKey = ' 0x4AAAAAAAVVIHGZCr2PPwrR'
224+ siteKey = " 0x4AAAAAAAVVIHGZCr2PPwrR"
194225 onSuccess = { ( token ) => {
195226 setTokenState ( token ) ;
196227 } }
197228 onError = { ( errorCode ) => {
198229 // https://developers.cloudflare.com/turnstile/reference/client-side-errors#error-codes
199230 if ( errorCode === '110200' ) {
200- setNameResultsError ( `Turnstile error: ${ window . location . hostname } is not a valid hostname` ) ;
231+ setNameResultsError (
232+ `Turnstile error: ${ window . location . hostname } is not a valid hostname` ,
233+ ) ;
201234 } else if ( errorCode . startsWith ( '600' ) ) {
202235 setNameResultsError ( 'Turnstile challenge failed' ) ;
203236 } else {
204237 setNameResultsError ( `Turnstile error code ${ errorCode } ` ) ;
205238 }
206239 } }
207- options = { { appearance : 'interaction-only' } }
240+ options = { { appearance : 'interaction-only' } }
208241 />
209242 { ! nameResultsError && searchResults }
210243 </ div > ,
0 commit comments