diff --git a/src/App.js b/src/App.js index 10fc95141..a804e2381 100644 --- a/src/App.js +++ b/src/App.js @@ -78,6 +78,7 @@ const WipeLength = React.lazy(() => import('./pages/wipe-length/index.js')); const Achievements = React.lazy(() => import('./pages/achievements/index.js')); const Players = React.lazy(() => import('./pages/players/index.js')); const Player = React.lazy(() => import('./pages/player/index.js')); +const PlayerForward = React.lazy(() => import('./pages/player/player-forward.js')); const Converter = React.lazy(() => import('./pages/converter/index.js')); const About = React.lazy(() => import('./pages/about/index.js')); @@ -924,7 +925,7 @@ function App() { ]} /> } key="suspense-player-wrapper"> @@ -933,6 +934,16 @@ function App() { remoteControlSessionElement, ]} /> + } key="suspense-player-forward-wrapper"> + + , + remoteControlSessionElement, + ]} + /> { + request: async (path, gameMode, body) => { try { const method = body ? 'POST' : 'GET'; const response = await fetch(apiUrl + path, { method, body, + headers: { + 'game-mode': gameMode, + } }); if (response.status !== 200) { @@ -33,13 +36,14 @@ const playerStats = { } return json; } catch (error) { + console.log(error); if (error.message.includes('NetworkError')) { return Promise.reject(new Error('Rate limited exceeded. Wait one minute to send another request.')); } return Promise.reject(error); } }, - searchPlayers: async (searchString, turnstileToken) => { + searchPlayers: async (searchString, gameMode = 'regular', turnstileToken) => { // Create a form request to send the Turnstile token // This avoids sending an extra pre-flight request let body; @@ -52,14 +56,14 @@ const playerStats = { searchParams = `?token=${turnstileToken}`; } } - return playerStats.request(`/name/${searchString}${searchParams}`, body).catch(error => { + return playerStats.request(`/name/${searchString}${searchParams}`, gameMode, body).catch(error => { if (error.message.includes('Malformed')) { return Promise.reject(new Error('Error searching player profile; try removing one character from the end until the search works.')); } return Promise.reject(error); }); }, - getProfile: async (accountId, turnstileToken) => { + getProfile: async (accountId, gameMode = 'regular', turnstileToken) => { let body; let searchParams = ''; if (turnstileToken) { @@ -70,7 +74,7 @@ const playerStats = { searchParams = `?token=${turnstileToken}`; } } - return playerStats.request(`/account/${accountId}${searchParams}`, body); + return playerStats.request(`/account/${accountId}${searchParams}`, gameMode, body); }, }; diff --git a/src/pages/player/index.js b/src/pages/player/index.js index 6e0e7306d..9333cd8e9 100644 --- a/src/pages/player/index.js +++ b/src/pages/player/index.js @@ -78,6 +78,8 @@ function Player() { const params = useParams(); const navigate = useNavigate(); + const gameMode = params.gameMode; + const [accountId, setAccountId] = useState(params.accountId); useEffect(() => { @@ -125,7 +127,7 @@ function Player() { } for (const result of searchResponse) { if (result.name.toLowerCase() === accountId.toLowerCase()) { - navigate('/player/'+result.aid); + navigate(`/players/${gameMode}/${result.aid}`); return; } } @@ -143,7 +145,7 @@ function Player() { } catch (error) { setProfileError(error.message); } - }, [accountId, setPlayerData, setProfileError, navigate, turnstileToken, turnstileRef]); + }, [accountId, setPlayerData, setProfileError, navigate, turnstileToken, turnstileRef, gameMode]); const downloadProfile = useCallback(() => { if (!playerData.aid) { @@ -166,13 +168,13 @@ function Player() { const data = JSON.parse(text); data.saved = true; setPlayerData(data); - window.history.replaceState(null, null, `/player/${data.aid}`); + window.history.replaceState(null, null, `/players/${gameMode}/${data.aid}`); } catch(error) { setProfileError('Error reading profile'); } }; reader.readAsText(e.target.files[0]); - }, [setPlayerData, setProfileError]); + }, [setPlayerData, setProfileError, gameMode]); const playerLevel = useMemo(() => { if (playerData.info.experience === 0) { @@ -708,11 +710,11 @@ function Player() { countLabel = tag.Level; let killerInfo = {tag.KillerName}; if (tag.KillerAccountId) { - killerInfo = {tag.KillerName}; + killerInfo = {tag.KillerName}; } label = ( - {tag.Nickname} + {tag.Nickname} {` ${t(tag.Status)} `} {killerInfo} {weapon !== undefined && [ @@ -753,7 +755,7 @@ function Player() { /> ); return { image: itemImage, label }; - }, [items, t]); + }, [items, t, gameMode]); const getLoadoutContents = useCallback((parentItem, itemType = 'loadout') => { const itemSource = itemType === 'loadout' ? playerData?.equipment?.Items : playerData?.favoriteItems; diff --git a/src/pages/player/player-forward.js b/src/pages/player/player-forward.js new file mode 100644 index 000000000..b1d44f66a --- /dev/null +++ b/src/pages/player/player-forward.js @@ -0,0 +1,9 @@ +import { useParams, useNavigate } from 'react-router-dom'; + +function PlayerForward() { + const params = useParams(); + const navigate = useNavigate(); + navigate('/players/regular/'+params.accountId); +} + +export default PlayerForward; diff --git a/src/pages/players/index.css b/src/pages/players/index.css index a7079de4c..7a2df2d9f 100644 --- a/src/pages/players/index.css +++ b/src/pages/players/index.css @@ -30,3 +30,13 @@ grid-template-columns: repeat(3, 1fr); grid-gap: 10px; } + +.game-mode .select__control { + color: #1b1919; + background-color: #2d2c2e; + border-color: #9a8866; +} + +.game-mode .select__single-value { + color: #fff; +} diff --git a/src/pages/players/index.js b/src/pages/players/index.js index 3f4933f4e..b02bf92ad 100644 --- a/src/pages/players/index.js +++ b/src/pages/players/index.js @@ -1,8 +1,9 @@ import { useState, useCallback, useMemo, useEffect, useRef } from 'react'; +import { useSelector } from 'react-redux'; import { Link } from 'react-router-dom'; import { Trans, useTranslation } from 'react-i18next'; import { Turnstile } from '@marsidev/react-turnstile' - +import Select from 'react-select'; import { Icon } from '@mdi/react'; import { mdiAccountSearch } from '@mdi/js'; @@ -12,6 +13,7 @@ import SEO from '../../components/SEO.jsx'; import { InputFilter } from '../../components/filter/index.js'; import playerStats from '../../modules/player-stats.mjs'; +import gameModes from '../../data/game-modes.json'; import './index.css'; @@ -23,6 +25,9 @@ function Players() { const enterPress = useKeyPress('Enter'); + const gameModeSetting = useSelector((state) => state.settings.gameMode); + const [ gameMode, setGameMode ] = useState(gameModeSetting); + const [nameFilter, setNameFilter] = useState(''); const [nameResults, setNameResults] = useState([]); const [nameResultsError, setNameResultsError] = useState(false); @@ -56,7 +61,7 @@ function Players() { try { setNameResultsError(false); setButtonDisabled(true); - setNameResults((await playerStats.searchPlayers(nameFilter, turnstileToken.current)).sort((a, b) => a.name.localeCompare(b.name))); + setNameResults((await playerStats.searchPlayers(nameFilter, gameMode, turnstileToken.current)).sort((a, b) => a.name.localeCompare(b.name))); setSearched(true); } catch (error) { setSearched(false); @@ -67,7 +72,7 @@ function Players() { if (turnstileRef.current?.reset) { turnstileRef.current.reset(); } - }, [nameFilter, searchTextValid, setNameResults, setNameResultsError, turnstileToken, turnstileRef]); + }, [nameFilter, searchTextValid, setNameResults, setNameResultsError, turnstileToken, turnstileRef, gameMode]); const searchResults = useMemo(() => { if (!searched) { @@ -122,6 +127,25 @@ function Players() {

+