From 508c5573be25b1255a65704a7b3051f88219857c Mon Sep 17 00:00:00 2001 From: james Date: Sat, 2 Apr 2022 22:25:57 +1100 Subject: [PATCH 1/6] QH-10 Collect and save doubles pairs in redux --- src/api/ApiTypes.ts | 1 + src/api/QuickHitAPI.ts | 30 ++++++++++++++++++- src/components/KeyPrompt/KeyPrompt.tsx | 3 +- src/components/QHDataLoader/QHDataLoader.tsx | 16 +++++++++- .../AchievementFeed/AchievementFeed.ts | 1 + src/containers/HallOfFallen/HallOfFallen.ts | 1 + src/containers/Ladder/Ladder.ts | 1 + src/containers/QHDataLoader/QHDataLoader.ts | 5 +++- src/containers/RecentGames/RecentGames.ts | 1 + src/containers/Tournament/Tournament.ts | 1 + src/containers/shared/index.ts | 1 + src/redux/actions/TTActions/index.ts | 14 ++++++++- src/redux/constants/TTConstants/index.ts | 3 ++ src/redux/reducers/TTReducer/index.ts | 1 + src/redux/types/TTTypes/index.ts | 3 +- src/types/database/models.ts | 5 ++++ 16 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/api/ApiTypes.ts b/src/api/ApiTypes.ts index d2d040d..6fb849f 100644 --- a/src/api/ApiTypes.ts +++ b/src/api/ApiTypes.ts @@ -10,6 +10,7 @@ export enum HttpMethod { export enum ApiActions { INSTANCES = "instances.json", PLAYERS = "player.json", + DOUBLES_PAIRS = "doubles_pair.json", MATCHES = "match.json", HAPPY_HOUR = "happyhour.json", BADGE = "badge.json", diff --git a/src/api/QuickHitAPI.ts b/src/api/QuickHitAPI.ts index 32a9d46..ebcfda8 100644 --- a/src/api/QuickHitAPI.ts +++ b/src/api/QuickHitAPI.ts @@ -1,6 +1,6 @@ import { DbBadge, - DbChatRoom, + DbChatRoom, DbDoublesPair, DbHappyHour, DbInstance, DbMatch, @@ -46,6 +46,16 @@ export class QuickHitAPI { }); } + public static getDoublesPairs(onSuccess: (doublesPairs: DbDoublesPair[]) => void, onFailure: (errorString: string) => void): void { + QuickHitAPI.makeAxiosRequest(ApiActions.DOUBLES_PAIRS, HttpMethod.GET) + .then((response: AxiosResponse) => { + onSuccess(Object.values(response.data)); + }) + .catch((error: AxiosError) => { + onFailure(error.message); + }); + } + public static getMatches(onSuccess: (matches: DbMatch[]) => void, onFailure: (errorString: string) => void): void { QuickHitAPI.makeAxiosRequest(ApiActions.MATCHES, HttpMethod.GET) .then((response: AxiosResponse) => { @@ -111,6 +121,24 @@ export class QuickHitAPI { }); } + public static addOrUpdateDoublesPair( + pairToAdd: DbDoublesPair, + onSuccess: () => void, + onFailure: (errorString: string) => void + ): void { + QuickHitAPI.makeAxiosRequest( + ApiActions.DOUBLES_PAIRS, + HttpMethod.PATCH, + `{"${pairToAdd.id}" : ${JSON.stringify(pairToAdd)}}` + ) + .then(() => { + onSuccess(); + }) + .catch((error: AxiosError) => { + onFailure(error.message); + }); + } + public static getTodaysHappyHour( onSuccess: (happyHour?: DbHappyHour) => void, onFailure: (errorString: string) => void diff --git a/src/components/KeyPrompt/KeyPrompt.tsx b/src/components/KeyPrompt/KeyPrompt.tsx index 52730f8..f0a545c 100644 --- a/src/components/KeyPrompt/KeyPrompt.tsx +++ b/src/components/KeyPrompt/KeyPrompt.tsx @@ -120,8 +120,7 @@ function KeyPrompt(props: KeyPromptProps): JSX.Element { }; }; - // Todo: use quickhitpage later - if (props.match && !(props.match.params.instance === "player")) { + if (props.match) { const instanceId = props.match.params.instance; const authKey = props.match.params.authKey; diff --git a/src/components/QHDataLoader/QHDataLoader.tsx b/src/components/QHDataLoader/QHDataLoader.tsx index 04d94be..908b800 100644 --- a/src/components/QHDataLoader/QHDataLoader.tsx +++ b/src/components/QHDataLoader/QHDataLoader.tsx @@ -8,7 +8,7 @@ import { makeErrorToast, makeRefreshToast } from "../Toast/Toast"; import { QuickHitAPI } from "../../api/QuickHitAPI"; import { Loader, Transition } from "semantic-ui-react"; import { - DbBadge, + DbBadge, DbDoublesPair, DbHappyHour, DbInstance, DbMatch, @@ -108,6 +108,19 @@ function QHDataLoader(props: QHDataLoaderProps): JSX.Element { QuickHitAPI.getPlayers(onSuccess, onFailure); }; + const getDoublesPairs = (): void => { + const onSuccess = (doublesPairs: DbDoublesPair[]): void => { + props.setDoublesPairs(doublesPairs); + }; + + const onFailure = (error: string): void => { + makeErrorToast("Could not get doubles pairs", error); + props.setLoading(false); + }; + + QuickHitAPI.getDoublesPairs(onSuccess, onFailure); + }; + const getBadges = (): void => { const onSuccess = (badges: DbBadge[]): void => { props.setBadges(badges); @@ -140,6 +153,7 @@ function QHDataLoader(props: QHDataLoaderProps): JSX.Element { getMatches(); getTournaments(); getPlayers(); + getDoublesPairs(); }; useEffect(() => { diff --git a/src/containers/AchievementFeed/AchievementFeed.ts b/src/containers/AchievementFeed/AchievementFeed.ts index 87c4cc6..732ae4b 100644 --- a/src/containers/AchievementFeed/AchievementFeed.ts +++ b/src/containers/AchievementFeed/AchievementFeed.ts @@ -21,6 +21,7 @@ export function mapStateToProps( happyHour: store.ttData.happyHour, badges: store.ttData.badges, tournaments: store.ttData.tournaments, + doublesPairs: store.ttData.doublesPairs, focusedPlayerId: ownProps.focusedPlayerId, }; } diff --git a/src/containers/HallOfFallen/HallOfFallen.ts b/src/containers/HallOfFallen/HallOfFallen.ts index 446245a..7d72b8f 100644 --- a/src/containers/HallOfFallen/HallOfFallen.ts +++ b/src/containers/HallOfFallen/HallOfFallen.ts @@ -16,6 +16,7 @@ export function mapStateToProps(store: QuickHitReduxStores): HallOfFallenReduxPr happyHour: store.ttData.happyHour, badges: store.ttData.badges, tournaments: store.ttData.tournaments, + doublesPairs: store.ttData.doublesPairs, disableMusic: store.viewStore.disableMusic, chosenInstance: store.authStore.chosenInstance, }; diff --git a/src/containers/Ladder/Ladder.ts b/src/containers/Ladder/Ladder.ts index cc16172..13f1826 100644 --- a/src/containers/Ladder/Ladder.ts +++ b/src/containers/Ladder/Ladder.ts @@ -22,6 +22,7 @@ export function mapStateToProps(store: QuickHitReduxStores): TTStoreState & View happyHour: store.ttData.happyHour, badges: store.ttData.badges, tournaments: store.ttData.tournaments, + doublesPairs: store.ttData.doublesPairs, hideUnplacedPlayers: store.viewStore.hideUnplacedPlayers, showCards: store.viewStore.showCards, disableMusic: store.viewStore.disableMusic, diff --git a/src/containers/QHDataLoader/QHDataLoader.ts b/src/containers/QHDataLoader/QHDataLoader.ts index c94b02d..4516de8 100644 --- a/src/containers/QHDataLoader/QHDataLoader.ts +++ b/src/containers/QHDataLoader/QHDataLoader.ts @@ -2,7 +2,7 @@ import { Dispatch } from "redux"; import * as actions from "../../redux/actions/TTActions"; import { connect } from "react-redux"; import QHDataLoader from "../../components/QHDataLoader/QHDataLoader"; -import { DbBadge, DbHappyHour, DbMatch, DbPlayer, DbTournament } from "../../types/database/models"; +import {DbBadge, DbDoublesPair, DbHappyHour, DbMatch, DbPlayer, DbTournament} from "../../types/database/models"; import { mapTTDataToProps, TTRefreshDispatchType } from "../shared"; export interface DataLoaderDispatchType extends TTRefreshDispatchType { @@ -12,6 +12,7 @@ export interface DataLoaderDispatchType extends TTRefreshDispatchType { setLoading: (newLoading: boolean) => void; setBadges: (newBadges: DbBadge[]) => void; setTournaments: (newTournaments: DbTournament[]) => void; + setDoublesPairs: (newDoublesPairs: DbDoublesPair[]) => void; } export function mapDispatchToProps( @@ -23,6 +24,7 @@ export function mapDispatchToProps( | actions.SetHappyHourAction | actions.SetBadgesAction | actions.SetTournamentsAction + | actions.SetDoublesPairsAction > ): DataLoaderDispatchType { return { @@ -36,6 +38,7 @@ export function mapDispatchToProps( setBadges: (newBadges: DbBadge[]): actions.SetBadgesAction => dispatch(actions.setBadges(newBadges)), setTournaments: (newTournaments: DbTournament[]): actions.SetTournamentsAction => dispatch(actions.setTournaments(newTournaments)), + setDoublesPairs: (newDoublesPairs: DbDoublesPair[]): actions.SetDoublesPairsAction => dispatch(actions.setDoublesPairs(newDoublesPairs)), }; } diff --git a/src/containers/RecentGames/RecentGames.ts b/src/containers/RecentGames/RecentGames.ts index 2665463..9336199 100644 --- a/src/containers/RecentGames/RecentGames.ts +++ b/src/containers/RecentGames/RecentGames.ts @@ -24,6 +24,7 @@ export function mapStateToProps( happyHour: store.ttData.happyHour, badges: store.ttData.badges, tournaments: store.ttData.tournaments, + doublesPairs: store.ttData.doublesPairs, currentUser: store.viewStore.currentUser, focusedPlayerId: ownProps.focusedPlayerId, }; diff --git a/src/containers/Tournament/Tournament.ts b/src/containers/Tournament/Tournament.ts index 9c82c58..30ab27f 100644 --- a/src/containers/Tournament/Tournament.ts +++ b/src/containers/Tournament/Tournament.ts @@ -15,6 +15,7 @@ export function mapStateToProps(store: QuickHitReduxStores): TournamentReduxProp refresh: store.ttData.refresh, happyHour: store.ttData.happyHour, badges: store.ttData.badges, + doublesPairs: store.ttData.doublesPairs, tournaments: store.ttData.tournaments, disableMusic: store.viewStore.disableMusic, chosenInstance: store.authStore.chosenInstance, diff --git a/src/containers/shared/index.ts b/src/containers/shared/index.ts index eab449b..9aa72f5 100644 --- a/src/containers/shared/index.ts +++ b/src/containers/shared/index.ts @@ -14,6 +14,7 @@ export function mapTTDataToProps(store: QuickHitReduxStores): TTStoreState & { c return { loading: store.ttData.loading, players: store.ttData.players, + doublesPairs: store.ttData.doublesPairs, matches: store.ttData.matches, happyHour: store.ttData.happyHour, badges: store.ttData.badges, diff --git a/src/redux/actions/TTActions/index.ts b/src/redux/actions/TTActions/index.ts index 9d5bea1..92a4b67 100644 --- a/src/redux/actions/TTActions/index.ts +++ b/src/redux/actions/TTActions/index.ts @@ -1,5 +1,5 @@ import * as constants from "../../constants/TTConstants"; -import { DbBadge, DbHappyHour, DbMatch, DbPlayer, DbTournament } from "../../../types/database/models"; +import {DbBadge, DbDoublesPair, DbHappyHour, DbMatch, DbPlayer, DbTournament} from "../../../types/database/models"; export interface SetMatchesAction { type: constants.SET_MATCHES_TYPE; @@ -36,6 +36,11 @@ export interface SetTournamentsAction { value: DbTournament[]; } +export interface SetDoublesPairsAction { + type: constants.SET_DOUBLES_PAIRS_TYPE; + value: DbDoublesPair[]; +} + export function setMatches(newMatches: DbMatch[]): SetMatchesAction { return { type: constants.SET_MATCHES, @@ -84,3 +89,10 @@ export function setTournaments(newTournaments: DbTournament[]): SetTournamentsAc value: newTournaments, }; } + +export function setDoublesPairs(newDoublesPairs: DbDoublesPair[]): SetDoublesPairsAction { + return { + type: constants.SET_DOUBLES_PAIRS, + value: newDoublesPairs, + }; +} diff --git a/src/redux/constants/TTConstants/index.ts b/src/redux/constants/TTConstants/index.ts index b3c004d..2af95b3 100644 --- a/src/redux/constants/TTConstants/index.ts +++ b/src/redux/constants/TTConstants/index.ts @@ -18,3 +18,6 @@ export type SET_BADGES_TYPE = typeof SET_BADGES; export const SET_TOURNAMENTS = "SET_TOURNAMENTS"; export type SET_TOURNAMENTS_TYPE = typeof SET_TOURNAMENTS; + +export const SET_DOUBLES_PAIRS = "SET_DOUBLES_PAIRS"; +export type SET_DOUBLES_PAIRS_TYPE = typeof SET_DOUBLES_PAIRS; diff --git a/src/redux/reducers/TTReducer/index.ts b/src/redux/reducers/TTReducer/index.ts index 1025deb..9b2da21 100644 --- a/src/redux/reducers/TTReducer/index.ts +++ b/src/redux/reducers/TTReducer/index.ts @@ -29,6 +29,7 @@ export const dataInitialState: TTStoreState = { }, badges: [], tournaments: [], + doublesPairs: [], refresh: false, }; diff --git a/src/redux/types/TTTypes/index.ts b/src/redux/types/TTTypes/index.ts index ca7cf0d..247c1ce 100644 --- a/src/redux/types/TTTypes/index.ts +++ b/src/redux/types/TTTypes/index.ts @@ -1,4 +1,4 @@ -import { DbBadge, DbHappyHour, DbMatch, DbPlayer, DbTournament } from "../../../types/database/models"; +import {DbBadge, DbDoublesPair, DbHappyHour, DbMatch, DbPlayer, DbTournament} from "../../../types/database/models"; export interface TTStoreState { matches: DbMatch[]; @@ -6,6 +6,7 @@ export interface TTStoreState { happyHour: DbHappyHour; badges: DbBadge[]; tournaments: DbTournament[]; + doublesPairs: DbDoublesPair[]; refresh: boolean; loading: boolean; } diff --git a/src/types/database/models.ts b/src/types/database/models.ts index 739074c..018d610 100644 --- a/src/types/database/models.ts +++ b/src/types/database/models.ts @@ -36,6 +36,11 @@ export interface DbPlayer { retired?: boolean; } +export interface DbDoublesPair extends DbPlayer { + player1_id: string; + player2_id: string +} + export interface DbHappyHour { /* yyyy-mm-dd */ date: string; From 8ad043055954c32b6421cf3a8c702ccee08d0bd0 Mon Sep 17 00:00:00 2001 From: james Date: Sat, 2 Apr 2022 23:05:04 +1100 Subject: [PATCH 2/6] QH-10 Rudimentary ladder impl, need to convert other pages to treat as similar --- src/App.tsx | 1 + src/components/Comparator/Comparator.tsx | 6 +- src/components/KeyPrompt/KeyPrompt.tsx | 2 - src/components/Ladder/Ladder.css | 11 ++ src/components/Ladder/Ladder.tsx | 114 +++++++++++------- src/components/Navbar/Navbar.css | 4 + src/components/Navbar/Navbar.tsx | 9 +- src/components/NewGame/NewGame.tsx | 6 +- .../PlayerStatistics/PlayerStatistics.tsx | 6 +- src/components/QHDataLoader/QHDataLoader.tsx | 3 +- src/components/RecentGames/RecentGames.tsx | 6 +- src/components/Tournament/Tournament.tsx | 3 + src/redux/reducers/TTReducer/index.ts | 7 +- src/util/QuickHitPage.ts | 1 + 14 files changed, 116 insertions(+), 63 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index b9e33a3..70430c0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -25,6 +25,7 @@ function App(): JSX.Element { + diff --git a/src/components/Comparator/Comparator.tsx b/src/components/Comparator/Comparator.tsx index c2805f1..14905b8 100644 --- a/src/components/Comparator/Comparator.tsx +++ b/src/components/Comparator/Comparator.tsx @@ -4,7 +4,7 @@ import "./Comparator.css"; import { DbPlayer, getELOString } from "../../types/database/models"; import { ComparatorStoreProps } from "../../containers/Comparator/Comparator"; import { WinLoss } from "../../types/types"; -import { getRecordAgainstPlayer, getWinLossForPlayer } from "../QHDataLoader/QHDataLoader"; +import { getRecordAgainstPlayer, getWinLossForPlayerOrPair } from "../QHDataLoader/QHDataLoader"; import { getChanceOfVictory } from "../../util/Predictor"; /** @@ -108,12 +108,12 @@ function Comparator(props: ComparatorStoreProps): JSX.Element { {playerOne && - getELOString(getWinLossForPlayer(playerOne.id, props.matches).matches, playerOne.elo)} + getELOString(getWinLossForPlayerOrPair(playerOne.id, props.matches).matches, playerOne.elo)} ELO {playerTwo && - getELOString(getWinLossForPlayer(playerTwo.id, props.matches).matches, playerTwo.elo)} + getELOString(getWinLossForPlayerOrPair(playerTwo.id, props.matches).matches, playerTwo.elo)} diff --git a/src/components/KeyPrompt/KeyPrompt.tsx b/src/components/KeyPrompt/KeyPrompt.tsx index f0a545c..f46eef7 100644 --- a/src/components/KeyPrompt/KeyPrompt.tsx +++ b/src/components/KeyPrompt/KeyPrompt.tsx @@ -24,8 +24,6 @@ export interface KeyPromptProps { setAuthKey: (newKey: string) => void; setChosenInstance: (newInstance: DbInstance) => void; setAuthDetail: (newAuthDetail?: AuthUserDetail) => void; - history?: H.History; - location?: H.Location; match?: match; } diff --git a/src/components/Ladder/Ladder.css b/src/components/Ladder/Ladder.css index 721671c..5a5e04b 100644 --- a/src/components/Ladder/Ladder.css +++ b/src/components/Ladder/Ladder.css @@ -10,6 +10,17 @@ display: block; } +.players .header .child.icon.first-child { + margin-left: -40px; + font-size: 3.6rem; +} + +.players .header .child.icon.second-child { + font-size: 3.6rem; + margin-left: 40px; + margin-top: -58px; +} + .horizontal .card { display: inline-flex; margin-left: 5px; diff --git a/src/components/Ladder/Ladder.tsx b/src/components/Ladder/Ladder.tsx index ea61db8..1403e8f 100644 --- a/src/components/Ladder/Ladder.tsx +++ b/src/components/Ladder/Ladder.tsx @@ -1,74 +1,84 @@ import "./Ladder.css"; -import { Button, Header, Icon, Table, Transition } from "semantic-ui-react"; +import {Button, Header, Icon, Segment, Table, Transition} from "semantic-ui-react"; import PlayerCard from "./PlayerCard/PlayerCard"; import NewEditPlayer from "../NewEditPlayer/NewEditPlayer"; import NewGame from "../../containers/NewGame"; -import { getWinLossForPlayer } from "../QHDataLoader/QHDataLoader"; +import { getWinLossForPlayerOrPair } from "../QHDataLoader/QHDataLoader"; import { TTDataPropsTypeCombined } from "../../containers/shared"; import { BASE_PATH, QuickHitPage } from "../../util/QuickHitPage"; import { Link } from "react-router-dom"; import { ViewDispatchType } from "../../containers/Ladder/Ladder"; import { ViewStoreState } from "../../redux/types/ViewTypes"; -import { DbPlayer, getELOString, isUnderPlacement } from "../../types/database/models"; +import {DbDoublesPair, DbPlayer, getELOString, isUnderPlacement} from "../../types/database/models"; +import * as H from "history"; + +export type LadderProps = ViewStoreState & TTDataPropsTypeCombined & ViewDispatchType & { + location: H.Location; +}; -export type LadderProps = ViewStoreState & TTDataPropsTypeCombined & ViewDispatchType; export const NUM_OF_FORM_GUIDE_MATCHES = 5; /** * QuickHit Ladder page. */ function Ladder(props: LadderProps): JSX.Element { + const isDoubles = props.location.pathname === QuickHitPage.DOUBLES_LADDER; + const renderPlayersAsCards = (): JSX.Element[] => { - const playersLadder: JSX.Element[] = []; + const ladder: JSX.Element[] = []; + + const iterable = isDoubles ? props.doublesPairs : props.players; - props.players.forEach((player) => { - if (!player.retired) { - const winLoss = getWinLossForPlayer(player.id, props.matches); + iterable.forEach((playerOrDoublesPair) => { + if (!playerOrDoublesPair.retired) { + const winLoss = getWinLossForPlayerOrPair(playerOrDoublesPair.id, props.matches); - const playerCard = ; + const playerCard = ; // If we are hiding zero game players, then only push if they have played a game if (props.hideUnplacedPlayers) { if (!isUnderPlacement(winLoss.wins + winLoss.losses)) { - playersLadder.push(playerCard); + ladder.push(playerCard); } } else { - playersLadder.push(playerCard); + ladder.push(playerCard); } } }); // Sorting the player items by elo. - playersLadder.sort((player1, player2) => { + ladder.sort((player1, player2) => { return player2.props.player.elo - player1.props.player.elo; }); - return playersLadder; + return ladder; }; const renderPlayersInTable = (): JSX.Element[] => { - const playersLadder: JSX.Element[] = []; - const playerTableRows: JSX.Element[] = []; + const ladder: JSX.Element[] = []; + const tableRows: JSX.Element[] = []; - const sortedPlayers = props.players.sort((player1, player2) => { - return player2.elo - player1.elo; + const iterable = isDoubles ? props.doublesPairs : props.players; + + const sortedIterable = iterable.sort((playerOrPair1, playerOrPair2) => { + return playerOrPair2.elo - playerOrPair1.elo; }); - const unplacedPlayerRows = []; + const unplacedPairRows = []; - for (let i = 0; i < sortedPlayers.length; i++) { - const player = sortedPlayers[i]; - const winLoss = getWinLossForPlayer(player.id, props.matches); - let addPlayer = true; + for (let i = 0; i < sortedIterable.length; i++) { + const playerOrPair = sortedIterable[i]; + const winLoss = getWinLossForPlayerOrPair(playerOrPair.id, props.matches); + let addPlayerOrPair = true; if ( (props.hideUnplacedPlayers && isUnderPlacement(winLoss.wins + winLoss.losses)) || - player.retired === true + playerOrPair.retired === true ) { - addPlayer = false; + addPlayerOrPair = false; } - if (addPlayer) { + if (addPlayerOrPair) { const formStr = winLoss && winLoss.formGuide.substr(0, NUM_OF_FORM_GUIDE_MATCHES).split("").reverse().join(""); @@ -77,16 +87,16 @@ function Ladder(props: LadderProps): JSX.Element { - {generateLadderTrendIcon(player, i, sortedPlayers)} - - {player.name} + {generateLadderTrendIcon(playerOrPair, i, sortedIterable)} + + {playerOrPair.name} - {getELOString(winLoss.wins + winLoss.losses, player.elo)} + {getELOString(winLoss.wins + winLoss.losses, playerOrPair.elo)} {winLoss.wins}-{winLoss.losses} @@ -95,14 +105,14 @@ function Ladder(props: LadderProps): JSX.Element { ); if (isUnderPlacement(winLoss.wins + winLoss.losses)) { - unplacedPlayerRows.push(row); + unplacedPairRows.push(row); } else { - playerTableRows.push(row); + tableRows.push(row); } } } - playersLadder.push( + ladder.push( @@ -113,18 +123,18 @@ function Ladder(props: LadderProps): JSX.Element { - {playerTableRows} - {unplacedPlayerRows} + {tableRows} + {unplacedPairRows}
); - return playersLadder; + return ladder; }; const generateLadderTrendIcon = ( - player: DbPlayer, + playerOrPair: DbPlayer | DbDoublesPair, positionOnLadder: number, - sortedPlayers: DbPlayer[] + sortedPlayersOrPairs: DbPlayer[] | DbDoublesPair[] ): JSX.Element => { let mostRecentMatch; let iconToReturn: JSX.Element = ; @@ -132,23 +142,23 @@ function Ladder(props: LadderProps): JSX.Element { // Find player's most recent match (assumes matches already sorted by newest) for (let i = 0; i < props.matches.length; i++) { const match = props.matches[i]; - if (match.winning_player_id === player.id || match.losing_player_id === player.id) { + if (match.winning_player_id === playerOrPair.id || match.losing_player_id === playerOrPair.id) { mostRecentMatch = match; break; } } - const winLoss = getWinLossForPlayer(player.id, props.matches); + const winLoss = getWinLossForPlayerOrPair(playerOrPair.id, props.matches); if (isUnderPlacement(winLoss.wins + winLoss.losses)) { iconToReturn = ; } else if (mostRecentMatch) { // If the most recent match was a loss - if (mostRecentMatch.losing_player_id === player.id) { + if (mostRecentMatch.losing_player_id === playerOrPair.id) { if (positionOnLadder !== 0) { let wentDown = false; // Get the player above them - const playerAboveOnLadder = sortedPlayers[positionOnLadder - 1]; + const playerAboveOnLadder = sortedPlayersOrPairs[positionOnLadder - 1]; // If the player above them was the player they versed, then use that player's original elo. if ( @@ -176,7 +186,7 @@ function Ladder(props: LadderProps): JSX.Element { // Otherwise, match was a win else { // Get the player below them - const playerBelowOnLadder = sortedPlayers[positionOnLadder + 1]; + const playerBelowOnLadder = sortedPlayersOrPairs[positionOnLadder + 1]; let wentUp = false; // If the player below them was the player they versed, then use that player's original elo. @@ -220,8 +230,22 @@ function Ladder(props: LadderProps): JSX.Element { return (
- - Ladder + {isDoubles ? + + + + + + } circular/> + Doubles ladder + + : + + + Singles ladder + + }