mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-03-21 18:04:39 -05:00
builds renders
This commit is contained in:
parent
528ec5e7e4
commit
8f6c7ea0e0
220
components/builds/BuildCard.tsx
Normal file
220
components/builds/BuildCard.tsx
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
import {
|
||||
Box,
|
||||
BoxProps,
|
||||
Flex,
|
||||
IconButton,
|
||||
Popover,
|
||||
PopoverBody,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@chakra-ui/core";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import WeaponImage from "components/common/WeaponImage";
|
||||
import { getEmojiFlag } from "countries-list";
|
||||
import { Unpacked } from "lib/types";
|
||||
import { useMyTheme } from "lib/useMyTheme";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { GetBuildsByWeaponData } from "prisma/queries/getBuildsByWeapon";
|
||||
import { useState } from "react";
|
||||
import { FiBarChart2, FiInfo, FiTarget } from "react-icons/fi";
|
||||
import Gears from "./Gears";
|
||||
//import ViewAP from "./ViewAP";
|
||||
import ViewSlots from "./ViewSlots";
|
||||
|
||||
interface BuildCardProps {
|
||||
build: Unpacked<GetBuildsByWeaponData>;
|
||||
canModify?: boolean;
|
||||
//setBuildBeingEdited?: (build: Build) => void;
|
||||
otherBuildCount?: number;
|
||||
onShowAllByUser?: () => void;
|
||||
}
|
||||
|
||||
const BuildCard: React.FC<BuildCardProps & BoxProps> = ({
|
||||
build,
|
||||
canModify,
|
||||
//setBuildBeingEdited,
|
||||
otherBuildCount,
|
||||
onShowAllByUser,
|
||||
...props
|
||||
}) => {
|
||||
const [apView, setApView] = useState(false);
|
||||
const [showStats, setShowStats] = useState(false);
|
||||
const { themeColor, secondaryBgColor, gray } = useMyTheme();
|
||||
|
||||
const username = build.user.username;
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* {showStats && (
|
||||
<BuildCardStats build={build} closeModal={() => setShowStats(false)} />
|
||||
)} */}
|
||||
<Box
|
||||
w="300px"
|
||||
rounded="lg"
|
||||
overflow="hidden"
|
||||
boxShadow="0px 0px 16px 6px rgba(0,0,0,0.1)"
|
||||
bg={secondaryBgColor}
|
||||
p="20px"
|
||||
{...props}
|
||||
>
|
||||
<Box display="flex" flexDirection="column" h="100%">
|
||||
<Box display="flex" justifyContent="space-between">
|
||||
<Box width="24">
|
||||
<WeaponImage name={build.weapon} size={64} />
|
||||
</Box>
|
||||
{build.top500 && (
|
||||
<Image
|
||||
src={`/layout/xsearch.png`}
|
||||
alt="x rank top 500 logo"
|
||||
height={40}
|
||||
width={40}
|
||||
title={t`Maker of the build has finished in the top 500 of X Rank with this weapon"`}
|
||||
/>
|
||||
)}
|
||||
{build.jpn && getEmojiFlag("jp")}
|
||||
</Box>
|
||||
<Flex alignItems="center">
|
||||
<Box
|
||||
color={gray}
|
||||
fontWeight="semibold"
|
||||
letterSpacing="wide"
|
||||
fontSize="xs"
|
||||
ml="8px"
|
||||
title={build.updatedAt.toLocaleString()}
|
||||
>
|
||||
{build.updatedAt.toLocaleDateString()}
|
||||
</Box>
|
||||
{build.user && (
|
||||
<Box
|
||||
style={{ textOverflow: "ellipsis" }}
|
||||
color={gray}
|
||||
fontWeight="semibold"
|
||||
letterSpacing="wide"
|
||||
fontSize="sm"
|
||||
ml="0.25em"
|
||||
whiteSpace="nowrap"
|
||||
overflow="hidden"
|
||||
title={`${build.user.username}#${build.user.discriminator}`}
|
||||
>
|
||||
•{" "}
|
||||
<Link href={`/u/${build.user.discordId}`}>
|
||||
<a>
|
||||
{build.user.username}#{build.user.discriminator}
|
||||
</a>
|
||||
</Link>
|
||||
</Box>
|
||||
)}
|
||||
</Flex>
|
||||
{build.title && (
|
||||
<Box
|
||||
ml="8px"
|
||||
fontWeight="semibold"
|
||||
as="h4"
|
||||
lineHeight="tight"
|
||||
mt="0.3em"
|
||||
>
|
||||
{build.title}
|
||||
</Box>
|
||||
)}
|
||||
<Flex mt="0.3em">
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
isRound
|
||||
colorScheme={themeColor}
|
||||
onClick={() => setApView(!apView)}
|
||||
aria-label="Set build card view"
|
||||
fontSize="20px"
|
||||
icon={<FiTarget />}
|
||||
mr="0.5em"
|
||||
/>
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
isRound
|
||||
colorScheme={themeColor}
|
||||
onClick={() => setShowStats(!showStats)}
|
||||
aria-label="Show build stats view"
|
||||
fontSize="20px"
|
||||
icon={<FiBarChart2 />}
|
||||
mr="0.5em"
|
||||
/>
|
||||
{build.description && (
|
||||
<Popover placement="top">
|
||||
<PopoverTrigger>
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
isRound
|
||||
colorScheme={themeColor}
|
||||
aria-label="Show description"
|
||||
fontSize="20px"
|
||||
icon={<FiInfo />}
|
||||
/>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
zIndex={4}
|
||||
width="220px"
|
||||
backgroundColor={secondaryBgColor}
|
||||
>
|
||||
<PopoverBody textAlign="center" whiteSpace="pre-wrap">
|
||||
{build.description}
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
{/* {canModify && (
|
||||
<IconButton
|
||||
variant="ghost"
|
||||
isRound
|
||||
colorScheme={themeColor}
|
||||
onClick={
|
||||
setBuildBeingEdited && (() => setBuildBeingEdited(build))
|
||||
}
|
||||
aria-label="Show description"
|
||||
fontSize="20px"
|
||||
icon={<FiEdit />}
|
||||
ml="0.5em"
|
||||
/>
|
||||
)} */}
|
||||
</Flex>
|
||||
<Box mt="1em">
|
||||
<Gears build={build} />
|
||||
</Box>
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
flexGrow={1}
|
||||
justifyContent="center"
|
||||
mt="1em"
|
||||
>
|
||||
{/* {apView ? <ViewAP build={build} /> : <ViewSlots build={build} />} */}
|
||||
<ViewSlots build={build} />
|
||||
</Box>
|
||||
<Box
|
||||
display="flex"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
mt="1em"
|
||||
>
|
||||
{otherBuildCount && (
|
||||
<Box
|
||||
mx="auto"
|
||||
fontSize="0.8em"
|
||||
color={themeColor}
|
||||
textAlign="center"
|
||||
onClick={onShowAllByUser}
|
||||
cursor="pointer"
|
||||
_hover={{ textDecoration: "underline" }}
|
||||
>
|
||||
<Trans>
|
||||
Show all {otherBuildCount} builds by {username}
|
||||
</Trans>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default BuildCard;
|
||||
30
components/builds/Gears.tsx
Normal file
30
components/builds/Gears.tsx
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import { Box, Flex } from "@chakra-ui/core";
|
||||
import GearImage from "components/common/GearImage";
|
||||
import { Unpacked } from "lib/types";
|
||||
import { GetBuildsByWeaponData } from "prisma/queries/getBuildsByWeapon";
|
||||
import React from "react";
|
||||
|
||||
interface GearsProps {
|
||||
build: Unpacked<GetBuildsByWeaponData>;
|
||||
}
|
||||
|
||||
const Gears: React.FC<GearsProps> = ({ build }) => {
|
||||
if (!build.headGear && !build.clothingGear && !build.shoesGear) {
|
||||
return <Box h="30px" />;
|
||||
}
|
||||
return (
|
||||
<Flex justifyContent="center">
|
||||
<Box w={build.headGear ? "85px" : undefined} h="85px" mx="2px">
|
||||
{build.headGear && <GearImage englishName={build.headGear} />}
|
||||
</Box>
|
||||
<Box w={build.clothingGear ? "85px" : undefined} h="85px" mx="2px">
|
||||
{build.clothingGear && <GearImage englishName={build.clothingGear} />}
|
||||
</Box>
|
||||
<Box w={build.shoesGear ? "85px" : undefined} h="85px" mx="2px">
|
||||
{build.shoesGear && <GearImage englishName={build.shoesGear} />}
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default Gears;
|
||||
110
components/builds/ViewAP.tsx
Normal file
110
components/builds/ViewAP.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
// This while is bit of a mess from TS PoV - might be worth while to do it better later
|
||||
|
||||
import { Box, Flex } from "@chakra-ui/core";
|
||||
import React, { useContext } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import MyThemeContext from "../../themeContext";
|
||||
import { Ability, Build } from "../../types";
|
||||
import { mainOnlyAbilities } from "../../utils/lists";
|
||||
import DividingBox from "../common/DividingBox";
|
||||
import AbilityIcon from "./AbilityIcon";
|
||||
|
||||
interface ViewAPProps {
|
||||
build: Build;
|
||||
}
|
||||
|
||||
const ViewAP: React.FC<ViewAPProps> = ({ build }) => {
|
||||
const { t } = useTranslation();
|
||||
const { grayWithShade } = useContext(MyThemeContext);
|
||||
const abilityArrays: Ability[][] = [
|
||||
build.headgear,
|
||||
build.clothing,
|
||||
build.shoes,
|
||||
];
|
||||
|
||||
const abilityToPoints: Partial<Record<Ability, number>> = {};
|
||||
abilityArrays.forEach((arr) =>
|
||||
arr.forEach((ability, index) => {
|
||||
let abilityPoints = index === 0 ? 10 : 3;
|
||||
if (mainOnlyAbilities.indexOf(ability as any) !== -1) abilityPoints = 999;
|
||||
abilityToPoints[ability] = abilityToPoints.hasOwnProperty(ability)
|
||||
? (abilityToPoints[ability] as any) + abilityPoints
|
||||
: abilityPoints;
|
||||
})
|
||||
);
|
||||
|
||||
const pointsToAbilities: Record<string, Ability[]> = {};
|
||||
(Object.keys(abilityToPoints) as Array<keyof typeof abilityToPoints>).forEach(
|
||||
(ability: Ability) => {
|
||||
const points = abilityToPoints[ability];
|
||||
|
||||
pointsToAbilities.hasOwnProperty(points as any)
|
||||
? pointsToAbilities[points as any].push(ability)
|
||||
: (pointsToAbilities[points as any] = [ability]);
|
||||
}
|
||||
);
|
||||
|
||||
const APArrays = (Object.keys(pointsToAbilities) as Array<
|
||||
keyof typeof pointsToAbilities
|
||||
>)
|
||||
.map((points) => [points, pointsToAbilities[points as any]])
|
||||
.sort((a1, a2) => parseInt(a2[0] as string) - parseInt(a1[0] as string));
|
||||
|
||||
let indexToPrintAPAt = APArrays[0][0] === "999" ? 1 : 0;
|
||||
|
||||
return (
|
||||
<Box mt="2">
|
||||
{APArrays.map((arr, index) => {
|
||||
return (
|
||||
<Flex
|
||||
key={arr[0] as any}
|
||||
justifyContent="flex-start"
|
||||
alignItems="center"
|
||||
gridRowGap="2em"
|
||||
mt={index === 0 ? "0" : "1em"}
|
||||
>
|
||||
{arr[0] !== "999" ? (
|
||||
<DividingBox location="right">
|
||||
<Box
|
||||
color={grayWithShade}
|
||||
width="32px"
|
||||
minH="45px"
|
||||
letterSpacing="wide"
|
||||
fontSize="s"
|
||||
fontWeight="semibold"
|
||||
textAlign="center"
|
||||
pt={indexToPrintAPAt !== index ? "10px" : undefined}
|
||||
>
|
||||
{arr[0] as string}
|
||||
{indexToPrintAPAt === index ? (
|
||||
<>
|
||||
<br />
|
||||
{t("analyzer;abilityPointShort")}
|
||||
</>
|
||||
) : null}
|
||||
</Box>
|
||||
</DividingBox>
|
||||
) : (
|
||||
<Box width="37px" />
|
||||
)}
|
||||
{(arr[1] as Array<Ability>).map((ability, abilityIndex) => (
|
||||
<Box
|
||||
width="45px"
|
||||
key={ability}
|
||||
ml={
|
||||
abilityIndex !== 0 && arr[1].length > 5
|
||||
? `-${(arr[1].length - 5) * 5}px`
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<AbilityIcon ability={ability} size="SUB" />
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default ViewAP;
|
||||
83
components/builds/ViewSlots.tsx
Normal file
83
components/builds/ViewSlots.tsx
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import { Box, BoxProps, Flex } from "@chakra-ui/core";
|
||||
import AbilityIcon from "components/common/AbilityIcon";
|
||||
import { Unpacked } from "lib/types";
|
||||
import { GetBuildsByWeaponData } from "prisma/queries/getBuildsByWeapon";
|
||||
|
||||
interface ViewSlotsProps {
|
||||
build: Unpacked<GetBuildsByWeaponData>;
|
||||
onAbilityClick?: (gear: "HEAD" | "CLOTHING" | "SHOES", index: number) => void;
|
||||
}
|
||||
|
||||
// FIXME: fix any
|
||||
const defaultAbilityRow = ["UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN"] as any[];
|
||||
|
||||
const ViewSlots: React.FC<ViewSlotsProps & BoxProps> = ({
|
||||
build,
|
||||
onAbilityClick,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<Box {...props}>
|
||||
<Flex alignItems="center" justifyContent="center">
|
||||
{(build.headAbilities ?? defaultAbilityRow).map((ability, index) => (
|
||||
<Box
|
||||
mx="3px"
|
||||
key={index}
|
||||
onClick={
|
||||
onAbilityClick ? () => onAbilityClick("HEAD", index) : undefined
|
||||
}
|
||||
cursor={onAbilityClick ? "pointer" : undefined}
|
||||
>
|
||||
<AbilityIcon
|
||||
key={index}
|
||||
ability={ability}
|
||||
size={index === 0 ? "MAIN" : "SUB"}
|
||||
/>
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
<Flex alignItems="center" justifyContent="center" my="0.5em">
|
||||
{(build.clothingAbilities ?? defaultAbilityRow).map(
|
||||
(ability, index) => (
|
||||
<Box
|
||||
mx="3px"
|
||||
key={index}
|
||||
onClick={
|
||||
onAbilityClick
|
||||
? () => onAbilityClick("CLOTHING", index)
|
||||
: undefined
|
||||
}
|
||||
cursor={onAbilityClick ? "pointer" : undefined}
|
||||
>
|
||||
<AbilityIcon
|
||||
key={index}
|
||||
ability={ability}
|
||||
size={index === 0 ? "MAIN" : "SUB"}
|
||||
/>
|
||||
</Box>
|
||||
)
|
||||
)}
|
||||
</Flex>
|
||||
<Flex alignItems="center" justifyContent="center">
|
||||
{(build.shoesAbilities ?? defaultAbilityRow).map((ability, index) => (
|
||||
<Box
|
||||
mx="3px"
|
||||
key={index}
|
||||
onClick={
|
||||
onAbilityClick ? () => onAbilityClick("SHOES", index) : undefined
|
||||
}
|
||||
cursor={onAbilityClick ? "pointer" : undefined}
|
||||
>
|
||||
<AbilityIcon
|
||||
key={index}
|
||||
ability={ability}
|
||||
size={index === 0 ? "MAIN" : "SUB"}
|
||||
/>
|
||||
</Box>
|
||||
))}
|
||||
</Flex>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default ViewSlots;
|
||||
|
|
@ -24,7 +24,20 @@ const Layout = ({ Component, pageProps }: AppProps) => {
|
|||
<SWRConfig
|
||||
value={{
|
||||
fetcher: (resource, init) =>
|
||||
fetch(resource, init).then((res) => res.json()),
|
||||
fetch(resource, init).then(async (res) => {
|
||||
let data = await res.json();
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
data.map((entry) => {
|
||||
if (!entry.updatedAt) return entry;
|
||||
entry.updatedAt = new Date(entry.updatedAt);
|
||||
|
||||
return entry;
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
}),
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: false,
|
||||
onError: (error) => {
|
||||
|
|
|
|||
|
|
@ -5,3 +5,5 @@ export type Unwrap<T> = T extends Promise<infer U>
|
|||
: T extends (...args: any) => infer U
|
||||
? U
|
||||
: T;
|
||||
|
||||
export type Unpacked<T> = T extends (infer U)[] ? U : T;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
import { t } from "@lingui/macro";
|
||||
import BuildCard from "components/builds/BuildCard";
|
||||
import Breadcrumbs from "components/common/Breadcrumbs";
|
||||
import WeaponSelector from "components/common/WeaponSelector";
|
||||
import { weaponToCode } from "lib/lists/weaponCodes";
|
||||
import { GetBuildsByWeaponData } from "prisma/queries/getBuildsByWeapon";
|
||||
import { useState } from "react";
|
||||
import useSWR from "swr";
|
||||
|
||||
const BuildsPage = () => {
|
||||
const [weapon, setWeapon] = useState("");
|
||||
|
||||
const { data } = useSWR(() => {
|
||||
const { data = [] } = useSWR<GetBuildsByWeaponData>(() => {
|
||||
if (!weapon) return null;
|
||||
|
||||
const key = weapon as keyof typeof weaponToCode;
|
||||
|
|
@ -21,6 +23,9 @@ const BuildsPage = () => {
|
|||
<>
|
||||
<Breadcrumbs pages={[{ name: t`Builds` }]} />
|
||||
<WeaponSelector value={weapon} onChange={setWeapon} excludeAlt isHeader />
|
||||
{data.map((build) => (
|
||||
<BuildCard build={build} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
72
prisma/migrations/20201111140528-init/README.md
Normal file
72
prisma/migrations/20201111140528-init/README.md
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# Migration `20201111140528-init`
|
||||
|
||||
This migration has been generated by Kalle (Sendou) at 11/11/2020, 4:05:28 PM.
|
||||
You can check out the [state of the schema](./schema.prisma) after the migration.
|
||||
|
||||
## Database Steps
|
||||
|
||||
```sql
|
||||
ALTER TABLE "Build" DROP COLUMN "mainAbilities",
|
||||
DROP COLUMN "subAbilities",
|
||||
ADD COLUMN "headAbilities" "Ability"[],
|
||||
ADD COLUMN "clothingAbilities" "Ability"[],
|
||||
ADD COLUMN "shoesAbilities" "Ability"[]
|
||||
```
|
||||
|
||||
## Changes
|
||||
|
||||
```diff
|
||||
diff --git schema.prisma schema.prisma
|
||||
migration 20201109140409-init..20201111140528-init
|
||||
--- datamodel.dml
|
||||
+++ datamodel.dml
|
||||
@@ -1,8 +1,8 @@
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
// FIXME: should use same .env system as Next.JS
|
||||
- url = "***"
|
||||
+ url = "***"
|
||||
}
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
@@ -93,23 +93,24 @@
|
||||
BRU
|
||||
}
|
||||
model Build {
|
||||
- id Int @id @default(autoincrement())
|
||||
- userId Int
|
||||
- weapon String
|
||||
- title String?
|
||||
- description String?
|
||||
- mainAbilities Ability[]
|
||||
- subAbilities Ability[]
|
||||
- abilityPoints Json
|
||||
- headGear String?
|
||||
- clothingGear String?
|
||||
- shoesGear String?
|
||||
- top500 Boolean
|
||||
- jpn Boolean
|
||||
- updatedAt DateTime @updatedAt
|
||||
- user User @relation(fields: [userId], references: [id])
|
||||
+ id Int @id @default(autoincrement())
|
||||
+ userId Int
|
||||
+ weapon String
|
||||
+ title String?
|
||||
+ description String?
|
||||
+ abilityPoints Json
|
||||
+ headGear String?
|
||||
+ headAbilities Ability[]
|
||||
+ clothingGear String?
|
||||
+ clothingAbilities Ability[]
|
||||
+ shoesGear String?
|
||||
+ shoesAbilities Ability[]
|
||||
+ top500 Boolean
|
||||
+ jpn Boolean
|
||||
+ updatedAt DateTime @updatedAt
|
||||
+ user User @relation(fields: [userId], references: [id])
|
||||
@@index(weapon)
|
||||
@@index(userId)
|
||||
@@index(abilityPoints)
|
||||
```
|
||||
|
||||
|
||||
117
prisma/migrations/20201111140528-init/schema.prisma
Normal file
117
prisma/migrations/20201111140528-init/schema.prisma
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
datasource db {
|
||||
provider = "postgresql"
|
||||
// FIXME: should use same .env system as Next.JS
|
||||
url = "***"
|
||||
}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
username String
|
||||
discriminator String
|
||||
discordId String @unique
|
||||
discordAvatar String?
|
||||
profile Profile?
|
||||
player Player?
|
||||
Build Build[]
|
||||
}
|
||||
|
||||
model Profile {
|
||||
twitterName String?
|
||||
twitchName String?
|
||||
youtubeId String?
|
||||
country String?
|
||||
sensMotion Float?
|
||||
sensStick Float?
|
||||
bio String?
|
||||
weaponPool String[]
|
||||
customUrlPath String? @unique
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int @unique
|
||||
|
||||
}
|
||||
|
||||
enum RankedMode {
|
||||
SZ
|
||||
TC
|
||||
RM
|
||||
CB
|
||||
}
|
||||
|
||||
model XRankPlacement {
|
||||
id Int @id @default(autoincrement())
|
||||
switchAccountId String
|
||||
player Player @relation(fields: [switchAccountId], references: [switchAccountId])
|
||||
playerName String
|
||||
ranking Int
|
||||
xPower Float
|
||||
weapon String
|
||||
mode RankedMode
|
||||
month Int
|
||||
year Int
|
||||
|
||||
@@unique([switchAccountId, mode, month, year])
|
||||
}
|
||||
|
||||
model Player {
|
||||
switchAccountId String @unique
|
||||
userId Int? @unique
|
||||
name String
|
||||
placements XRankPlacement[]
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
}
|
||||
|
||||
enum Ability {
|
||||
CB
|
||||
LDE
|
||||
OG
|
||||
T
|
||||
H
|
||||
NS
|
||||
TI
|
||||
RP
|
||||
AD
|
||||
DR
|
||||
SJ
|
||||
OS
|
||||
BDU
|
||||
REC
|
||||
RES
|
||||
ISM
|
||||
ISS
|
||||
MPU
|
||||
QR
|
||||
QSJ
|
||||
RSU
|
||||
SSU
|
||||
SCU
|
||||
SPU
|
||||
SS
|
||||
BRU
|
||||
}
|
||||
|
||||
model Build {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
weapon String
|
||||
title String?
|
||||
description String?
|
||||
abilityPoints Json
|
||||
headGear String?
|
||||
headAbilities Ability[]
|
||||
clothingGear String?
|
||||
clothingAbilities Ability[]
|
||||
shoesGear String?
|
||||
shoesAbilities Ability[]
|
||||
top500 Boolean
|
||||
jpn Boolean
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
@@index(weapon)
|
||||
@@index(userId)
|
||||
@@index(abilityPoints)
|
||||
}
|
||||
36
prisma/migrations/20201111140528-init/steps.json
Normal file
36
prisma/migrations/20201111140528-init/steps.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"version": "0.3.14-fixed",
|
||||
"steps": [
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Build",
|
||||
"field": "headAbilities",
|
||||
"type": "Ability",
|
||||
"arity": "List"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Build",
|
||||
"field": "clothingAbilities",
|
||||
"type": "Ability",
|
||||
"arity": "List"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Build",
|
||||
"field": "shoesAbilities",
|
||||
"type": "Ability",
|
||||
"arity": "List"
|
||||
},
|
||||
{
|
||||
"tag": "DeleteField",
|
||||
"model": "Build",
|
||||
"field": "mainAbilities"
|
||||
},
|
||||
{
|
||||
"tag": "DeleteField",
|
||||
"model": "Build",
|
||||
"field": "subAbilities"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -2,4 +2,5 @@
|
|||
|
||||
20201103144752-init
|
||||
20201109002900-init
|
||||
20201109140409-init
|
||||
20201109140409-init
|
||||
20201111140528-init
|
||||
|
|
@ -15,5 +15,14 @@ export const getBuildsByWeapon = async ({
|
|||
return prisma.build.findMany({
|
||||
where: { weapon },
|
||||
orderBy: [{ top500: "desc" }, { jpn: "desc" }, { updatedAt: "desc" }],
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
username: true,
|
||||
discriminator: true,
|
||||
discordId: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -94,21 +94,22 @@ enum Ability {
|
|||
}
|
||||
|
||||
model Build {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
weapon String
|
||||
title String?
|
||||
description String?
|
||||
mainAbilities Ability[]
|
||||
subAbilities Ability[]
|
||||
abilityPoints Json
|
||||
headGear String?
|
||||
clothingGear String?
|
||||
shoesGear String?
|
||||
top500 Boolean
|
||||
jpn Boolean
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
weapon String
|
||||
title String?
|
||||
description String?
|
||||
abilityPoints Json
|
||||
headGear String?
|
||||
headAbilities Ability[]
|
||||
clothingGear String?
|
||||
clothingAbilities Ability[]
|
||||
shoesGear String?
|
||||
shoesAbilities Ability[]
|
||||
top500 Boolean
|
||||
jpn Boolean
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
@@index(weapon)
|
||||
@@index(userId)
|
||||
|
|
|
|||
|
|
@ -118,8 +118,9 @@ const main = async () => {
|
|||
},
|
||||
},
|
||||
weapon: "Splattershot Jr.",
|
||||
mainAbilities: ["SS", "SS", "SS"],
|
||||
subAbilities: ["SS", "SS", "SS", "SS", "SS", "SS", "SS", "SS", "SS"],
|
||||
headAbilities: ["SS", "SS", "SS", "SS"],
|
||||
clothingAbilities: ["SS", "SS", "SS", "SS"],
|
||||
shoesAbilities: ["SS", "SS", "SS", "SS"],
|
||||
title: "Amazing test build",
|
||||
description: "Just testing.",
|
||||
top500: true,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user