mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-30 07:12:36 -05:00
Port teams tab
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import mapPoolStylesUrl from "~/styles/map-pool.css";
|
||||
import stylesUrl from "~/styles/map-pool.css";
|
||||
import type { Mode } from ".prisma/client";
|
||||
import classNames from "classnames";
|
||||
import { modesShort, stages } from "~/utils";
|
||||
@@ -6,7 +6,7 @@ import { LinksFunction, useMatches } from "remix";
|
||||
import { FindTournamentByNameForUrlI } from "../../../../services/tournament";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: mapPoolStylesUrl }];
|
||||
return [{ rel: "stylesheet", href: stylesUrl }];
|
||||
};
|
||||
|
||||
export default function MapPoolTab() {
|
||||
|
||||
88
app/routes/to/$organization.$tournament/teams.tsx
Normal file
88
app/routes/to/$organization.$tournament/teams.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import { useMatches, LinksFunction } from "remix";
|
||||
import { FindTournamentByNameForUrlI } from "../../../../services/tournament";
|
||||
import stylesUrl from "~/styles/teams.css";
|
||||
import { Fragment } from "react";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: stylesUrl }];
|
||||
};
|
||||
|
||||
export default function TeamsTab() {
|
||||
const [, parentRoute] = useMatches();
|
||||
const { teams } = parentRoute.data as FindTournamentByNameForUrlI;
|
||||
|
||||
if (!teams.length) return null;
|
||||
|
||||
const sortedTeams = teams
|
||||
// TODO: user id here
|
||||
.sort(sortOwnTeamsAndFullTeamsFirst(-1))
|
||||
.map((team) => {
|
||||
return {
|
||||
...team,
|
||||
members: team.members.sort(sortCaptainFirst),
|
||||
};
|
||||
});
|
||||
|
||||
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>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function sortCaptainFirst(a: { captain: boolean }, b: { captain: boolean }) {
|
||||
return Number(b.captain) - Number(a.captain);
|
||||
}
|
||||
|
||||
function sortOwnTeamsAndFullTeamsFirst(userId?: number) {
|
||||
return function (
|
||||
a: { members: { member: { id: number } }[] },
|
||||
b: { members: { member: { id: number } }[] }
|
||||
) {
|
||||
if (userId) {
|
||||
const aSortValue = Number(
|
||||
a.members.some(({ member }) => userId === member.id)
|
||||
);
|
||||
const bSortValue = Number(
|
||||
b.members.some(({ member }) => userId === member.id)
|
||||
);
|
||||
|
||||
if (aSortValue !== bSortValue) return bSortValue - aSortValue;
|
||||
}
|
||||
|
||||
const aSortValue = a.members.length >= 4 ? 1 : 0;
|
||||
const bSortValue = b.members.length >= 4 ? 1 : 0;
|
||||
|
||||
return bSortValue - aSortValue;
|
||||
};
|
||||
}
|
||||
77
app/styles/teams.css
Normal file
77
app/styles/teams.css
Normal file
@@ -0,0 +1,77 @@
|
||||
.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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user