mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-11 05:36:10 -05:00
Fix hydration error
This commit is contained in:
@@ -1,26 +1,7 @@
|
||||
import { eliminationBracket } from "~/core/tournament/algorithms";
|
||||
import { participantCountToRoundsInfo } from "~/core/tournament/bracket";
|
||||
import {
|
||||
UseTournamentRoundsAction,
|
||||
UseTournamentRoundsState,
|
||||
UseTournamentsArgs,
|
||||
} from "./types";
|
||||
import * as React from "react";
|
||||
import { UseTournamentRoundsAction, UseTournamentRoundsState } from "./types";
|
||||
|
||||
const getInitialState = ({
|
||||
teams,
|
||||
type,
|
||||
mapPool,
|
||||
}: UseTournamentsArgs): UseTournamentRoundsState => {
|
||||
const teamCount = teams.reduce(
|
||||
(acc, cur) => acc + (cur.checkedInTime ? 1 : 0),
|
||||
0
|
||||
);
|
||||
const bracket = eliminationBracket(teamCount, type);
|
||||
return participantCountToRoundsInfo({ bracket, mapPool });
|
||||
};
|
||||
|
||||
export function useTournamentRounds(args: UseTournamentsArgs) {
|
||||
export function useTournamentRounds(initialState: UseTournamentRoundsState) {
|
||||
return React.useReducer(
|
||||
(oldState: UseTournamentRoundsState, action: UseTournamentRoundsAction) => {
|
||||
switch (action.type) {
|
||||
@@ -30,6 +11,6 @@ export function useTournamentRounds(args: UseTournamentsArgs) {
|
||||
return oldState;
|
||||
}
|
||||
},
|
||||
getInitialState(args)
|
||||
initialState
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import type { BracketType, Stage } from ".prisma/client";
|
||||
import type { Stage } from ".prisma/client";
|
||||
import type { EliminationBracket } from "~/core/tournament/bracket";
|
||||
|
||||
export interface UseTournamentsArgs {
|
||||
teams: { checkedInTime: string | null }[];
|
||||
type: BracketType;
|
||||
mapPool: Stage[];
|
||||
}
|
||||
|
||||
export type UseTournamentRoundsState = EliminationBracket<
|
||||
{
|
||||
bestOf: number;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { useMatches } from "remix";
|
||||
import type { LinksFunction } from "remix";
|
||||
import type { LinksFunction, LoaderFunction } from "remix";
|
||||
import { json, useLoaderData } from "remix";
|
||||
import invariant from "tiny-invariant";
|
||||
import { eliminationBracket } from "~/core/tournament/algorithms";
|
||||
import { participantCountToRoundsInfo } from "~/core/tournament/bracket";
|
||||
import { useTournamentRounds } from "~/hooks/useTournamentRounds";
|
||||
import type { UseTournamentRoundsState } from "~/hooks/useTournamentRounds/types";
|
||||
import type { FindTournamentByNameForUrlI } from "~/services/tournament";
|
||||
import { findTournamentByNameForUrl } from "~/services/tournament";
|
||||
import startBracketTabStylesUrl from "~/styles/tournament-start.css";
|
||||
|
||||
// 2) can change best of -> regens maps
|
||||
@@ -14,19 +17,45 @@ export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: startBracketTabStylesUrl }];
|
||||
};
|
||||
|
||||
// TODO: handle warning if check-in has not concluded
|
||||
export default function StartBracketTab() {
|
||||
const [, parentRoute] = useMatches();
|
||||
const { teams, mapPool } = parentRoute.data as FindTournamentByNameForUrlI;
|
||||
const [rounds, dispatch] = useTournamentRounds({
|
||||
mapPool,
|
||||
teams,
|
||||
// TODO: and also below don't show losers if SE
|
||||
type: "DE",
|
||||
const typedJson = (args: UseTournamentRoundsState) => json(args);
|
||||
|
||||
export const loader: LoaderFunction = async ({ params }) => {
|
||||
invariant(
|
||||
typeof params.organization === "string",
|
||||
"Expected params.organization to be string"
|
||||
);
|
||||
invariant(
|
||||
typeof params.tournament === "string",
|
||||
"Expected params.tournament to be string"
|
||||
);
|
||||
|
||||
const tournament = await findTournamentByNameForUrl({
|
||||
organizationNameForUrl: params.organization,
|
||||
tournamentNameForUrl: params.tournament,
|
||||
});
|
||||
|
||||
const teamCount = tournament.teams.reduce(
|
||||
(acc, cur) => acc + (cur.checkedInTime ? 1 : 0),
|
||||
0
|
||||
);
|
||||
|
||||
// TODO: and also below don't show losers if SE
|
||||
const bracket = eliminationBracket(teamCount, "DE");
|
||||
const result = participantCountToRoundsInfo({
|
||||
bracket,
|
||||
mapPool: tournament.mapPool,
|
||||
});
|
||||
|
||||
return typedJson(result);
|
||||
};
|
||||
|
||||
// TODO: handle warning if check-in has not concluded
|
||||
export default function StartBracketTab() {
|
||||
const initialState = useLoaderData<UseTournamentRoundsState>();
|
||||
const [rounds, dispatch] = useTournamentRounds(initialState);
|
||||
|
||||
return (
|
||||
<div style={{ width: "100%" }}>
|
||||
<div className="tournament__start__container">
|
||||
<RoundsCollection side="Winners" rounds={rounds.winners} />
|
||||
<RoundsCollection side="Losers" rounds={rounds.losers} />
|
||||
</div>
|
||||
|
||||
38
app/styles/tournament-start.css
Normal file
38
app/styles/tournament-start.css
Normal file
@@ -0,0 +1,38 @@
|
||||
.tournament__start__container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tournament__start__rounds-container {
|
||||
display: grid;
|
||||
gap: var(--s-4);
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
}
|
||||
|
||||
.tournament__start__round {
|
||||
padding: var(--s-4);
|
||||
background-color: var(--bg-lighter);
|
||||
border-radius: var(--rounded);
|
||||
}
|
||||
|
||||
.tournament__start__best-of {
|
||||
color: var(--theme-secondary);
|
||||
font-size: var(--fonts-xs);
|
||||
font-weight: var(--semi-bold);
|
||||
}
|
||||
|
||||
.tournament__start__rounds-list {
|
||||
padding-top: var(--s-2);
|
||||
padding-left: 0;
|
||||
font-size: var(--fonts-sm);
|
||||
}
|
||||
|
||||
.tournament__start__map-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-bottom: var(--s-1);
|
||||
gap: var(--s-2);
|
||||
}
|
||||
|
||||
.tournament__start__mode-image {
|
||||
width: 1.75rem;
|
||||
}
|
||||
Reference in New Issue
Block a user