Skip to content

Commit

Permalink
Merge pull request #121 from daithihearn/feature/admin-game-stats
Browse files Browse the repository at this point in the history
Adding switched for games stats
  • Loading branch information
daithihearn authored Feb 26, 2023
2 parents adf505c + 978b40a commit e208af8
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 34 deletions.
75 changes: 46 additions & 29 deletions src/components/GameStats/GameStats.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,64 @@
import { Doughnut } from "react-chartjs-2"
import { Card, CardHeader, CardBody, CardGroup, Input, Label } from "reactstrap"
import { useCallback, useState } from "react"
import { useCallback, useMemo, useState } from "react"
import { useAppSelector } from "../../caches/hooks"
import { getGameStats } from "../../caches/GameStatsSlice"
import "chart.js/auto"
import { ChartOptions } from "chart.js"
import { getMyProfile } from "../../caches/MyProfileSlice"
import PlayerSwitcher from "./PlayerSwitcher"

const GameStats = () => {
const myProfile = useAppSelector(getMyProfile)
const stats = useAppSelector(getGameStats)

const [last3Months, updateLast3Months] = useState(false)

const fromDate = new Date()
fromDate.setMonth(fromDate.getMonth() - 3)

const filteredStats = last3Months
? stats.filter(s => new Date(s.timestamp) >= fromDate)
: stats
const wins = filteredStats.filter(g => g.winner)
const data = {
labels: ["Win", "Loss"],
datasets: [
{
label: "My Win Percentage",
data: [wins.length, filteredStats.length - wins.length],
backgroundColor: ["rgb(54, 162, 235)", "rgb(255, 99, 132)"],
hoverOffset: 4,
},
],
}
const filteredStats = useMemo(
() =>
last3Months
? stats.filter(s => new Date(s.timestamp) >= fromDate)
: stats,
[stats],
)

const wins = useMemo(
() => filteredStats.filter(g => g.winner),
[filteredStats],
)

const data = useMemo(() => {
return {
labels: ["Win", "Loss"],
datasets: [
{
label: "My Win Percentage",
data: [wins.length, filteredStats.length - wins.length],
backgroundColor: ["rgb(54, 162, 235)", "rgb(255, 99, 132)"],
hoverOffset: 4,
},
],
}
}, [wins, filteredStats])

const options: ChartOptions = {
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: `Win Percentage (${(
(wins.length / filteredStats.length) *
100
).toFixed(1)}%)`,
position: "bottom",
const options: ChartOptions = useMemo(() => {
return {
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: `Win Percentage (${(
(wins.length / filteredStats.length) *
100
).toFixed(1)}%)`,
position: "bottom",
},
},
},
}
}
}, [wins, filteredStats])

const threeMonthsCheckboxChanged = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
Expand All @@ -58,7 +74,8 @@ const GameStats = () => {
return (
<CardGroup>
<Card className="p-6 data-card">
<CardHeader tag="h2">My Stats </CardHeader>
<CardHeader tag="h2">Stats </CardHeader>
{myProfile.isAdmin ? <PlayerSwitcher /> : null}
<CardBody>
{!!stats && stats.length > 0 ? (
<Doughnut
Expand Down
60 changes: 60 additions & 0 deletions src/components/GameStats/PlayerSwitcher.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { useCallback, useEffect, useState } from "react"
import {
Dropdown,
DropdownItem,
DropdownMenu,
DropdownToggle,
} from "reactstrap"
import { useAppDispatch, useAppSelector } from "../../caches/hooks"
import { getMyProfile } from "../../caches/MyProfileSlice"
import { getPlayerProfiles } from "../../caches/PlayerProfilesSlice"
import { PlayerProfile } from "../../model/Player"
import StatsService from "../../services/StatsService"

const PlayerSwitcher: React.FC = () => {
const dispatch = useAppDispatch()
const myProfile = useAppSelector(getMyProfile)
const players = useAppSelector(getPlayerProfiles)
const [showDropdown, setShowDropdown] = useState(false)
const [currentPlayer, setCurrentPlayer] = useState<PlayerProfile>()

const toggleDropdown = useCallback(
() => setShowDropdown(!showDropdown),
[showDropdown],
)

useEffect(() => {
const me = players.find(p => p.id === myProfile.id)
if (me) setCurrentPlayer(me)
}, [myProfile])

useEffect(() => {
dispatch(StatsService.gameStatsForPlayer(currentPlayer?.id))
}, [currentPlayer])

return (
<Dropdown isOpen={showDropdown} toggle={toggleDropdown}>
<DropdownToggle data-toggle="dropdown" tag="span">
<img
alt={currentPlayer ? currentPlayer.name : ""}
src={currentPlayer ? currentPlayer.picture : ""}
className="avatar clickable"
onClick={() => setShowDropdown(true)}
/>
</DropdownToggle>
<DropdownMenu>
{players.map(p => {
return (
<DropdownItem
key={p.id}
onClick={() => setCurrentPlayer(p)}>
{p.name}
</DropdownItem>
)
})}
</DropdownMenu>
</Dropdown>
)
}

export default PlayerSwitcher
16 changes: 11 additions & 5 deletions src/services/StatsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ import { PlayerGameStats } from "../model/Player"
import { getDefaultConfig } from "../utils/AxiosUtils"

const gameStatsForPlayer =
(): AppThunk<Promise<PlayerGameStats>> => async (dispatch, getState) => {
(playerId?: string): AppThunk<Promise<PlayerGameStats>> =>
async (dispatch, getState) => {
const accessToken = getAccessToken(getState())

const response = await axios.get(
`${process.env.REACT_APP_API_URL}/api/v1/stats/gameStatsForPlayer`,
getDefaultConfig(accessToken),
)
const url = playerId
? `${
process.env.REACT_APP_API_URL
}/api/v1/admin/stats/gameStatsForPlayer?playerId=${encodeURIComponent(
playerId,
)}`
: `${process.env.REACT_APP_API_URL}/api/v1/stats/gameStatsForPlayer`

const response = await axios.get(url, getDefaultConfig(accessToken))
dispatch(updateGameStats(response.data))
return response.data
}
Expand Down

0 comments on commit e208af8

Please sign in to comment.