PlayerStatsDrawer.tsx
This commit is contained in:
22
src/App.tsx
22
src/App.tsx
@ -16,8 +16,9 @@ import {
|
||||
} from "@mui/joy";
|
||||
import GameAccordionItem from "./components/GameAccordionItem.tsx";
|
||||
import PlayerAccordionItem from "./components/PlayerAccordionItem.tsx";
|
||||
import StatsDrawer from "./components/StatsDrawer.tsx";
|
||||
import PlayerGameStatsDrawer from "./components/PlayerGameStatsDrawer.tsx";
|
||||
import {Cancel, CheckCircleOutline} from '@mui/icons-material';
|
||||
import {PlayerStatsDrawer} from "./components/PlayerStatsDrawer.tsx";
|
||||
|
||||
export default function App() {
|
||||
const [apiUri, setApiUri] = useState<string>("http://127.0.0.1:5239");
|
||||
@ -29,12 +30,18 @@ export default function App() {
|
||||
|
||||
const [selectedPlayer, setSelectedPlayer] = useState<IPlayer | null>(null);
|
||||
const [selectedGame, setSelectedGame] = useState<IGame | null>(null);
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const [openPlayerGameStats, setOpenPlayerGameStats] = useState<boolean>(false);
|
||||
const [openPlayerStats, setOpenPlayerStats] = useState<boolean>(false);
|
||||
|
||||
const OpenDrawer = (player: IPlayer, game: IGame) => {
|
||||
const OpenPlayerGameStatsDrawer = (player: IPlayer, game: IGame) => {
|
||||
setSelectedPlayer(player);
|
||||
setSelectedGame(game);
|
||||
setOpen(true);
|
||||
setOpenPlayerGameStats(true);
|
||||
}
|
||||
|
||||
const OpenPlayerStatsDrawer = (player: IPlayer) => {
|
||||
setSelectedPlayer(player);
|
||||
setOpenPlayerStats(true);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -92,18 +99,19 @@ export default function App() {
|
||||
<Box sx={{width:'50%'}}>
|
||||
<Typography level={"h2"}>Players</Typography>
|
||||
<AccordionGroup>
|
||||
{players?.map((player) => <PlayerAccordionItem key={player.steamId} player={player} OpenDrawer={OpenDrawer} />)}
|
||||
{players?.map((player) => <PlayerAccordionItem key={player.steamId} player={player} OpenPlayerGameStatsDrawer={OpenPlayerGameStatsDrawer} OpenPlayerStatsDrawer={OpenPlayerStatsDrawer} />)}
|
||||
</AccordionGroup>
|
||||
</Box>
|
||||
<Divider />
|
||||
<Box sx={{width:'50%'}}>
|
||||
<Typography level={"h2"}>Games</Typography>
|
||||
<AccordionGroup>
|
||||
{games?.map((game) => <GameAccordionItem key={game.appId} game={game} OpenDrawer={OpenDrawer} />)}
|
||||
{games?.map((game) => <GameAccordionItem key={game.appId} game={game} OpenPlayerGameStatsDrawer={OpenPlayerGameStatsDrawer} />)}
|
||||
</AccordionGroup>
|
||||
</Box>
|
||||
</Stack>
|
||||
<StatsDrawer player={selectedPlayer} game={selectedGame} open={open} setOpen={setOpen} />
|
||||
<PlayerGameStatsDrawer player={selectedPlayer} game={selectedGame} open={openPlayerGameStats} setOpen={setOpenPlayerGameStats} />
|
||||
<PlayerStatsDrawer player={selectedPlayer} open={openPlayerStats} setOpen={setOpenPlayerStats} />
|
||||
</GamesContext>
|
||||
</PlayersContext.Provider>
|
||||
</ApiUriContext>
|
||||
|
@ -2,7 +2,7 @@ import {getData} from "../fetchApi.tsx";
|
||||
import type ITrackedTime from "../types/ITrackedTime.ts";
|
||||
|
||||
export function GetTimelines(apiUri: string, steamId: bigint){
|
||||
return getData(`${apiUri}/TimeTrack/${steamId}`) as Promise<Map<bigint, ITrackedTime[]>>;
|
||||
return getData(`${apiUri}/TimeTrack/${steamId}`) as Promise<{key: bigint, value: ITrackedTime[]}[]>;
|
||||
}
|
||||
|
||||
export function GetTimelineGame(apiUri: string, steamId: bigint, appId: bigint){
|
||||
@ -14,5 +14,5 @@ export function GetTotal(apiUri: string, steamId: bigint){
|
||||
}
|
||||
|
||||
export function GetTotalPerGame(apiUri: string, steamId: bigint){
|
||||
return getData(`${apiUri}/TimeTrack/${steamId}/Total/PerGame`) as Promise<Map<bigint, bigint>>;
|
||||
return getData(`${apiUri}/TimeTrack/${steamId}/Total/PerGame`) as Promise<{key: bigint, value: bigint}[]>;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import {GetPlayersOfGame} from "../api/endpoints/Data.tsx";
|
||||
import {ApiUriContext} from "../api/fetchApi.tsx";
|
||||
import PlayerCard from "./PlayerCard.tsx";
|
||||
|
||||
export default function GameAccordionItem({game, OpenDrawer} : {game: IGame, OpenDrawer : (player: IPlayer, game: IGame) => void}) {
|
||||
export default function GameAccordionItem({game, OpenPlayerGameStatsDrawer} : {game: IGame, OpenPlayerGameStatsDrawer : (player: IPlayer, game: IGame) => void}) {
|
||||
const apiUri = useContext(ApiUriContext);
|
||||
|
||||
const [players, setPlayers] = useState<IPlayer[]>([]);
|
||||
@ -39,7 +39,7 @@ export default function GameAccordionItem({game, OpenDrawer} : {game: IGame, Ope
|
||||
<Stack flexWrap={"wrap"} direction={"row"} spacing={1} useFlexGap>
|
||||
{loading
|
||||
? <CircularProgress />
|
||||
: players?.map((player) => <PlayerCard player={player} onClick={() => OpenDrawer(player, game)} />)}
|
||||
: players?.map((player) => <PlayerCard key={player.steamId} player={player} onClick={() => OpenPlayerGameStatsDrawer(player, game)} />)}
|
||||
</Stack>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
@ -12,7 +12,7 @@ import {GetGamesOfPlayer} from "../api/endpoints/Data.tsx";
|
||||
import GameCard from "./GameCard.tsx";
|
||||
import {GetTotal} from "../api/endpoints/TimeTrack.tsx";
|
||||
|
||||
export default function PlayerAccordionItem({player, OpenDrawer} : {player: IPlayer, OpenDrawer : (player: IPlayer, game: IGame) => void}) {
|
||||
export default function PlayerAccordionItem({player, OpenPlayerGameStatsDrawer, OpenPlayerStatsDrawer} : {player: IPlayer, OpenPlayerGameStatsDrawer : (player: IPlayer, game: IGame) => void, OpenPlayerStatsDrawer : (player: IPlayer) => void}) {
|
||||
const apiUri = useContext(ApiUriContext);
|
||||
|
||||
const [games, setGames] = useState<IGame[]>([]);
|
||||
@ -41,13 +41,13 @@ export default function PlayerAccordionItem({player, OpenDrawer} : {player: IPla
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Stack flexWrap={"nowrap"} direction={"row"} alignContent={"center"} spacing={2} useFlexGap marginBottom={"10px"}>
|
||||
<Button>All Games</Button>
|
||||
<Button onClick={() => OpenPlayerStatsDrawer(player)}>All Games</Button>
|
||||
<Typography level={"h4"} >Total Time: {totalTime}</Typography>
|
||||
</Stack>
|
||||
<Stack flexWrap={"wrap"} direction={"row"} spacing={1} useFlexGap>
|
||||
{loadingGames
|
||||
? <CircularProgress />
|
||||
: games?.map((game) => <GameCard game={game} onClick={() => OpenDrawer(player, game)} />)}
|
||||
: games?.map((game) => <GameCard key={game.appId} game={game} onClick={() => OpenPlayerGameStatsDrawer(player, game)} />)}
|
||||
</Stack>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
|
@ -9,7 +9,7 @@ import {LineChart} from "@mui/x-charts";
|
||||
import PlayerCard from "./PlayerCard.tsx";
|
||||
import GameCard from "./GameCard.tsx";
|
||||
|
||||
export default function StatsDrawer({player, game, open, setOpen} : {player: IPlayer | null, game: IGame | null, open: boolean, setOpen: Dispatch<boolean>}) {
|
||||
export default function PlayerGameStatsDrawer({player, game, open, setOpen} : {player: IPlayer | null, game: IGame | null, open: boolean, setOpen: Dispatch<boolean>}) {
|
||||
|
||||
const apiUri = useContext(ApiUriContext);
|
||||
|
88
src/components/PlayerStatsDrawer.tsx
Normal file
88
src/components/PlayerStatsDrawer.tsx
Normal file
@ -0,0 +1,88 @@
|
||||
import type IPlayer from "../api/types/IPlayer.ts";
|
||||
import {Autocomplete, DialogContent, DialogTitle, Drawer, ModalClose, Stack} from "@mui/joy";
|
||||
import {type Dispatch, useContext, useEffect, useState} from "react";
|
||||
import {ApiUriContext} from "../api/fetchApi.tsx";
|
||||
import {LineChart, type LineSeriesType} from "@mui/x-charts";
|
||||
import PlayerCard from "./PlayerCard.tsx";
|
||||
import {GamesContext} from "../api/contexts/GamesContext.tsx";
|
||||
import {GetTimelines} from "../api/endpoints/TimeTrack.tsx";
|
||||
import type {DatasetElementType} from "@mui/x-charts/internals";
|
||||
|
||||
export function PlayerStatsDrawer({player, open, setOpen}: {
|
||||
player: IPlayer | null,
|
||||
open: boolean,
|
||||
setOpen: Dispatch<boolean>
|
||||
}) {
|
||||
|
||||
const apiUri = useContext(ApiUriContext);
|
||||
const games = useContext(GamesContext);
|
||||
|
||||
const [trackedTimes, setTrackedTimes] = useState<DatasetElementType<string | number | Date | null | undefined>[]>([]);
|
||||
const [availableSeries, setAvailableSeries] = useState<LineSeriesType[]>([]);
|
||||
const [selectedSeries, setSelectedSeries] = useState<LineSeriesType[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open || !player)
|
||||
return;
|
||||
GetTimelines(apiUri, player.steamId)
|
||||
.then((tt) => {
|
||||
const times: DatasetElementType<string | number | Date | null | undefined>[] = [];
|
||||
const g: Set<bigint> = new Set<bigint>();
|
||||
tt.forEach((app) => {
|
||||
app.value.forEach((time) => {
|
||||
let o = {date: new Date(time.timeStamp)};
|
||||
// @ts-ignore
|
||||
o[`${app.key.toString()}`] = Number(time.timePlayed / 60)
|
||||
times.push(o);
|
||||
g.add(app.key);
|
||||
});
|
||||
});
|
||||
|
||||
const seriesTypes: LineSeriesType[] = [];
|
||||
const iterator = g.keys();
|
||||
let value = iterator.next();
|
||||
while (!value.done) {
|
||||
const appId = value.value;
|
||||
seriesTypes.push({
|
||||
type: "line",
|
||||
dataKey: appId.toString(),
|
||||
connectNulls: true,
|
||||
label: games.games.find(g => g.appId == appId)?.name ?? appId?.toString() ?? ""
|
||||
})
|
||||
value = iterator.next();
|
||||
}
|
||||
|
||||
setAvailableSeries(seriesTypes);
|
||||
setTrackedTimes(times);
|
||||
});
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<Drawer anchor={"bottom"} size={"lg"} open={open} onClose={() => setOpen(false)}>
|
||||
<ModalClose/>
|
||||
<DialogTitle>
|
||||
<PlayerCard player={player}/>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Stack direction={"column"} height={"100%"}>
|
||||
<Autocomplete multiple
|
||||
options={availableSeries.sort((a, b) => (a.label as string).localeCompare(b.label as string))}
|
||||
placeholder={"Games"}
|
||||
getOptionLabel={(opt) => opt.label as string}
|
||||
isOptionEqualToValue={(a, b) => a.dataKey == b.dataKey}
|
||||
onChange={(_, value, reason) => {
|
||||
if(reason == "selectOption" || reason == "removeOption" || reason == "clear")
|
||||
setSelectedSeries(value);
|
||||
console.log(value);
|
||||
}}
|
||||
/>
|
||||
<LineChart dataset={trackedTimes}
|
||||
xAxis={[{dataKey: "date", scaleType: "utc"}]}
|
||||
yAxis={[{dataKey: "time", scaleType: "linear"}]}
|
||||
series={selectedSeries}
|
||||
/>
|
||||
</Stack>
|
||||
</DialogContent>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user