mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-09 12:46:10 -05:00
Roster shown on manage roster page
This commit is contained in:
36
app/components/tournament/TeamRoster.tsx
Normal file
36
app/components/tournament/TeamRoster.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>>;
|
||||
|
||||
Reference in New Issue
Block a user