Roster shown on manage roster page

This commit is contained in:
Kalle (Sendou)
2021-11-29 12:52:33 +02:00
parent 79c378a2c8
commit 5fd79e2e96
7 changed files with 135 additions and 118 deletions

View File

@@ -0,0 +1,36 @@
import type { FindTournamentByNameForUrlI } from "~/services/tournament";
import { Unpacked } from "~/utils";
export function TeamRoster({
team,
}: {
team: Unpacked<FindTournamentByNameForUrlI["teams"]>;
}) {
return (
<div className="teams-tab__team-container">
<div className="teams-tab__team-name">{team.name}</div>
<div className="teams-tab__members-container">
{team.members.map(({ member, captain }, i) => (
<div key={member.id} className="teams-tab__member">
<div className="teams-tab__member__order-number">
{captain ? "C" : i + 1}
</div>
<div className="teams-tab__member__container">
<div className="teams-tab__member__placeholder">
{member.discordAvatar && (
<img
alt=""
className="teams-tab__member__avatar"
loading="lazy"
src={`https://cdn.discordapp.com/avatars/${member.discordId}/${member.discordAvatar}.png?size=80`}
/>
)}
</div>
<div>{member.discordName}</div>
</div>
</div>
))}
</div>
</div>
);
}

View File

@@ -13,6 +13,7 @@ import {
} from "remix";
import invariant from "tiny-invariant";
import ErrorMessage from "~/components/ErrorMessage";
import { TeamRoster } from "~/components/tournament/TeamRoster";
import {
createTournamentTeam,
FindTournamentByNameForUrlI,
@@ -91,8 +92,6 @@ export default function RegisterPage() {
const location = useLocation();
const user = useUser();
console.log("tournamentData", tournamentData);
// TODO: redirect if tournament has concluded
if (!user) {
@@ -170,7 +169,8 @@ function AddPlayersPage() {
if (!ownTeam) return null;
return (
<>
<div className="tournament__invite-players">
<TeamRoster team={ownTeam} />
<div className="tournament__invite-players__actions-container">
<div>
<label>Add players you previously played with</label>
@@ -196,6 +196,6 @@ function AddPlayersPage() {
</button>
</div>
</div>
</>
</div>
);
}

View File

@@ -1,11 +1,6 @@
import { useMatches, LinksFunction } from "remix";
import type { FindTournamentByNameForUrlI } from "~/services/tournament";
import styles from "~/styles/tournament-teams.css";
import { Fragment } from "react";
export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: styles }];
};
import { TeamRoster } from "~/components/tournament/TeamRoster";
export default function TeamsTab() {
const [, parentRoute] = useMatches();
@@ -25,37 +20,9 @@ export default function TeamsTab() {
return (
<div className="teams-tab">
<div>
<div className="teams-tab__teams-container">
{sortedTeams.map((team) => (
<Fragment key={team.id}>
<div className="teams-tab__team-name">{team.name}</div>
<div className="teams-tab__members-container">
{team.members.map(({ member, captain }, i) => (
<div key={member.id} className="teams-tab__member">
<div className="teams-tab__member__order-number">
{captain ? "C" : i + 1}
</div>
<div className="teams-tab__member__container">
<div className="teams-tab__member__placeholder">
{member.discordAvatar && (
<img
alt=""
className="teams-tab__member__avatar"
loading="lazy"
src={`https://cdn.discordapp.com/avatars/${member.discordId}/${member.discordAvatar}.png?size=80`}
/>
)}
</div>
<div>{member.discordName}</div>
</div>
</div>
))}
</div>
</Fragment>
))}
</div>
</div>
{sortedTeams.map((team) => (
<TeamRoster team={team} key={team.id} />
))}
</div>
);
}

View File

@@ -21,6 +21,13 @@
margin-block-start: var(--s-6);
}
.tournament__invite-players {
display: flex;
flex-direction: column;
gap: var(--s-10);
margin-block-start: var(--s-4);
}
.tournament__invite-players__actions-container {
display: grid;
grid-template-columns: 1fr 1fr;

View File

@@ -1,77 +0,0 @@
.teams-tab {
display: flex;
flex-direction: column;
gap: var(--s-10);
}
.teams-tab__teams-container {
display: grid;
column-gap: var(--s-6);
grid-template-columns: 1fr;
row-gap: var(--s-10);
}
.teams-tab__team-name {
display: flex;
align-self: center;
border-block-end: 2px solid var(--theme);
font-size: var(--fonts-lg);
font-weight: var(--extra-bold);
justify-self: center;
}
.teams-tab__members-container {
display: flex;
flex-direction: column;
gap: var(--s-4);
}
.teams-tab__member {
display: flex;
align-items: center;
gap: var(--s-3);
}
.teams-tab__member__order-number {
color: var(--theme-secondary);
font-size: var(--fonts-sm);
font-weight: bold;
}
.teams-tab__member__container {
display: flex;
align-items: center;
font-weight: var(--semi-bold);
gap: var(--s-3);
}
.teams-tab__member__avatar {
block-size: 2.5rem;
border-radius: var(--rounded);
filter: none;
inline-size: 2.5rem;
text-indent: -10000px;
}
.teams-tab__member__placeholder {
background-image: url("/svg/background-pattern.svg");
block-size: 2.5rem;
border-radius: var(--rounded);
inline-size: 2.5rem;
}
@media screen and (min-width: 640px) {
.teams-tab__teams-container {
grid-template-columns: 1fr 1fr;
}
.teams-tab__team-name {
border-bottom: none;
justify-self: flex-end;
}
.teams-tab__members-container {
border-inline-start: 2px solid var(--theme);
padding-inline-start: var(--s-6);
}
}

View File

@@ -153,6 +153,68 @@
transform: translateY(1px);
}
.teams-tab {
display: flex;
flex-direction: column;
gap: var(--s-10);
}
.teams-tab__team-container {
display: grid;
column-gap: var(--s-6);
grid-template-columns: 1fr;
row-gap: var(--s-10);
}
.teams-tab__team-name {
display: flex;
align-self: center;
border-block-end: 2px solid var(--theme);
font-size: var(--fonts-lg);
font-weight: var(--extra-bold);
justify-self: center;
}
.teams-tab__members-container {
display: flex;
flex-direction: column;
gap: var(--s-4);
}
.teams-tab__member {
display: flex;
align-items: center;
gap: var(--s-3);
}
.teams-tab__member__order-number {
color: var(--theme-secondary);
font-size: var(--fonts-sm);
font-weight: bold;
}
.teams-tab__member__container {
display: flex;
align-items: center;
font-weight: var(--semi-bold);
gap: var(--s-3);
}
.teams-tab__member__avatar {
block-size: 2.5rem;
border-radius: var(--rounded);
filter: none;
inline-size: 2.5rem;
text-indent: -10000px;
}
.teams-tab__member__placeholder {
background-image: url("/svg/background-pattern.svg");
block-size: 2.5rem;
border-radius: var(--rounded);
inline-size: 2.5rem;
}
@media screen and (min-width: 480px) {
.tournament__links-container {
grid-template-columns: repeat(3, 100px);
@@ -172,6 +234,20 @@
flex-direction: row;
align-items: flex-end;
}
.teams-tab__team-container {
grid-template-columns: 1fr 1fr;
}
.teams-tab__team-name {
border-bottom: none;
justify-self: flex-end;
}
.teams-tab__members-container {
border-inline-start: 2px solid var(--theme);
padding-inline-start: var(--s-6);
}
}
@media screen and (min-width: 768px) {

View File

@@ -36,5 +36,13 @@ export type Serialized<T> = {
[P in keyof T]: T[P] extends Date ? string : Serialized<T[P]>;
};
export type Unpacked<T> = T extends (infer U)[]
? U
: T extends (...args: any[]) => infer U
? U
: T extends Promise<infer U>
? U
: T;
// TODO:
// export type InferredSerializedAPI<T> = Serialized<Prisma.PromiseReturnType<T>>;