mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-27 21:55:15 -05:00
quad table
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname $0)/_/husky.sh"
|
||||
|
||||
npm run prettier:pre-commit && npm run ex:pre-commit
|
||||
npm run ex:pre-commit
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
.next
|
||||
prisma/migrations
|
||||
locales/**/*
|
||||
locales/**/*.js
|
||||
126
components/player/QuadTable.tsx
Normal file
126
components/player/QuadTable.tsx
Normal file
@@ -0,0 +1,126 @@
|
||||
import { Box, Flex, Text } from "@chakra-ui/react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { useLingui } from "@lingui/react";
|
||||
import { Player } from "@prisma/client";
|
||||
import MyLink from "components/common/MyLink";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "components/common/Table";
|
||||
import WeaponImage from "components/common/WeaponImage";
|
||||
import { getRankingString } from "lib/strings";
|
||||
import { useMyTheme } from "lib/useMyTheme";
|
||||
import { GetPlayerWithPlacementsData } from "prisma/queries/getPlayerWithPlacements";
|
||||
|
||||
interface Props {
|
||||
player: NonNullable<GetPlayerWithPlacementsData>;
|
||||
}
|
||||
|
||||
const QuadTable: React.FC<Props> = ({ player }) => {
|
||||
const { i18n } = useLingui();
|
||||
const { gray } = useMyTheme();
|
||||
return (
|
||||
<Table maxW="50rem">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableHeader />
|
||||
<TableHeader>
|
||||
<Trans>Date</Trans>
|
||||
</TableHeader>
|
||||
<TableHeader>
|
||||
<Trans>Power</Trans>
|
||||
</TableHeader>
|
||||
<TableHeader>
|
||||
<Trans>Weapon</Trans>
|
||||
</TableHeader>
|
||||
<TableHeader>
|
||||
<Trans>Mates</Trans>
|
||||
</TableHeader>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{player.leaguePlacements.QUAD.map(({ squad }, index) => {
|
||||
return (
|
||||
<TableRow key={squad.id}>
|
||||
<TableCell color={gray}>{getRankingString(index + 1)}</TableCell>
|
||||
<TableCell>
|
||||
{new Date(squad.startTime).toLocaleString(i18n.locale, {
|
||||
month: "numeric",
|
||||
year: "numeric",
|
||||
hour: "numeric",
|
||||
day: "numeric",
|
||||
})}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Text fontWeight="bold">{squad.leaguePower}</Text>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<WeaponImage
|
||||
name={
|
||||
squad.members.find(
|
||||
(member) =>
|
||||
member.player.switchAccountId === player.switchAccountId
|
||||
)!.weapon
|
||||
}
|
||||
size={32}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<LeagueMates
|
||||
mates={squad.members.filter(
|
||||
(member) =>
|
||||
member.player.switchAccountId !== player.switchAccountId
|
||||
)}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
};
|
||||
|
||||
function LeagueMates({
|
||||
mates,
|
||||
}: {
|
||||
mates: {
|
||||
player: Player & {
|
||||
user: {
|
||||
username: string;
|
||||
discriminator: string;
|
||||
discordId: string;
|
||||
discordAvatar: string | null;
|
||||
} | null;
|
||||
};
|
||||
weapon: string;
|
||||
}[];
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
{mates.map((mate) => (
|
||||
<Flex align="center" key={mate.player.switchAccountId}>
|
||||
<WeaponImage name={mate.weapon} size={32} />
|
||||
<Box ml={2}>
|
||||
<MyLink
|
||||
href={
|
||||
mate.player.user
|
||||
? `/u/${mate.player.user.discordId}`
|
||||
: `/player/${mate.player.switchAccountId}`
|
||||
}
|
||||
prefetch={false}
|
||||
>
|
||||
{mate.player.name ?? "???"}
|
||||
</MyLink>
|
||||
</Box>
|
||||
</Flex>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default QuadTable;
|
||||
@@ -18,10 +18,10 @@ import { useMyTheme } from "lib/useMyTheme";
|
||||
import { GetPlayerWithPlacementsData } from "prisma/queries/getPlayerWithPlacements";
|
||||
|
||||
interface Props {
|
||||
placements: GetPlayerWithPlacementsData;
|
||||
player: NonNullable<GetPlayerWithPlacementsData>;
|
||||
}
|
||||
|
||||
const TwinTable: React.FC<Props> = ({ placements }) => {
|
||||
const TwinTable: React.FC<Props> = ({ player }) => {
|
||||
const { i18n } = useLingui();
|
||||
const { gray } = useMyTheme();
|
||||
return (
|
||||
@@ -47,7 +47,7 @@ const TwinTable: React.FC<Props> = ({ placements }) => {
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{placements?.leaguePlacements.TWIN.map(({ squad }, index) => {
|
||||
{player.leaguePlacements.TWIN.map(({ squad }, index) => {
|
||||
return (
|
||||
<TableRow key={squad.id}>
|
||||
<TableCell color={gray}>{getRankingString(index + 1)}</TableCell>
|
||||
@@ -67,8 +67,7 @@ const TwinTable: React.FC<Props> = ({ placements }) => {
|
||||
name={
|
||||
squad.members.find(
|
||||
(member) =>
|
||||
member.player.switchAccountId ===
|
||||
placements.switchAccountId
|
||||
member.player.switchAccountId === player.switchAccountId
|
||||
)!.weapon
|
||||
}
|
||||
size={32}
|
||||
@@ -79,8 +78,7 @@ const TwinTable: React.FC<Props> = ({ placements }) => {
|
||||
mate={
|
||||
squad.members.find(
|
||||
(member) =>
|
||||
member.player.switchAccountId !==
|
||||
placements.switchAccountId
|
||||
member.player.switchAccountId !== player.switchAccountId
|
||||
)!.player
|
||||
}
|
||||
/>
|
||||
@@ -90,8 +88,7 @@ const TwinTable: React.FC<Props> = ({ placements }) => {
|
||||
name={
|
||||
squad.members.find(
|
||||
(member) =>
|
||||
member.player.switchAccountId !==
|
||||
placements.switchAccountId
|
||||
member.player.switchAccountId !== player.switchAccountId
|
||||
)!.weapon
|
||||
}
|
||||
size={32}
|
||||
@@ -120,7 +117,7 @@ function LeagueMate({
|
||||
if (!mate.user && !mate.name) return <>{"???"}</>;
|
||||
if (mate.user)
|
||||
return (
|
||||
<MyLink href={`/u/${mate.user.discordId}`}>
|
||||
<MyLink href={`/u/${mate.user.discordId}`} prefetch={false}>
|
||||
<Flex alignItems="center">
|
||||
<UserAvatar user={mate.user} size="sm" mr={2} />
|
||||
{mate.user.username}
|
||||
@@ -128,7 +125,11 @@ function LeagueMate({
|
||||
</MyLink>
|
||||
);
|
||||
|
||||
return <MyLink href={`/player/${mate.switchAccountId}`}>{mate.name}</MyLink>;
|
||||
return (
|
||||
<MyLink href={`/player/${mate.switchAccountId}`} prefetch={false}>
|
||||
{mate.name}
|
||||
</MyLink>
|
||||
);
|
||||
}
|
||||
|
||||
export default TwinTable;
|
||||
|
||||
@@ -15,10 +15,10 @@ import { useMyTheme } from "lib/useMyTheme";
|
||||
import { GetPlayerWithPlacementsData } from "prisma/queries/getPlayerWithPlacements";
|
||||
|
||||
interface Props {
|
||||
placements: NonNullable<GetPlayerWithPlacementsData>["placements"];
|
||||
player: NonNullable<GetPlayerWithPlacementsData>;
|
||||
}
|
||||
|
||||
const XRankTable: React.FC<Props> = ({ placements }) => {
|
||||
const XRankTable: React.FC<Props> = ({ player }) => {
|
||||
const { gray } = useMyTheme();
|
||||
|
||||
return (
|
||||
@@ -47,7 +47,7 @@ const XRankTable: React.FC<Props> = ({ placements }) => {
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{placements.map((record) => {
|
||||
{player.placements.map((record) => {
|
||||
return (
|
||||
<TableRow key={record.id}>
|
||||
<TableCell color={gray}>
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "",
|
||||
"Power": "",
|
||||
"Weapon": "Waffe",
|
||||
"Mates": "",
|
||||
"Mate": "",
|
||||
"Mate's weapon": "",
|
||||
"Name": "Name",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "",
|
||||
"Top 500 Tier Lists": "",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": ""
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "",
|
||||
"Power": "",
|
||||
"Weapon": "Όπλο",
|
||||
"Mates": "",
|
||||
"Mate": "",
|
||||
"Mate's weapon": "",
|
||||
"Name": "Όνομα",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "",
|
||||
"Top 500 Tier Lists": "",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": ""
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "Date",
|
||||
"Power": "Power",
|
||||
"Weapon": "Weapon",
|
||||
"Mates": "Mates",
|
||||
"Mate": "Mate",
|
||||
"Mate's weapon": "Mate's weapon",
|
||||
"Name": "Name",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "Search for users by their Discord tag or Twitter name",
|
||||
"Top 500 Tier Lists": "Top 500 Tier Lists",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": "Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown."
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "",
|
||||
"Power": "",
|
||||
"Weapon": "Arma",
|
||||
"Mates": "",
|
||||
"Mate": "",
|
||||
"Mate's weapon": "",
|
||||
"Name": "Nombre",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "",
|
||||
"Top 500 Tier Lists": "",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": ""
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "",
|
||||
"Power": "",
|
||||
"Weapon": "Arme",
|
||||
"Mates": "",
|
||||
"Mate": "",
|
||||
"Mate's weapon": "",
|
||||
"Name": "Nom",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "",
|
||||
"Top 500 Tier Lists": "",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": ""
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "",
|
||||
"Power": "",
|
||||
"Weapon": "Arma",
|
||||
"Mates": "",
|
||||
"Mate": "",
|
||||
"Mate's weapon": "",
|
||||
"Name": "Nome",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "",
|
||||
"Top 500 Tier Lists": "",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": ""
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "",
|
||||
"Power": "",
|
||||
"Weapon": "",
|
||||
"Mates": "",
|
||||
"Mate": "",
|
||||
"Mate's weapon": "",
|
||||
"Name": "",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "",
|
||||
"Top 500 Tier Lists": "",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": ""
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "",
|
||||
"Power": "",
|
||||
"Weapon": "무기",
|
||||
"Mates": "",
|
||||
"Mate": "",
|
||||
"Mate's weapon": "",
|
||||
"Name": "이름",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "",
|
||||
"Top 500 Tier Lists": "",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": ""
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "",
|
||||
"Power": "",
|
||||
"Weapon": "",
|
||||
"Mates": "",
|
||||
"Mate": "",
|
||||
"Mate's weapon": "",
|
||||
"Name": "",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "",
|
||||
"Top 500 Tier Lists": "",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": ""
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "",
|
||||
"Power": "",
|
||||
"Weapon": "Arma",
|
||||
"Mates": "",
|
||||
"Mate": "",
|
||||
"Mate's weapon": "",
|
||||
"Name": "Nome",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "",
|
||||
"Top 500 Tier Lists": "",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": ""
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "",
|
||||
"Power": "",
|
||||
"Weapon": "",
|
||||
"Mates": "",
|
||||
"Mate": "",
|
||||
"Mate's weapon": "",
|
||||
"Name": "",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "",
|
||||
"Top 500 Tier Lists": "",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": ""
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@
|
||||
"Date": "",
|
||||
"Power": "",
|
||||
"Weapon": "Vapen",
|
||||
"Mates": "",
|
||||
"Mate": "",
|
||||
"Mate's weapon": "",
|
||||
"Name": "Namn",
|
||||
@@ -244,4 +245,4 @@
|
||||
"Search for users by their Discord tag or Twitter name": "",
|
||||
"Top 500 Tier Lists": "",
|
||||
"Here you can find X Rank Top 500 usage tier lists. For example for a weapon to be in the X tier it needs at least 30 placements in that mode that month. Below the weapon count and X Power average are shown.": ""
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { t } from "@lingui/macro";
|
||||
import Breadcrumbs from "components/common/Breadcrumbs";
|
||||
import QuadTable from "components/player/QuadTable";
|
||||
import TwinTable from "components/player/TwinTable";
|
||||
import XRankTable from "components/player/XRankTable";
|
||||
import { GetStaticPaths, GetStaticProps } from "next";
|
||||
@@ -17,7 +18,9 @@ interface Props {
|
||||
const PlayerPage = (props: Props) => {
|
||||
const player = props.player!;
|
||||
|
||||
const [tab, setTab] = useState<"XRANK" | "TWIN" | "QUAD">("XRANK");
|
||||
const [tab, setTab] = useState<"XRANK" | "TWIN" | "QUAD">("QUAD");
|
||||
|
||||
console.log({ player });
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -28,8 +31,9 @@ const PlayerPage = (props: Props) => {
|
||||
]}
|
||||
/>
|
||||
|
||||
{tab === "XRANK" && <XRankTable placements={player.placements} />}
|
||||
{tab === "TWIN" && <TwinTable placements={player} />}
|
||||
{tab === "XRANK" && <XRankTable player={player} />}
|
||||
{tab === "TWIN" && <TwinTable player={player} />}
|
||||
{tab === "QUAD" && <QuadTable player={player} />}
|
||||
</>
|
||||
);
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ export const getPlayerWithPlacements = async (switchAccountId: string) => {
|
||||
};
|
||||
|
||||
function getTopLeaguePlacements() {
|
||||
// TODO: remove duplicates
|
||||
const result: { TWIN: LeaguePlacementArray; QUAD: LeaguePlacementArray } = {
|
||||
TWIN: [],
|
||||
QUAD: [],
|
||||
@@ -36,7 +35,13 @@ export const getPlayerWithPlacements = async (switchAccountId: string) => {
|
||||
|
||||
if (!player) return result;
|
||||
|
||||
const timeScoreSet = new Set<string>();
|
||||
for (const placement of player.leaguePlacements) {
|
||||
const identifier =
|
||||
placement.squad.startTime.toString() + placement.squad.leaguePower;
|
||||
if (timeScoreSet.has(identifier)) continue;
|
||||
timeScoreSet.add(identifier);
|
||||
|
||||
result[placement.squad.members.length === 2 ? "TWIN" : "QUAD"].push(
|
||||
placement
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user