From 026516e9ae659a5113b149f0fcb7afb0a2dcd8d9 Mon Sep 17 00:00:00 2001 From: Jonas Simoen Date: Tue, 31 Oct 2023 12:44:11 +0100 Subject: [PATCH] feat(stats): gamestats management --- src/components/Stats/MatchStats.tsx | 50 ++++++++++ src/components/Stats/StatsStyle.ts | 26 ++++++ src/config.tsx | 2 +- .../GameStatsManagement.tsx | 91 +++++++++++++------ src/services/matchesApi.ts | 12 +-- 5 files changed, 146 insertions(+), 35 deletions(-) create mode 100644 src/components/Stats/MatchStats.tsx diff --git a/src/components/Stats/MatchStats.tsx b/src/components/Stats/MatchStats.tsx new file mode 100644 index 0000000..9ce9895 --- /dev/null +++ b/src/components/Stats/MatchStats.tsx @@ -0,0 +1,50 @@ +import { useGetMatchQuery } from "@/services/matchesApi" +import { ClubBadgeBg, ClubDetails, ClubName } from "../Calendar/CalendarStyle" +import { MatchStatsStyle } from "./StatsStyle" +import config from "@/config" + +declare type MatchStatsProps = { + matchId: number + homeScore: number + awayScore: number +} + +export const MatchStats = (props: MatchStatsProps) => { + const { data } = useGetMatchQuery(props.matchId); + return ( + // + // + // + // {/* */} + // + // + // + // + // + // + // { `${props.homeScore} - ${props.awayScore}` } + // + // + // + // + // + // + // + // + // + + + + + +
+ {`${props.homeScore} - ${props.awayScore}`} +
+ + + + +
+ ) + +} \ No newline at end of file diff --git a/src/components/Stats/StatsStyle.ts b/src/components/Stats/StatsStyle.ts index 9e0ba4a..e6d9fde 100644 --- a/src/components/Stats/StatsStyle.ts +++ b/src/components/Stats/StatsStyle.ts @@ -39,5 +39,31 @@ export const StatsStyle = styled.div ` font-weight: bold; margin: 0; } + + .team-name { + color: white; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + vertical-align: middle; + } } `; + +export const MatchStatsStyle = styled.div ` + display:flex; + justify-content: center; + background-color: ${theme.primaryContrast}; + color: white; + font-size: 15px; + + .team { + padding: 15px; + } + + .score { + display:flex; + align-items: center; + } +`; \ No newline at end of file diff --git a/src/config.tsx b/src/config.tsx index bd47f36..c92da6c 100644 --- a/src/config.tsx +++ b/src/config.tsx @@ -156,7 +156,7 @@ export default { }, { full: "Man of the Match", - slug: "MOTM", + slug: "motm", short: "MOTM", type: "bool", }, diff --git a/src/pages/GameStatsManagement/GameStatsManagement.tsx b/src/pages/GameStatsManagement/GameStatsManagement.tsx index 18e1be4..248bcc2 100644 --- a/src/pages/GameStatsManagement/GameStatsManagement.tsx +++ b/src/pages/GameStatsManagement/GameStatsManagement.tsx @@ -3,7 +3,7 @@ import { Form as CustomForm } from "@/components/UI/Form/Form"; import { Col, Row } from "@/components/UI/Grid/Grid"; import { InputNumber } from "@/components/UI/InputNumber/InputNumber"; import config from "@/config"; -import { openSuccessNotification } from "@/lib/helpers"; +import { openErrorNotification, openSuccessNotification } from "@/lib/helpers"; import { useGetMatchQuery, useGetMatchStatisticsQuery, useLazyImportMatchStatisticsQuery, useUpdateMatchStatisticsMutation } from "@/services/matchesApi"; import { useGetPlayersQuery } from "@/services/playersApi"; import { CheckOutlined, DownloadOutlined } from "@ant-design/icons"; @@ -13,6 +13,7 @@ import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { useParams } from "react-router-dom"; import { TableStyle } from "./GameStatsManagementStyle"; +import { MatchStats } from "@/components/Stats/MatchStats"; const GameStatsHeaderTable = (props: { name?: string, score: number, type: string }) => { return ( @@ -63,6 +64,7 @@ type GameStatsManagementState = { allEvents: { [n: number]: Statistic }, homeScore: number, awayScore: number, + validStats: boolean, } export const GameStatsManagement = (props: GameStatsMangementProps) => { @@ -75,6 +77,7 @@ export const GameStatsManagement = (props: GameStatsMangementProps) => { allEvents: [], homeScore: 0, awayScore: 0, + validStats: true, }); const { data: match, isFetching: matchLoading, isError: matchError, isSuccess: matchSuccess } = useGetMatchQuery(+(id || 0)); @@ -82,12 +85,10 @@ export const GameStatsManagement = (props: GameStatsMangementProps) => { const { data: stats } = useGetMatchStatisticsQuery(+(id || 0)); const [importMatchStatistics, { data: importedStats, isLoading: matchStatisticsImportLoading, isSuccess: matchStatisticsImportSuccess }] = useLazyImportMatchStatisticsQuery(); - const matchPlayers = useMemo(() => - players?.filter((p: Player) => (p.clubId === match?.home?.id) || (p.clubId === match?.away?.id)) - .sort((a: Player, b: Player) => a.clubId - b.clubId), [match, players]); - + const matchPlayers = useMemo(() => players?.filter((p: Player) => (p.clubId === match?.home?.id)).concat(players?.filter((p: Player) => (p.clubId === match?.away?.id))), [match, players]); + const splitHomeAwayPlayers = useMemo(() => matchPlayers?.findIndex((p: Player) => p.clubId === match?.away?.id), [matchPlayers, match]); const sortedEvents = useMemo(() => Object.values(state.allEvents)?.sort( - (s1: Statistic, s2: Statistic) => matchPlayers.find((v: Player) => v.externalId === s1.playerId)?.clubId - matchPlayers.find((v: Player) => v.externalId === s2.playerId)?.clubId + (s1: Statistic, s2: Statistic) => matchPlayers.find((v: Player) => v.id === s1.playerId)?.clubId - matchPlayers.find((v: Player) => v.id === s2.playerId)?.clubId ), [state.allEvents]); const [form] = Form.useForm(); @@ -100,13 +101,14 @@ export const GameStatsManagement = (props: GameStatsMangementProps) => { return { ...playerStat }; } else { return { - playerId: p.externalId, + playerId: p.id, matchId: +(id || 0), }; } }) || []; form.setFieldsValue(allStats); - setState({ ...state, allEvents: allStats }); + setState((state) => ({ ...state, allEvents: allStats })); + onFieldsChange(allStats); } }, [matchPlayers, stats]); @@ -115,10 +117,10 @@ export const GameStatsManagement = (props: GameStatsMangementProps) => { const allStats = matchPlayers?.map((p: Player) => { const playerStat = importedStats?.find((s: Statistic) => s.playerId === p.externalId); if (playerStat) { - return { ...playerStat }; + return { ...playerStat, playerId: p.id }; } else { return { - playerId: p.externalId, + playerId: p.id, matchId: +(id || 0), }; } @@ -146,17 +148,18 @@ export const GameStatsManagement = (props: GameStatsMangementProps) => { dataIndex: 'playerId', width: '6rem', render: (txt: number, rec: any, index: number) => { - const player = matchPlayers.find((v: Player) => v.externalId === txt); - const clubBadge = `${config.API_URL}/static/badges/${player.clubId === match.home.id ? match.home.externalId : match.away.externalId}.png`; + const player = matchPlayers.find((v: Player) => v.id === txt); + const clubBadge = `${config.API_URL}/static/badges/${player?.clubId === match.home.id ? match.home.externalId : match.away.externalId}.png`; ++index; return ( + {txt} ) } - } + }, ].concat(config.STATISTICS.map((stat: any) => ({ title: () => {stat.short}, dataIndex: stat.slug, @@ -179,30 +182,62 @@ export const GameStatsManagement = (props: GameStatsMangementProps) => { }))); + const onFieldsChange = (values: any) => { + const playersArray = Object.values(values); + const homePlayers = playersArray.slice(0, splitHomeAwayPlayers); + const awayPlayers = playersArray.slice(splitHomeAwayPlayers); + const homeScore = homePlayers.reduce((acc: number, value: any) => acc + (value.goals || 0), 0); + const awayScore = awayPlayers.reduce((acc: number, value: any) => acc + (value.goals || 0), 0); + const validStats = playersArray.reduce((acc: number, value: any) => acc + (value.motm || 0), 0) === 1; + + setState((state) => ({ ...state, homeScore, awayScore, validStats })); + } + + const onFormSubmit = (form: any) => { + form.validateFields() + .then((formObj: any) => Object.values(formObj).map((value: any, idx: any) => ({ ...value, playerId: matchPlayers[idx].id }))) + .then((playerStats: any) => updateMatchStats({ matchId: +(id || 0), stats: playerStats, score: { home: state.homeScore, away: state.awayScore } })) + // .then((formObj: any) => Object.values(formObj)) + // .then((playerStats: any,)) + + // updateMatchStats({ stats: Object.values(obj), matchId: +(id || 0) }) + } + useEffect(() => console.log("state", state), [state]); + return ( - - {matchStatisticsImportSuccess ? + + + { + matchStatisticsImportSuccess ? + + : + + } + { + !state.validStats && - : - } console.log(form.getFieldsValue())} - style={{ padding: "2rem 0" }} + onFieldsChange={() => onFieldsChange(form.getFieldsValue())} > {/* */} @@ -228,7 +263,7 @@ export const GameStatsManagement = (props: GameStatsMangementProps) => { - diff --git a/src/services/matchesApi.ts b/src/services/matchesApi.ts index fd25549..4ff1d62 100644 --- a/src/services/matchesApi.ts +++ b/src/services/matchesApi.ts @@ -4,7 +4,7 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; export const matchesApi = createApi({ reducerPath: "matchesApi", baseQuery: fetchBaseQuery({ baseUrl: `${config.API_URL}/matches`, credentials: "include" }), - tagTypes: ["Match", "MatchEvents", "MatchStatistics", "PlayerStats"], + tagTypes: ["Match", "MatchEvents", "MatchStatistics", "PlayerStats", "ImportedMatchStatistics"], endpoints: (builder) => ({ getMatches: builder.query({ @@ -93,11 +93,11 @@ export const matchesApi = createApi({ : ["MatchStatistics"], }), - updateMatchStatistics: builder.mutation[], matchId: number }>({ - query: ({ matchId, stats }) => ({ + updateMatchStatistics: builder.mutation[], matchId: number, score: { home: number, away: number} }>({ + query: ({ matchId, stats, score }) => ({ url: `${matchId}/stats`, method: "PUT", - body: [...stats], + body: {stats, score}, }), invalidatesTags: (res, err, arg) => [{ type: "MatchStatistics", id: arg.matchId }, { type: "Match", id: arg.matchId }, "PlayerStats"], }), @@ -115,8 +115,8 @@ export const matchesApi = createApi({ query: (matchId) => `${matchId}/stats/import`, providesTags: (res, err, arg) => res - ? [{ type: "MatchStatistics" as const, id: arg }, "MatchStatistics"] - : ["MatchStatistics"], + ? [{ type: "ImportedMatchStatistics" as const, id: arg }, "ImportedMatchStatistics"] + : ["ImportedMatchStatistics"], }), }) });