Skip to content

Commit

Permalink
allow search filtering by part of username
Browse files Browse the repository at this point in the history
  • Loading branch information
zefanjajobse committed Nov 28, 2024
1 parent babfa5f commit b7f4651
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 141 deletions.
3 changes: 3 additions & 0 deletions src/api/GametoolsApi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ interface ServerLeaderboard {

interface ServerLeaderboardV2 {
gameId: string;
playernameFilter: string;
amount: string;
sort: string;
days: string;
Expand Down Expand Up @@ -449,6 +450,7 @@ export class ApiProvider extends JsonClient {

async serverLeaderboardV2({
gameId,
playernameFilter,
amount,
sort,
days
Expand All @@ -458,6 +460,7 @@ export class ApiProvider extends JsonClient {
}
return await this.getJsonMethod(`/manager/leaderboard/v2/`, {
gameId: gameId,
player_name_filter: playernameFilter,
amount: amount,
sort: sort,
days: days
Expand Down
305 changes: 164 additions & 141 deletions src/components/routes/Servers/Detailed/Leaderboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { addDays, addSeconds } from "date-fns";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { GametoolsApi } from "../../../../api/GametoolsApi";
import { ServerLeaderboardList } from "../../../../api/ReturnTypes";
import { ServerLeaderboardList, ServerLeaderboardReturn } from "../../../../api/ReturnTypes";
import "../../../../assets/scss/App.scss";
import "../../../../locales/config";
import { Box } from "../../../Materials";
Expand All @@ -20,50 +20,24 @@ export function ServerLeaderboard(
const { t } = useTranslation();
const [days, setDays] = React.useState<number>(30);
const [sortType, setSortType] = React.useState<string>("score");
const getLanguage = () => window.localStorage.i18nextLng;
const numberFormat = new Intl.NumberFormat(getLanguage());
const [adminMode] = useLocalStorage<boolean>("adminMode", false);
const [searchTerm, setSearchTerm] = React.useState<string>("");
const gameId = props.gameid;
const {
isLoading: loading,
isError: error,
data: stats,
} = useQuery({
queryKey: ["serverLeaderboardV2" + gameId + sortType + days],
queryKey: ["serverLeaderboardV2" + gameId + sortType + days + searchTerm],
queryFn: () =>
GametoolsApi.serverLeaderboardV2({
gameId: gameId,
playernameFilter: searchTerm,
amount: "50",
sort: sortType,
days: days.toString()
}),
});

const players = stats?.data;
let playerIds: number[] = [];
playerIds = playerIds.concat(
players?.map((player) => {
return player?.playerId;
}),
);

const {
isLoading: checkBanLoading,
isError: checkBanError,
data: checkBanInfo,
} = useQuery({
queryKey: ["managerCheckPlayers" + playerIds + "leaderboard"],
queryFn: () => GametoolsApi.managerCheckPlayers({ playerIds }),
});

if (loading || error) {
return (
<div className={Mainstyles.spacing}>
<h2 className={Mainstyles.title}>{t("servers.leaderboard.main")}</h2>
<p className={Mainstyles.description}>{t("loading")}</p>
</div>
);
}

return (
<div className={Mainstyles.spacing}>
Expand Down Expand Up @@ -102,119 +76,168 @@ export function ServerLeaderboard(
})}</option>
})}
</select>
<input
className="smallSearchBox"
style={{ margin: 0, marginLeft: "14px" }}
placeholder={t(`playerSearch.searchPlaceholder`)}
value={searchTerm}
onChange={(ev: React.ChangeEvent<HTMLInputElement>): void =>
setSearchTerm(ev.target.value)
}
/>
</div>
{players?.length !== 0 ? (
<Box>
{players.map((key: ServerLeaderboardList, index: number) => {
return (
<div className="column" key={index}>
<div className="row">
<a
href={`https://gametools.network/stats/pc/playerid/${key.playerId
}?game=bf1&name=${encodeURIComponent(key.name)}`}
target="_blank"
rel="noreferrer"
>
<h4 className={styles.serverPlayerName}>
{key.platoon !== "" ? `[${key.platoon}]` : ""}
{key.name}
</h4>
<CheckBan
playerId={key.playerId.toString()}
checkBanInfo={checkBanInfo}
checkBanLoading={checkBanLoading}
checkBanError={checkBanError}
adminMode={adminMode}
>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("stats.view")}
</p>
</CheckBan>
</a>
</div>
<div className="smallestPhoneRow">
<h4>{numberFormat.format(key.score)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.score")}
</p>
</div>
<div className="row">
<h4>{numberFormat.format(key.killDeath)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.killDeath")}
</p>
</div>
<div className="tabletRow">
<h4>{numberFormat.format(key.kills)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.kills")}
</p>
</div>
<div className="tabletRow">
<h4>{numberFormat.format(key.deaths)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.deaths")}
</p>
</div>
<div className="smallPhoneRow">
<h4>{numberFormat.format(key.wins)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.wins")}
</p>
</div>
<div className="smallPhoneRow">
<h4>{numberFormat.format(key.losses)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.losses")}
</p>
</div>
<div className="row">
<h4>
{key.timePlayed > 3600
? t("hourChange", {
change: addSeconds(new Date(), key.timePlayed),
})
: t("change", {
change: addSeconds(new Date(), key.timePlayed),
})}
<ServerLeaderboardData stats={stats} isLoading={loading} isError={error} />
</div>
);
}

function ServerLeaderboardData(
props: Readonly<{
stats: ServerLeaderboardReturn,
isLoading: boolean,
isError: boolean,
}>
) {
const getLanguage = () => window.localStorage.i18nextLng;
const numberFormat = new Intl.NumberFormat(getLanguage());
const [adminMode] = useLocalStorage<boolean>("adminMode", false);
const { t } = useTranslation();

const players = props.stats?.data;
let playerIds: number[] = [];
playerIds = playerIds.concat(
players?.map((player) => {
return player?.playerId;
}),
);

const {
isLoading: checkBanLoading,
isError: checkBanError,
data: checkBanInfo,
} = useQuery({
queryKey: ["managerCheckPlayers" + playerIds + "leaderboard"],
queryFn: () => GametoolsApi.managerCheckPlayers({ playerIds }),
});


if (props.isLoading || props.isError) {
return (
<p className={Mainstyles.description}>{t("loading")}</p>
);
}

return (<>
{players?.length !== 0 ? (
<Box>
{players.map((key: ServerLeaderboardList, index: number) => {
return (
<div className="column" key={index}>
<div className="row">
<a
href={`https://gametools.network/stats/pc/playerid/${key.playerId
}?game=bf1&name=${encodeURIComponent(key.name)}`}
target="_blank"
rel="noreferrer"
>
<h4 className={styles.serverPlayerName}>
{key.platoon !== "" ? `[${key.platoon}]` : ""}
{key.name}
</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
<CheckBan
playerId={key.playerId.toString()}
checkBanInfo={checkBanInfo}
checkBanLoading={checkBanLoading}
checkBanError={checkBanError}
adminMode={adminMode}
>
{t("servers.leaderboard.row.timePlayed")}
</p>
</div>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("stats.view")}
</p>
</CheckBan>
</a>
</div>
);
})}
</Box>
) : (
<Box>
<p>{t("servers.leaderboard.none")}</p>
</Box>
)}
</div>
);
<div className="smallestPhoneRow">
<h4>{numberFormat.format(key.score)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.score")}
</p>
</div>
<div className="row">
<h4>{numberFormat.format(key.killDeath)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.killDeath")}
</p>
</div>
<div className="tabletRow">
<h4>{numberFormat.format(key.kills)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.kills")}
</p>
</div>
<div className="tabletRow">
<h4>{numberFormat.format(key.deaths)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.deaths")}
</p>
</div>
<div className="smallPhoneRow">
<h4>{numberFormat.format(key.wins)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.wins")}
</p>
</div>
<div className="smallPhoneRow">
<h4>{numberFormat.format(key.losses)}</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.losses")}
</p>
</div>
<div className="row">
<h4>
{key.timePlayed > 3600
? t("hourChange", {
change: addSeconds(new Date(), key.timePlayed),
})
: t("change", {
change: addSeconds(new Date(), key.timePlayed),
})}
</h4>
<p
className={Mainstyles.description}
style={{ lineHeight: 0 }}
>
{t("servers.leaderboard.row.timePlayed")}
</p>
</div>
</div>
);
})}
</Box>
) : (
<Box>
<p>{t("servers.leaderboard.none")}</p>
</Box>
)}</>)
}

0 comments on commit b7f4651

Please sign in to comment.