Match modal renders correct info

This commit is contained in:
Kalle (Sendou) 2022-01-19 08:37:27 +02:00
parent 7c7140f046
commit 487f0e27fb
7 changed files with 71 additions and 32 deletions

View File

@ -26,8 +26,8 @@ export function DuringMatchActionsRosters({
<Form method="post" className="width-full">
<div>
<TeamRosterInputs
teamOne={ownTeam}
teamTwo={opponentTeam}
teamUpper={ownTeam}
teamLower={opponentTeam}
winnerId={winnerId}
setWinnerId={setWinnerId}
checkedPlayers={checkedPlayers}

View File

@ -17,6 +17,8 @@ export interface TeamRosterInputTeam {
}[];
}
export type TeamRosterInputsType = "DEFAULT" | "DISABLED" | "PRESENTATIONAL";
/** Inputs to select who played for teams in a match as well as the winner. Can also be used in a presentational way. */
export function TeamRosterInputs({
teamUpper,
@ -25,7 +27,7 @@ export function TeamRosterInputs({
setWinnerId,
checkedPlayers,
setCheckedPlayers,
interactable = true,
presentational = false,
}: {
teamUpper: TeamRosterInputTeam;
teamLower: TeamRosterInputTeam;
@ -33,8 +35,21 @@ export function TeamRosterInputs({
setWinnerId: (newId: string) => void;
checkedPlayers: [string[], string[]];
setCheckedPlayers: React.Dispatch<React.SetStateAction<[string[], string[]]>>;
interactable?: boolean;
presentational?: boolean;
}) {
const inputMode = (team: TeamRosterInputTeam): TeamRosterInputsType => {
if (presentational) return "PRESENTATIONAL";
// Disabled in this case because we expect a result to have exactly
// TOURNAMENT_TEAM_ROSTER_MIN_SIZE members per team when reporting it
// so there is no point to let user to change them around
if (team.members.length <= TOURNAMENT_TEAM_ROSTER_MIN_SIZE) {
return "DISABLED";
}
return "DEFAULT";
};
return (
<div className="tournament-bracket__during-match-actions__rosters">
{[teamUpper, teamLower].map((team, teamI) => (
@ -44,7 +59,6 @@ export function TeamRosterInputs({
<input
type="radio"
id={team.id}
name="winnerTeamId"
onChange={() => setWinnerId(team.id)}
checked={winnerId === team.id}
/>
@ -55,7 +69,7 @@ export function TeamRosterInputs({
<TeamRosterInputsCheckboxes
team={team}
checkedPlayers={checkedPlayers[teamI]}
disabled={team.members.length <= TOURNAMENT_TEAM_ROSTER_MIN_SIZE}
mode={inputMode(team)}
handlePlayerClick={(playerId: string) =>
setCheckedPlayers((players) => {
const newPlayers = clone(players);

View File

@ -1,18 +1,18 @@
import clsx from "clsx";
import { TOURNAMENT_TEAM_ROSTER_MIN_SIZE } from "~/constants";
import { Label } from "../Label";
import { TeamRosterInputTeam } from "./TeamRosterInputs";
import { TeamRosterInputsType, TeamRosterInputTeam } from "./TeamRosterInputs";
export function TeamRosterInputsCheckboxes({
team,
checkedPlayers,
handlePlayerClick,
disabled,
mode,
}: {
team: TeamRosterInputTeam;
checkedPlayers: string[];
handlePlayerClick: (playerId: string) => void;
disabled: boolean;
/** DEFAULT = inputs work, DISABLED = inputs disabled and look disabled, PRESENTATION = inputs disabled but look like in DEFAULT (without hover styles) */
mode: TeamRosterInputsType;
}) {
return (
<div className="tournament-bracket__during-match-actions__team-players">
@ -21,7 +21,8 @@ export function TeamRosterInputsCheckboxes({
key={member.id}
className={clsx(
"tournament-bracket__during-match-actions__checkbox-name",
{ "disabled-opaque": disabled }
{ "disabled-opaque": mode === "DISABLED" },
{ presentational: mode === "PRESENTATIONAL" }
)}
>
<input
@ -29,7 +30,7 @@ export function TeamRosterInputsCheckboxes({
type="checkbox"
id={member.id}
name="playerName"
disabled={team.members.length === TOURNAMENT_TEAM_ROSTER_MIN_SIZE}
disabled={mode === "DISABLED" || mode === "PRESENTATIONAL"}
value={member.id}
checked={checkedPlayers.flat().includes(member.id)}
onChange={() => handlePlayerClick(member.id)}

View File

@ -1,6 +1,5 @@
import type {
Mode,
TeamOrder,
TournamentMatchGameResult,
TournamentTeamMember,
User,
@ -19,7 +18,7 @@ export type FindMatchModalInfoByNumber =
idForReact: string;
teamUpper: TeamRosterInputTeam;
teamLower: TeamRosterInputTeam;
winner?: TeamOrder;
winnerId?: string;
stage: { name: string; mode: Mode };
}[];
}
@ -92,7 +91,11 @@ export async function findMatchModalInfoByNumber({
id: lowerTeam.teamId,
members: membersWithPlayedInfo.lowerTeamMembers,
},
winner: stageResult?.winner,
winnerId: stageResult
? stageResult.winner === "UPPER"
? upperTeam.teamId
: lowerTeam.teamId
: undefined,
stage: {
name: tournamentRoundStage.stage.name,
mode: tournamentRoundStage.stage.mode,

View File

@ -1,4 +1,10 @@
import { json, LoaderFunction, useLoaderData, useLocation } from "remix";
import {
json,
LinksFunction,
LoaderFunction,
useLoaderData,
useLocation,
} from "remix";
import { z } from "zod";
import Modal from "~/components/Modal";
import { TeamRosterInputs } from "~/components/tournament/TeamRosterInputs";
@ -7,6 +13,11 @@ import {
findMatchModalInfoByNumber,
} from "~/db/tournament/queries/findMatchModalInfoByNumber";
import { Unpacked } from "~/utils";
import styles from "~/styles/tournament-match.css";
export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: styles }];
};
const typedJson = (args: NonNullable<FindMatchModalInfoByNumber>) => json(args);
@ -28,20 +39,24 @@ export default function MatchModal() {
return (
<Modal title={data.title} closeUrl={location.pathname.split("/match")[0]}>
<h4>{data.roundName}</h4>
{data.matchInfos
.filter((matchInfo) => matchInfo.winner)
.map((matchInfo) => {
return (
<TeamRosterInputs
key={matchInfo.idForReact}
teamUpper={matchInfo.teamUpper}
teamLower={matchInfo.teamLower}
checkedPlayers={matchInfoToCheckedPlayers(matchInfo)}
setCheckedPlayers={() => null}
setWinnerId={() => null}
/>
);
})}
<div className="tournament-match-modal__rounds">
{data.matchInfos
.filter((matchInfo) => matchInfo.winnerId)
.map((matchInfo) => {
return (
<TeamRosterInputs
key={matchInfo.idForReact}
teamUpper={matchInfo.teamUpper}
teamLower={matchInfo.teamLower}
checkedPlayers={matchInfoToCheckedPlayers(matchInfo)}
setCheckedPlayers={() => null}
setWinnerId={() => null}
winnerId={matchInfo.winnerId}
presentational
/>
);
})}
</div>
</Modal>
);
}

View File

@ -152,11 +152,11 @@
display: flex;
width: 100%;
align-items: center;
cursor: pointer;
}
.tournament-bracket__during-match-actions__checkbox-name:not(.disabled-opaque):hover {
.tournament-bracket__during-match-actions__checkbox-name:not(.disabled-opaque):not(.presentational):hover {
border-radius: var(--rounded);
cursor: pointer;
outline: 2px solid var(--theme-transparent);
outline-offset: 2px;
}

View File

@ -0,0 +1,6 @@
.tournament-match-modal__rounds {
display: flex;
flex-direction: column;
gap: var(--s-8);
margin-block-start: var(--s-4);
}