mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 12:09:51 +02:00
feat: archived player lookup
This commit is contained in:
1 parent
1bb83da253
commit
466f68701f
1 file changed
+90
-23
@@ -5,19 +5,29 @@ import {
|
|||||||
CaretRightIcon,
|
CaretRightIcon,
|
||||||
MagnifyingGlassIcon,
|
MagnifyingGlassIcon,
|
||||||
} from '@radix-ui/react-icons';
|
} from '@radix-ui/react-icons';
|
||||||
import { Button, Flex, Popover, Select, TextField } from '@radix-ui/themes';
|
import {
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
Flex,
|
||||||
|
Popover,
|
||||||
|
Select,
|
||||||
|
TextField,
|
||||||
|
} from '@radix-ui/themes';
|
||||||
import { produce } from 'immer';
|
import { produce } from 'immer';
|
||||||
import { range } from 'lodash';
|
import { debounce, range } from 'lodash';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { ChangeEvent, useEffect, useRef, useState } from 'react';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import * as Leaderboard from '../../../components/Leaderboard';
|
import * as Leaderboard from '../../../components/Leaderboard';
|
||||||
import PageWrapper from '../../../components/PageWrapper';
|
import PageWrapper from '../../../components/PageWrapper';
|
||||||
import { FIRST_ARCHIVED_RATINGS_SEASON } from '../../../constants/ratings';
|
import { FIRST_ARCHIVED_RATINGS_SEASON } from '../../../constants/ratings';
|
||||||
import { REGIONS, REGION_NAMES, Region } from '../../../constants/regions';
|
import { REGIONS, REGION_NAMES, Region } from '../../../constants/regions';
|
||||||
|
import { WARGAMING_APPLICATION_ID } from '../../../constants/wargamingApplicationID';
|
||||||
|
import fetchBlitz from '../../../core/blitz/fetchBlitz';
|
||||||
import { getAccountInfo } from '../../../core/blitz/getAccountInfo';
|
import { getAccountInfo } from '../../../core/blitz/getAccountInfo';
|
||||||
import { getClanAccountInfo } from '../../../core/blitz/getClanAccountInfo';
|
import { getClanAccountInfo } from '../../../core/blitz/getClanAccountInfo';
|
||||||
import getRatingsInfo from '../../../core/blitz/getRatingsInfo';
|
import getRatingsInfo from '../../../core/blitz/getRatingsInfo';
|
||||||
|
import { AccountList } from '../../../core/blitz/searchPlayersAcrossRegions';
|
||||||
import getArchivedRatingsInfoAPI from '../../../core/blitzkrieg/getArchivedRatingsInfoAPI';
|
import getArchivedRatingsInfoAPI from '../../../core/blitzkrieg/getArchivedRatingsInfoAPI';
|
||||||
import { getArchivedRatingsLeaderboardAPI } from '../../../core/blitzkrieg/getArchivedRatingsLeaderboardAPI';
|
import { getArchivedRatingsLeaderboardAPI } from '../../../core/blitzkrieg/getArchivedRatingsLeaderboardAPI';
|
||||||
import { numberFetcher } from '../../../core/blitzkrieg/numberFetcher';
|
import { numberFetcher } from '../../../core/blitzkrieg/numberFetcher';
|
||||||
@@ -66,6 +76,9 @@ export default function Page() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
const [page, setPage] = useState(0);
|
const [page, setPage] = useState(0);
|
||||||
|
const [highlightedPlayerId, setHighlightedPlayerId] = useState<number | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
const playerSlice = players.data?.slice(
|
const playerSlice = players.data?.slice(
|
||||||
page * rowsPerPage,
|
page * rowsPerPage,
|
||||||
page * rowsPerPage + rowsPerPage,
|
page * rowsPerPage + rowsPerPage,
|
||||||
@@ -75,6 +88,34 @@ export default function Page() {
|
|||||||
setPage((page) =>
|
setPage((page) =>
|
||||||
Math.min(page + 1, Math.floor((players.data?.length ?? 0) / rowsPerPage)),
|
Math.min(page + 1, Math.floor((players.data?.length ?? 0) / rowsPerPage)),
|
||||||
);
|
);
|
||||||
|
const [searchResults, setSearchResults] = useState<AccountList | undefined>(
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
const handleSearchPlayerChange = debounce(
|
||||||
|
async (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const trimmedSearch = event.target.value.trim();
|
||||||
|
|
||||||
|
if (trimmedSearch) {
|
||||||
|
const encodedSearch = encodeURIComponent(trimmedSearch);
|
||||||
|
const accountList = await fetchBlitz<AccountList>(
|
||||||
|
`https://api.wotblitz.com/wotb/account/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=100`,
|
||||||
|
);
|
||||||
|
|
||||||
|
setSearchResults(
|
||||||
|
accountList.filter(
|
||||||
|
(searchedPlayer) =>
|
||||||
|
players.data?.some(
|
||||||
|
(leaderboardPlayer) =>
|
||||||
|
leaderboardPlayer.id === searchedPlayer.account_id,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setSearchResults(undefined);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
500,
|
||||||
|
);
|
||||||
|
|
||||||
cachePage(page - 1);
|
cachePage(page - 1);
|
||||||
cachePage(page);
|
cachePage(page);
|
||||||
@@ -156,7 +197,7 @@ export default function Page() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageWrapper color="tomato">
|
<PageWrapper color="orange">
|
||||||
<Flex gap="2">
|
<Flex gap="2">
|
||||||
<Select.Root
|
<Select.Root
|
||||||
defaultValue={region}
|
defaultValue={region}
|
||||||
@@ -234,42 +275,67 @@ export default function Page() {
|
|||||||
<Popover.Close>
|
<Popover.Close>
|
||||||
<Button color="red">Cancel</Button>
|
<Button color="red">Cancel</Button>
|
||||||
</Popover.Close>
|
</Popover.Close>
|
||||||
|
|
||||||
<Popover.Close>
|
|
||||||
<Button>Jump</Button>
|
|
||||||
</Popover.Close>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Popover.Content>
|
</Popover.Content>
|
||||||
</Popover.Root>
|
</Popover.Root>
|
||||||
|
|
||||||
<Popover.Root>
|
<Dialog.Root>
|
||||||
<Popover.Trigger>
|
<Dialog.Trigger>
|
||||||
<Button variant="soft">Jump to player</Button>
|
<Button variant="soft">Jump to player</Button>
|
||||||
</Popover.Trigger>
|
</Dialog.Trigger>
|
||||||
|
|
||||||
<Popover.Content>
|
<Dialog.Content>
|
||||||
<Flex gap="2" direction="column">
|
<Flex gap="4" direction="column">
|
||||||
<TextField.Root>
|
<TextField.Root>
|
||||||
<TextField.Slot>
|
<TextField.Slot>
|
||||||
<MagnifyingGlassIcon height="16" width="16" />
|
<MagnifyingGlassIcon height="16" width="16" />
|
||||||
</TextField.Slot>
|
</TextField.Slot>
|
||||||
|
|
||||||
<TextField.Input placeholder="Search for player..." />
|
<TextField.Input
|
||||||
|
onChange={handleSearchPlayerChange}
|
||||||
|
placeholder="Search for player..."
|
||||||
|
/>
|
||||||
</TextField.Root>
|
</TextField.Root>
|
||||||
|
|
||||||
<Flex gap="2">
|
<Flex direction="column" gap="2">
|
||||||
<Popover.Close>
|
{searchResults?.map((player) => (
|
||||||
<Button color="red">Cancel</Button>
|
<Dialog.Close>
|
||||||
</Popover.Close>
|
<Button
|
||||||
|
key={player.account_id}
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => {
|
||||||
|
const playerIndex = players.data?.findIndex(
|
||||||
|
(playerData) => playerData.id === player.account_id,
|
||||||
|
);
|
||||||
|
const playerPage = Math.floor(
|
||||||
|
playerIndex! / rowsPerPage,
|
||||||
|
);
|
||||||
|
|
||||||
<Popover.Close>
|
setPage(playerPage);
|
||||||
<Button>Jump</Button>
|
setHighlightedPlayerId(player.account_id);
|
||||||
</Popover.Close>
|
}}
|
||||||
|
>
|
||||||
|
{player.nickname}
|
||||||
|
</Button>
|
||||||
|
</Dialog.Close>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{searchResults?.length === 0 && (
|
||||||
|
<Button disabled variant="ghost">
|
||||||
|
No players found in leaderboard
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex gap="2">
|
||||||
|
<Dialog.Close>
|
||||||
|
<Button color="red">Cancel</Button>
|
||||||
|
</Dialog.Close>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Popover.Content>
|
</Dialog.Content>
|
||||||
</Popover.Root>
|
</Dialog.Root>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Select.Root
|
<Select.Root
|
||||||
@@ -312,6 +378,7 @@ export default function Page() {
|
|||||||
score={player.score}
|
score={player.score}
|
||||||
clan={clanCache[region][player.id]}
|
clan={clanCache[region][player.id]}
|
||||||
key={player.id}
|
key={player.id}
|
||||||
|
highlight={highlightedPlayerId === player.id}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in new issue
Block a user