Add Season 13 data

This commit is contained in:
Kalle
2026-08-29 18:14:59 +03:00
parent abe022c452
commit ec42e0f7b1
4 changed files with 96 additions and 57 deletions

View File

@@ -205,19 +205,10 @@ function TournamentShowcase() {
}
function ResultHighlights() {
const { t } = useTranslation(["front", "common"]);
const data = useLoaderData<typeof loader>();
// should not happen
if (
!data.leaderboards.team.length ||
!data.leaderboards.user.length ||
!data.tournaments.results.length
) {
return null;
}
const season = Seasons.currentOrPrevious()!;
const hasLeaderboards =
data.leaderboards.user.length > 0 && data.leaderboards.team.length > 0;
return (
<>
@@ -229,52 +220,74 @@ function ResultHighlights() {
)}
>
<SeasonCard />
<div className="stack sm text-center">
<h2 className={styles.resultHighlightsTitle}>
{t("front:leaderboards.topPlayers")}
</h2>
<Leaderboard
entries={data.leaderboards.user}
fullLeaderboardUrl={leaderboardsPage({
season: season.nth,
type: "USER",
})}
/>
</div>
<div className="stack sm text-center">
<h2 className={styles.resultHighlightsTitle}>
{t("front:leaderboards.topTeams")}
</h2>
<Leaderboard
entries={data.leaderboards.team}
fullLeaderboardUrl={leaderboardsPage({
season: season.nth,
type: "TEAM",
})}
/>
</div>
{hasLeaderboards ? <Leaderboards /> : null}
</div>
<div className={clsx(styles.resultHighlights, "scrollbar")}>
<div className="stack sm text-center">
<h2
className={clsx(
styles.resultHighlightsTitle,
styles.resultHighlightsTitleTournaments,
)}
>
{t("front:showcase.results")}
</h2>
<div className={clsx(styles.tournamentCardsSpacer, "scrollbar")}>
{data.tournaments.results.map((tournament) => (
<TournamentCard key={tournament.id} tournament={tournament} />
))}
</div>
</div>
{data.tournaments.results.length > 0 ? <TournamentResults /> : null}
</>
);
}
function Leaderboards() {
const { t } = useTranslation(["front"]);
const data = useLoaderData<typeof loader>();
const season = Seasons.currentOrPrevious()!;
return (
<>
<div className="stack sm text-center">
<h2 className={styles.resultHighlightsTitle}>
{t("front:leaderboards.topPlayers")}
</h2>
<Leaderboard
entries={data.leaderboards.user}
fullLeaderboardUrl={leaderboardsPage({
season: season.nth,
type: "USER",
})}
/>
</div>
<div className="stack sm text-center">
<h2 className={styles.resultHighlightsTitle}>
{t("front:leaderboards.topTeams")}
</h2>
<Leaderboard
entries={data.leaderboards.team}
fullLeaderboardUrl={leaderboardsPage({
season: season.nth,
type: "TEAM",
})}
/>
</div>
</>
);
}
function TournamentResults() {
const { t } = useTranslation(["front"]);
const data = useLoaderData<typeof loader>();
return (
<div className={clsx(styles.resultHighlights, "scrollbar")}>
<div className="stack sm text-center">
<h2
className={clsx(
styles.resultHighlightsTitle,
styles.resultHighlightsTitleTournaments,
)}
>
{t("front:showcase.results")}
</h2>
<div className={clsx(styles.tournamentCardsSpacer, "scrollbar")}>
{data.tournaments.results.map((tournament) => (
<TournamentCard key={tournament.id} tournament={tournament} />
))}
</div>
</div>
</div>
);
}
function Leaderboard({
entries,
fullLeaderboardUrl,

View File

@@ -106,6 +106,11 @@ export const list =
starts: new Date("2026-06-01T17:00:00.000Z"),
ends: new Date("2026-08-23T22:00:00.000Z"),
},
{
nth: 13,
starts: new Date("2026-09-01T17:00:00.000Z"),
ends: new Date("2026-11-22T22:00:00.000Z"),
},
] as const);
/**

View File

@@ -2,11 +2,21 @@ import { afterAll, beforeAll, vi } from "vitest";
import * as Seasons from "~/features/mmr/core/Seasons";
import invariant from "~/utils/invariant";
const lastSeason = Seasons.list[Seasons.list.length - 1];
invariant(lastSeason, "Expected at least one season");
const startedSeasons = Seasons.list.filter(
(season) => season.starts.getTime() <= Date.now(),
);
const latestStartedSeason = startedSeasons[startedSeasons.length - 1];
invariant(latestStartedSeason, "Expected at least one started season");
// the database stamps its own rows with the real "now", so a pinned time in the
// future would make every one of them look long expired
const insideASeason = new Date(
(lastSeason.starts.getTime() + lastSeason.ends.getTime()) / 2,
Math.min(
(latestStartedSeason.starts.getTime() +
latestStartedSeason.ends.getTime()) /
2,
Date.now(),
),
);
/**

View File

@@ -74,8 +74,8 @@
.seasonBannerImg {
position: absolute;
width: 109px;
right: -5px;
width: 84px;
right: 4px;
bottom: 0;
}
@@ -180,6 +180,12 @@
.resultHighlightsTop {
--card-width: 100%;
overflow-x: auto;
/* on a season's first day the leaderboards are still empty, leaving the card
alone in the row with nothing beside it to stretch against */
& > .seasonCardDesktopOnly:only-child {
max-width: 25%;
}
}
.resultHighlightsTitle {
@@ -194,6 +200,11 @@
.seasonCard {
--l: 50%;
/* see .resultHighlightsTop: alone in the row it collapses to its text */
.seasonCardDesktopOnly:only-child & {
min-height: 250px;
}
min-width: var(--card-width);
max-width: var(--card-width);
flex: 1;
@@ -232,7 +243,7 @@
.seasonCardImg {
position: absolute;
width: 175px;
width: 150px;
bottom: 0;
right: 10px;
}