mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-10-01 07:37:55 -05:00
Extract TeamRosterCheckboxes component
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import { Form, useMatches } from "remix";
|
||||
import { useMatches } from "remix";
|
||||
import invariant from "tiny-invariant";
|
||||
import { modesShortToLong } from "~/constants";
|
||||
import { resolveHostInfo } from "~/core/tournament/utils";
|
||||
@@ -8,9 +7,6 @@ import type {
|
||||
FindTournamentByNameForUrlI,
|
||||
} from "~/services/tournament";
|
||||
import { modeToImageUrl, Unpacked } from "~/utils";
|
||||
import { Button } from "../Button";
|
||||
import { Label } from "../Label";
|
||||
import { SubmitButton } from "../SubmitButton";
|
||||
import { ActionSectionWrapper } from "./ActionSectionWrapper";
|
||||
import { DuringMatchActionsRosters } from "./DuringMatchActionsRosters";
|
||||
|
||||
@@ -25,11 +21,6 @@ export function DuringMatchActions({
|
||||
}) {
|
||||
const [, parentRoute] = useMatches();
|
||||
const { teams, seeds } = parentRoute.data as FindTournamentByNameForUrlI;
|
||||
const [joinedRoom, setJoinedRoom] = useState(
|
||||
true ||
|
||||
(currentMatch.score?.[0] ?? 0) > 0 ||
|
||||
(currentMatch.score?.[1] ?? 0) > 0
|
||||
);
|
||||
|
||||
const opponentTeam = teams.find(
|
||||
(team) =>
|
||||
@@ -45,41 +36,47 @@ export function DuringMatchActions({
|
||||
seeds,
|
||||
});
|
||||
|
||||
if (joinedRoom) {
|
||||
const currentPosition =
|
||||
currentMatch.score?.reduce((acc, cur) => acc + cur, 1) ?? 1;
|
||||
const currentStage = currentRound.stages.find(
|
||||
(m) => m.position === currentPosition
|
||||
);
|
||||
invariant(currentStage, "currentStage is undefined");
|
||||
const { stage } = currentStage;
|
||||
const currentPosition =
|
||||
currentMatch.score?.reduce((acc, cur) => acc + cur, 1) ?? 1;
|
||||
const currentStage = currentRound.stages.find(
|
||||
(m) => m.position === currentPosition
|
||||
);
|
||||
invariant(currentStage, "currentStage is undefined");
|
||||
const { stage } = currentStage;
|
||||
|
||||
const roundInfos: string[] = [
|
||||
`Pass ${roomPass} (${weHost ? "We" : "They"} host)`,
|
||||
`Add ${friendCodeToAdd}`,
|
||||
`${currentMatch.score?.join("-")} (Bo${currentRound.stages.length})`,
|
||||
];
|
||||
const roundInfos = [
|
||||
<>
|
||||
Add <b>{friendCodeToAdd}</b>
|
||||
</>,
|
||||
<>
|
||||
Pass <b>{roomPass}</b> ({weHost ? "We" : "They"} host)
|
||||
</>,
|
||||
<>
|
||||
<b>{currentMatch.score?.join("-")}</b> (Best of{" "}
|
||||
{currentRound.stages.length})
|
||||
</>,
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="tournament-bracket__during-match-actions">
|
||||
<div className="tournament-bracket__stage-banner">
|
||||
<div className="tournament-bracket__stage-banner__top-bar">
|
||||
<h4 className="tournament-bracket__stage-banner__top-bar__header">
|
||||
<img
|
||||
className="tournament-bracket__stage-banner__top-bar__mode-image"
|
||||
src={modeToImageUrl(stage.mode)}
|
||||
/>
|
||||
{modesShortToLong[stage.mode]} on {stage.name}
|
||||
</h4>
|
||||
<h4>Stage {currentPosition}</h4>
|
||||
</div>
|
||||
return (
|
||||
<div className="tournament-bracket__during-match-actions">
|
||||
<div className="tournament-bracket__stage-banner">
|
||||
<div className="tournament-bracket__stage-banner__top-bar">
|
||||
<h4 className="tournament-bracket__stage-banner__top-bar__header">
|
||||
<img
|
||||
className="tournament-bracket__stage-banner__top-bar__mode-image"
|
||||
src={modeToImageUrl(stage.mode)}
|
||||
/>
|
||||
{modesShortToLong[stage.mode]} on {stage.name}
|
||||
</h4>
|
||||
<h4>Stage {currentPosition}</h4>
|
||||
</div>
|
||||
<div className="tournament-bracket__infos">
|
||||
{roundInfos.map((info) => (
|
||||
<div key={info}>{info}</div>
|
||||
))}
|
||||
</div>
|
||||
{/* <ActionSectionWrapper justify-center>
|
||||
</div>
|
||||
<div className="tournament-bracket__infos">
|
||||
{roundInfos.map((info) => (
|
||||
<div>{info}</div>
|
||||
))}
|
||||
</div>
|
||||
{/* <ActionSectionWrapper justify-center>
|
||||
<div className="tournament-bracket__infos">
|
||||
<Form method="post">
|
||||
<input type="hidden" name="_action" value="UNDO_REPORT_SCORE" />
|
||||
@@ -104,48 +101,14 @@ export function DuringMatchActions({
|
||||
</Form>
|
||||
</div>
|
||||
</ActionSectionWrapper> */}
|
||||
<ActionSectionWrapper>
|
||||
<DuringMatchActionsRosters
|
||||
ownTeam={ownTeam}
|
||||
opponentTeam={opponentTeam}
|
||||
matchId={currentMatch.id}
|
||||
position={currentPosition}
|
||||
/>
|
||||
</ActionSectionWrapper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ActionSectionWrapper>
|
||||
<h4 className="tournament-bracket__during-match__opponent-info">
|
||||
Opponent: {opponentTeam.name}
|
||||
</h4>
|
||||
<ol>
|
||||
<li>Add FC: {friendCodeToAdd}</li>
|
||||
{weHost ? (
|
||||
<li>
|
||||
<p>Your team hosting. Make a room (pass has to be {roomPass})</p>
|
||||
</li>
|
||||
) : (
|
||||
<li>
|
||||
<p>Their team is hosting. Join the room (pass: {roomPass})</p>
|
||||
</li>
|
||||
)}
|
||||
<li>
|
||||
<p className="button-text-paragraph">
|
||||
Click{" "}
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => setJoinedRoom(true)}
|
||||
variant="minimal-success"
|
||||
>
|
||||
here
|
||||
</Button>{" "}
|
||||
when you have completed the steps above
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</ActionSectionWrapper>
|
||||
<ActionSectionWrapper>
|
||||
<DuringMatchActionsRosters
|
||||
ownTeam={ownTeam}
|
||||
opponentTeam={opponentTeam}
|
||||
matchId={currentMatch.id}
|
||||
position={currentPosition}
|
||||
/>
|
||||
</ActionSectionWrapper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { FindTournamentByNameForUrlI } from "~/services/tournament";
|
||||
import { Unpacked } from "~/utils";
|
||||
import { Label } from "../Label";
|
||||
import { SubmitButton } from "../SubmitButton";
|
||||
import { TeamRosterCheckboxes } from "./TeamRosterCheckboxes";
|
||||
|
||||
export function DuringMatchActionsRosters({
|
||||
ownTeam,
|
||||
@@ -42,45 +43,24 @@ export function DuringMatchActionsRosters({
|
||||
Winner
|
||||
</Label>
|
||||
</div>
|
||||
<div className="tournament-bracket__during-match-actions__team-players">
|
||||
{team.members.map(({ member }) => (
|
||||
<div
|
||||
key={member.id}
|
||||
className="tournament-bracket__during-match-actions__checkbox-name"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={member.id}
|
||||
name="playerName"
|
||||
disabled={
|
||||
team.members.length === TOURNAMENT_TEAM_ROSTER_MIN_SIZE
|
||||
}
|
||||
value={member.id}
|
||||
checked={checkedPlayers.flat().includes(member.id)}
|
||||
onChange={() =>
|
||||
setCheckedPlayers((players) => {
|
||||
const newPlayers = clone(players);
|
||||
if (checkedPlayers.flat().includes(member.id)) {
|
||||
newPlayers[teamI] = newPlayers[teamI].filter(
|
||||
(id) => id !== member.id
|
||||
);
|
||||
} else {
|
||||
newPlayers[teamI].push(member.id);
|
||||
}
|
||||
<TeamRosterCheckboxes
|
||||
team={team}
|
||||
checkedPlayers={checkedPlayers[teamI]}
|
||||
handlePlayerClick={(playerId: string) =>
|
||||
setCheckedPlayers((players) => {
|
||||
const newPlayers = clone(players);
|
||||
if (checkedPlayers.flat().includes(playerId)) {
|
||||
newPlayers[teamI] = newPlayers[teamI].filter(
|
||||
(id) => id !== playerId
|
||||
);
|
||||
} else {
|
||||
newPlayers[teamI].push(playerId);
|
||||
}
|
||||
|
||||
return newPlayers;
|
||||
})
|
||||
}
|
||||
/>{" "}
|
||||
<Label
|
||||
className="tournament-bracket__during-match-actions__player-name"
|
||||
htmlFor={member.id}
|
||||
>
|
||||
{member.discordName}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
return newPlayers;
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
41
app/components/tournament/TeamRosterCheckboxes.tsx
Normal file
41
app/components/tournament/TeamRosterCheckboxes.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { TOURNAMENT_TEAM_ROSTER_MIN_SIZE } from "~/constants";
|
||||
import type { FindTournamentByNameForUrlI } from "~/services/tournament";
|
||||
import { Unpacked } from "~/utils";
|
||||
import { Label } from "../Label";
|
||||
|
||||
export function TeamRosterCheckboxes({
|
||||
team,
|
||||
checkedPlayers,
|
||||
handlePlayerClick,
|
||||
}: {
|
||||
team: Unpacked<FindTournamentByNameForUrlI["teams"]>;
|
||||
checkedPlayers: string[];
|
||||
handlePlayerClick: (playerId: string) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="tournament-bracket__during-match-actions__team-players">
|
||||
{team.members.map(({ member }) => (
|
||||
<div
|
||||
key={member.id}
|
||||
className="tournament-bracket__during-match-actions__checkbox-name"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
id={member.id}
|
||||
name="playerName"
|
||||
disabled={team.members.length === TOURNAMENT_TEAM_ROSTER_MIN_SIZE}
|
||||
value={member.id}
|
||||
checked={checkedPlayers.flat().includes(member.id)}
|
||||
onChange={() => handlePlayerClick(member.id)}
|
||||
/>{" "}
|
||||
<Label
|
||||
className="tournament-bracket__during-match-actions__player-name"
|
||||
htmlFor={member.id}
|
||||
>
|
||||
{member.discordName}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -66,8 +66,8 @@
|
||||
border-end-start-radius: var(--rounded);
|
||||
color: var(--tournaments-text);
|
||||
column-gap: var(--s-8);
|
||||
font-size: var(--fonts-xxs);
|
||||
font-weight: var(--bold);
|
||||
font-size: var(--fonts-xs);
|
||||
padding-block: 1px;
|
||||
}
|
||||
|
||||
.tournament-bracket__infos__label {
|
||||
@@ -85,7 +85,6 @@
|
||||
|
||||
.tournament-bracket__during-match-actions {
|
||||
display: grid;
|
||||
margin-top: var(--s-4);
|
||||
grid-template-areas:
|
||||
"img"
|
||||
"infos"
|
||||
|
||||
Reference in New Issue
Block a user