From f1b7f28fe352f4a1d2a1780d35e37592eeeef53f Mon Sep 17 00:00:00 2001 From: glax Date: Mon, 26 May 2025 19:53:26 +0200 Subject: [PATCH] PlayerStatsDrawer.tsx --- src/App.tsx | 22 +++-- src/api/endpoints/TimeTrack.tsx | 4 +- src/components/GameAccordionItem.tsx | 4 +- src/components/PlayerAccordionItem.tsx | 6 +- ...tsDrawer.tsx => PlayerGameStatsDrawer.tsx} | 2 +- src/components/PlayerStatsDrawer.tsx | 88 +++++++++++++++++++ 6 files changed, 111 insertions(+), 15 deletions(-) rename src/components/{StatsDrawer.tsx => PlayerGameStatsDrawer.tsx} (89%) create mode 100644 src/components/PlayerStatsDrawer.tsx diff --git a/src/App.tsx b/src/App.tsx index 19cd0d5..3dc3645 100644 --- a/src/App.tsx +++ b/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("http://127.0.0.1:5239"); @@ -29,12 +30,18 @@ export default function App() { const [selectedPlayer, setSelectedPlayer] = useState(null); const [selectedGame, setSelectedGame] = useState(null); - const [open, setOpen] = useState(false); + const [openPlayerGameStats, setOpenPlayerGameStats] = useState(false); + const [openPlayerStats, setOpenPlayerStats] = useState(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() { Players - {players?.map((player) => )} + {players?.map((player) => )} Games - {games?.map((game) => )} + {games?.map((game) => )} - + + diff --git a/src/api/endpoints/TimeTrack.tsx b/src/api/endpoints/TimeTrack.tsx index 02dc2a3..c57e404 100644 --- a/src/api/endpoints/TimeTrack.tsx +++ b/src/api/endpoints/TimeTrack.tsx @@ -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>; + 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>; + return getData(`${apiUri}/TimeTrack/${steamId}/Total/PerGame`) as Promise<{key: bigint, value: bigint}[]>; } diff --git a/src/components/GameAccordionItem.tsx b/src/components/GameAccordionItem.tsx index 5300a61..fea179a 100644 --- a/src/components/GameAccordionItem.tsx +++ b/src/components/GameAccordionItem.tsx @@ -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([]); @@ -39,7 +39,7 @@ export default function GameAccordionItem({game, OpenDrawer} : {game: IGame, Ope {loading ? - : players?.map((player) => OpenDrawer(player, game)} />)} + : players?.map((player) => OpenPlayerGameStatsDrawer(player, game)} />)} diff --git a/src/components/PlayerAccordionItem.tsx b/src/components/PlayerAccordionItem.tsx index 3550817..ad803c5 100644 --- a/src/components/PlayerAccordionItem.tsx +++ b/src/components/PlayerAccordionItem.tsx @@ -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([]); @@ -41,13 +41,13 @@ export default function PlayerAccordionItem({player, OpenDrawer} : {player: IPla - + Total Time: {totalTime} {loadingGames ? - : games?.map((game) => OpenDrawer(player, game)} />)} + : games?.map((game) => OpenPlayerGameStatsDrawer(player, game)} />)} diff --git a/src/components/StatsDrawer.tsx b/src/components/PlayerGameStatsDrawer.tsx similarity index 89% rename from src/components/StatsDrawer.tsx rename to src/components/PlayerGameStatsDrawer.tsx index 61c6bf0..744fafb 100644 --- a/src/components/StatsDrawer.tsx +++ b/src/components/PlayerGameStatsDrawer.tsx @@ -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}) { +export default function PlayerGameStatsDrawer({player, game, open, setOpen} : {player: IPlayer | null, game: IGame | null, open: boolean, setOpen: Dispatch}) { const apiUri = useContext(ApiUriContext); diff --git a/src/components/PlayerStatsDrawer.tsx b/src/components/PlayerStatsDrawer.tsx new file mode 100644 index 0000000..c3837eb --- /dev/null +++ b/src/components/PlayerStatsDrawer.tsx @@ -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 +}) { + + const apiUri = useContext(ApiUriContext); + const games = useContext(GamesContext); + + const [trackedTimes, setTrackedTimes] = useState[]>([]); + const [availableSeries, setAvailableSeries] = useState([]); + const [selectedSeries, setSelectedSeries] = useState([]); + + useEffect(() => { + if (!open || !player) + return; + GetTimelines(apiUri, player.steamId) + .then((tt) => { + const times: DatasetElementType[] = []; + const g: Set = new Set(); + 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 ( + setOpen(false)}> + + + + + + + (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); + }} + /> + + + + + ); +} \ No newline at end of file