mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-26 13:17:15 -05:00
Map pools in team tab
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { useTranslation } from "~/hooks/useTranslation";
|
||||
import type { MainWeaponId, ModeShort } from "~/modules/in-game-lists";
|
||||
import type { MainWeaponId, ModeShort, StageId } from "~/modules/in-game-lists";
|
||||
import {
|
||||
mainWeaponImageUrl,
|
||||
modeImageUrl,
|
||||
outlinedMainWeaponImageUrl,
|
||||
stageImageUrl,
|
||||
} from "~/utils/urls";
|
||||
|
||||
interface ImageProps {
|
||||
@@ -101,3 +102,21 @@ export function ModeImage({ mode, testId, ...rest }: ModeImageProps) {
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
type StageImageProps = {
|
||||
stageId: StageId;
|
||||
} & Omit<ImageProps, "path" | "alt" | "title">;
|
||||
|
||||
export function StageImage({ stageId, testId, ...rest }: StageImageProps) {
|
||||
const { t } = useTranslation(["game-misc"]);
|
||||
|
||||
return (
|
||||
<Image
|
||||
{...rest}
|
||||
alt={t(`game-misc:STAGE_${stageId}`)}
|
||||
title={t(`game-misc:STAGE_${stageId}`)}
|
||||
testId={testId}
|
||||
path={stageImageUrl(stageId)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import type {
|
||||
import { parseDBJsonArray } from "~/utils/sql";
|
||||
import { TOURNAMENT } from "../tournament-constants";
|
||||
import type { Unpacked } from "~/utils/types";
|
||||
import { modesShort } from "~/modules/in-game-lists";
|
||||
|
||||
const stm = sql.prepare(/*sql*/ `
|
||||
with "TeamWithMembers" as (
|
||||
@@ -97,7 +98,15 @@ export function findTeamsByTournamentId(tournamentId: Tournament["id"]) {
|
||||
return {
|
||||
...row,
|
||||
members: parseDBJsonArray(row.members),
|
||||
mapPool: parseDBJsonArray(row.mapPool),
|
||||
mapPool: (
|
||||
parseDBJsonArray(
|
||||
row.mapPool
|
||||
) as FindTeamsByTournamentIdItem["mapPool"]
|
||||
)?.sort((a, b) => {
|
||||
if (a.mode === b.mode) return a.stageId - b.stageId;
|
||||
|
||||
return modesShort.indexOf(a.mode) - modesShort.indexOf(b.mode);
|
||||
}),
|
||||
};
|
||||
}) as FindTeamsByTournamentId
|
||||
).sort(teamSorter);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Link, useOutletContext } from "@remix-run/react";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { ModeImage, StageImage } from "~/components/Image";
|
||||
import { userPage } from "~/utils/urls";
|
||||
import type { FindTeamsByTournamentIdItem } from "../queries/findTeamsByTournamentId.server";
|
||||
import type { TournamentLoaderData } from "./to.$id";
|
||||
@@ -19,27 +20,53 @@ export default function TournamentTeamsPage() {
|
||||
function TeamWithRoster({
|
||||
team,
|
||||
}: {
|
||||
team: Pick<FindTeamsByTournamentIdItem, "members" | "name">;
|
||||
team: Pick<FindTeamsByTournamentIdItem, "members" | "name" | "mapPool">;
|
||||
}) {
|
||||
return (
|
||||
<div className="tournament__team-with-roster">
|
||||
<div className="tournament__team-with-roster__name">{team.name}</div>
|
||||
<ul className="tournament__team-with-roster__members">
|
||||
{team.members.map((member) => (
|
||||
<li
|
||||
key={member.userId}
|
||||
className="tournament__team-with-roster__member"
|
||||
>
|
||||
<Avatar user={member} size="xxs" />
|
||||
<Link
|
||||
to={userPage(member)}
|
||||
className="tournament__team-member-name"
|
||||
<div>
|
||||
<div className="tournament__team-with-roster">
|
||||
<div className="tournament__team-with-roster__name">{team.name}</div>
|
||||
<ul className="tournament__team-with-roster__members">
|
||||
{team.members.map((member) => (
|
||||
<li
|
||||
key={member.userId}
|
||||
className="tournament__team-with-roster__member"
|
||||
>
|
||||
{member.discordName}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Avatar user={member} size="xxs" />
|
||||
<Link
|
||||
to={userPage(member)}
|
||||
className="tournament__team-member-name"
|
||||
>
|
||||
{member.discordName}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
{team.mapPool && team.mapPool.length > 0 ? (
|
||||
<TeamMapPool mapPool={team.mapPool} />
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function TeamMapPool({
|
||||
mapPool,
|
||||
}: {
|
||||
mapPool: NonNullable<FindTeamsByTournamentIdItem["mapPool"]>;
|
||||
}) {
|
||||
return (
|
||||
<div className="tournament__team-with-roster__map-pool">
|
||||
{mapPool.map(({ mode, stageId }, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<StageImage stageId={stageId} width={85} />
|
||||
<div className="tournament__team-with-roster__map-pool__mode-info">
|
||||
<ModeImage mode={mode} size={16} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
gap: var(--s-2);
|
||||
list-style: none;
|
||||
padding-inline-start: var(--s-4);
|
||||
padding-block: var(--s-3);
|
||||
}
|
||||
|
||||
.tournament__team-with-roster__member {
|
||||
@@ -127,6 +128,27 @@
|
||||
grid-template-columns: max-content max-content 1fr;
|
||||
}
|
||||
|
||||
.tournament__team-with-roster__map-pool {
|
||||
display: grid;
|
||||
grid-template-columns: max-content max-content max-content max-content;
|
||||
border-radius: var(--rounded);
|
||||
border: 2px solid var(--theme);
|
||||
width: max-content;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tournament__team-with-roster__map-pool__mode-info {
|
||||
background-color: var(--bg-darker);
|
||||
display: flex;
|
||||
font-size: var(--fonts-xxs);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: var(--s-1);
|
||||
font-weight: var(--semi-bold);
|
||||
padding-block: var(--s-0-5);
|
||||
}
|
||||
|
||||
.tournament__team-member-name {
|
||||
overflow: hidden;
|
||||
color: var(--text);
|
||||
|
||||
Reference in New Issue
Block a user