mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-04-24 15:08:44 -05:00
x trends first version
This commit is contained in:
parent
b40daa24d5
commit
842f9c06f4
68
frontend-react/package-lock.json
generated
68
frontend-react/package-lock.json
generated
|
|
@ -1991,9 +1991,9 @@
|
|||
}
|
||||
},
|
||||
"@testing-library/jest-dom": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.3.0.tgz",
|
||||
"integrity": "sha512-Cdhpc3BHL888X55qBNyra9eM0UG63LCm/FqCWTa1Ou/0MpsUbQTM9vW1NU6/jBQFoSLgkFfDG5XVpm2V0dOm/A==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.5.0.tgz",
|
||||
"integrity": "sha512-7sWHrpxG4Yd8TmryI7Rtbx8Ff4mbs3ASye3oshQIuHvsCR+QHgr7rTR/PfeXvOmwUwR36wSTTAvrLKsPmr6VEQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.9.2",
|
||||
"@types/testing-library__jest-dom": "^5.0.2",
|
||||
|
|
@ -2015,9 +2015,9 @@
|
|||
}
|
||||
},
|
||||
"@jest/types": {
|
||||
"version": "25.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@jest/types/-/types-25.2.3.tgz",
|
||||
"integrity": "sha512-6oLQwO9mKif3Uph3RX5J1i3S7X7xtDHWBaaaoeKw8hOzV6YUd0qDcYcHZ6QXMHDIzSr7zzrEa51o2Ovlj6AtKQ==",
|
||||
"version": "25.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@jest/types/-/types-25.3.0.tgz",
|
||||
"integrity": "sha512-UkaDNewdqXAmCDbN2GlUM6amDKS78eCqiw/UmF5nE0mmLTd6moJkiZJML/X52Ke3LH7Swhw883IRXq8o9nWjVw==",
|
||||
"requires": {
|
||||
"@types/istanbul-lib-coverage": "^2.0.0",
|
||||
"@types/istanbul-reports": "^1.1.1",
|
||||
|
|
@ -2065,9 +2065,9 @@
|
|||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"diff-sequences": {
|
||||
"version": "25.2.1",
|
||||
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.1.tgz",
|
||||
"integrity": "sha512-foe7dXnGlSh3jR1ovJmdv+77VQj98eKCHHwJPbZ2eEf0fHwKbkZicpPxEch9smZ+n2dnF6QFwkOQdLq9hpeJUg=="
|
||||
"version": "25.2.6",
|
||||
"resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz",
|
||||
"integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg=="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
|
|
@ -2075,38 +2075,38 @@
|
|||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
|
||||
},
|
||||
"jest-diff": {
|
||||
"version": "25.2.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.2.3.tgz",
|
||||
"integrity": "sha512-VtZ6LAQtaQpFsmEzps15dQc5ELbJxy4L2DOSo2Ev411TUEtnJPkAMD7JneVypeMJQ1y3hgxN9Ao13n15FAnavg==",
|
||||
"version": "25.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.3.0.tgz",
|
||||
"integrity": "sha512-vyvs6RPoVdiwARwY4kqFWd4PirPLm2dmmkNzKqo38uZOzJvLee87yzDjIZLmY1SjM3XR5DwsUH+cdQ12vgqi1w==",
|
||||
"requires": {
|
||||
"chalk": "^3.0.0",
|
||||
"diff-sequences": "^25.2.1",
|
||||
"jest-get-type": "^25.2.1",
|
||||
"pretty-format": "^25.2.3"
|
||||
"diff-sequences": "^25.2.6",
|
||||
"jest-get-type": "^25.2.6",
|
||||
"pretty-format": "^25.3.0"
|
||||
}
|
||||
},
|
||||
"jest-get-type": {
|
||||
"version": "25.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.1.tgz",
|
||||
"integrity": "sha512-EYjTiqcDTCRJDcSNKbLTwn/LcDPEE7ITk8yRMNAOjEsN6yp+Uu+V1gx4djwnuj/DvWg0YGmqaBqPVGsPxlvE7w=="
|
||||
"version": "25.2.6",
|
||||
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz",
|
||||
"integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig=="
|
||||
},
|
||||
"jest-matcher-utils": {
|
||||
"version": "25.2.3",
|
||||
"resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-25.2.3.tgz",
|
||||
"integrity": "sha512-ZmiXiwQRVM9MoKjGMP5YsGGk2Th5ncyRxfXKz5AKsmU8m43kgNZirckVzaP61MlSa9LKmXbevdYqVp1ZKAw2Rw==",
|
||||
"version": "25.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-25.3.0.tgz",
|
||||
"integrity": "sha512-ZBUJ2fchNIZt+fyzkuCFBb8SKaU//Rln45augfUtbHaGyVxCO++ANARdBK9oPGXU3hEDgyy7UHnOP/qNOJXFUg==",
|
||||
"requires": {
|
||||
"chalk": "^3.0.0",
|
||||
"jest-diff": "^25.2.3",
|
||||
"jest-get-type": "^25.2.1",
|
||||
"pretty-format": "^25.2.3"
|
||||
"jest-diff": "^25.3.0",
|
||||
"jest-get-type": "^25.2.6",
|
||||
"pretty-format": "^25.3.0"
|
||||
}
|
||||
},
|
||||
"pretty-format": {
|
||||
"version": "25.2.3",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.2.3.tgz",
|
||||
"integrity": "sha512-IP4+5UOAVGoyqC/DiomOeHBUKN6q00gfyT2qpAsRH64tgOKB2yF7FHJXC18OCiU0/YFierACup/zdCOWw0F/0w==",
|
||||
"version": "25.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.3.0.tgz",
|
||||
"integrity": "sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA==",
|
||||
"requires": {
|
||||
"@jest/types": "^25.2.3",
|
||||
"@jest/types": "^25.3.0",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"ansi-styles": "^4.0.0",
|
||||
"react-is": "^16.12.0"
|
||||
|
|
@ -2392,9 +2392,9 @@
|
|||
}
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "16.9.32",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.32.tgz",
|
||||
"integrity": "sha512-fmejdp0CTH00mOJmxUPPbWCEBWPvRIL4m8r0qD+BSDUqmutPyGQCHifzMpMzdvZwROdEdL78IuZItntFWgPXHQ==",
|
||||
"version": "16.9.34",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.34.tgz",
|
||||
"integrity": "sha512-8AJlYMOfPe1KGLKyHpflCg5z46n0b5DbRfqDksxBLBTUpB75ypDBAO9eCUcjNwE6LCUslwTz00yyG/X9gaVtow==",
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^2.2.0"
|
||||
|
|
@ -2565,9 +2565,9 @@
|
|||
}
|
||||
},
|
||||
"@types/testing-library__jest-dom": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.0.2.tgz",
|
||||
"integrity": "sha512-dZP+/WHndgCSmdaImITy0KhjGAa9c0hlGGkzefbtrPFpnGEPZECDA0zyvfSp8RKhHECJJSKHFExjOwzo0rHyIA==",
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.0.3.tgz",
|
||||
"integrity": "sha512-NdbKc6yseg6uq4UJFwimPws0iwsGugVbPoOTP2EH+PJMJKiZsoSg5F2H3XYweOyytftCOuIMuXifBUrF9CSvaQ==",
|
||||
"requires": {
|
||||
"@types/jest": "*"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@
|
|||
"@reach/router": "^1.3.3",
|
||||
"@rehooks/local-storage": "^2.3.0",
|
||||
"@sendou/react-sketch": "^0.5.2",
|
||||
"@testing-library/jest-dom": "^5.3.0",
|
||||
"@testing-library/jest-dom": "^5.5.0",
|
||||
"@testing-library/react": "^10.0.2",
|
||||
"@testing-library/user-event": "^10.0.1",
|
||||
"@types/jest": "^25.2.1",
|
||||
"@types/reach__router": "^1.3.4",
|
||||
"@types/react": "^16.9.32",
|
||||
"@types/react": "^16.9.34",
|
||||
"@types/react-color": "^3.0.1",
|
||||
"@types/react-datepicker": "^2.11.0",
|
||||
"@types/react-dom": "^16.9.6",
|
||||
|
|
|
|||
BIN
frontend-react/src/assets/2d9e3f8bcaa27e37cce14b208ec94143.png
Normal file
BIN
frontend-react/src/assets/2d9e3f8bcaa27e37cce14b208ec94143.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 505 KiB |
BIN
frontend-react/src/assets/Puolijoukkueteltta.jfif
Normal file
BIN
frontend-react/src/assets/Puolijoukkueteltta.jfif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
|
|
@ -58,7 +58,7 @@ const BuildCard: React.FC<BuildCardProps & BoxProps> = ({
|
|||
<Box display="flex" flexDirection="column" h="100%">
|
||||
<Box display="flex" justifyContent="space-between">
|
||||
<Box width="24">
|
||||
<WeaponImage englishName={build.weapon} size="MEDIUM" />
|
||||
<WeaponImage englishName={build.weapon} size="BIG" />
|
||||
</Box>
|
||||
{build.top && (
|
||||
<Image
|
||||
|
|
|
|||
|
|
@ -6,22 +6,35 @@ import { Weapon } from "../../types.js"
|
|||
|
||||
interface WeaponImageProps {
|
||||
englishName: Weapon
|
||||
size: "SMALL" | "MEDIUM"
|
||||
size: "SMALL" | "MEDIUM" | "BIG"
|
||||
asInlineBlock?: boolean
|
||||
noTitle?: boolean
|
||||
}
|
||||
|
||||
const WeaponImage: React.FC<WeaponImageProps> = ({ englishName, size }) => {
|
||||
const sizeWhMap: Record<"SMALL" | "MEDIUM" | "BIG", string | undefined> = {
|
||||
SMALL: "32px",
|
||||
MEDIUM: "64px",
|
||||
BIG: undefined,
|
||||
}
|
||||
|
||||
const WeaponImage: React.FC<WeaponImageProps> = ({
|
||||
englishName,
|
||||
size,
|
||||
asInlineBlock,
|
||||
noTitle,
|
||||
}) => {
|
||||
const dictToUse: any = wpnMedium
|
||||
const wh = "32px"
|
||||
const wh = sizeWhMap[size]
|
||||
return (
|
||||
<img
|
||||
src={dictToUse[english_internal[englishName]]}
|
||||
alt={englishName}
|
||||
title={englishName}
|
||||
style={
|
||||
size === "SMALL"
|
||||
? { width: wh, height: wh, display: "inline-block" }
|
||||
: undefined
|
||||
}
|
||||
title={noTitle ? undefined : englishName}
|
||||
style={{
|
||||
width: wh,
|
||||
height: wh,
|
||||
display: asInlineBlock ? "inline-block" : undefined,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ const BuildFormModal: React.FC<BuildFormModalProps> = ({
|
|||
Build
|
||||
>(ADD_BUILD, {
|
||||
variables: { ...(build as Build) },
|
||||
onCompleted: data => {
|
||||
onCompleted: (data) => {
|
||||
closeModal()
|
||||
toast({
|
||||
description: `New ${data.addBuild.weapon} build created`,
|
||||
|
|
@ -77,7 +77,7 @@ const BuildFormModal: React.FC<BuildFormModalProps> = ({
|
|||
duration: 10000,
|
||||
})
|
||||
},
|
||||
onError: error => {
|
||||
onError: (error) => {
|
||||
toast({
|
||||
title: "An error occurred",
|
||||
description: error.message,
|
||||
|
|
@ -103,7 +103,7 @@ const BuildFormModal: React.FC<BuildFormModalProps> = ({
|
|||
duration: 10000,
|
||||
})
|
||||
},
|
||||
onError: error => {
|
||||
onError: (error) => {
|
||||
toast({
|
||||
title: "An error occurred",
|
||||
description: error.message,
|
||||
|
|
@ -129,7 +129,7 @@ const BuildFormModal: React.FC<BuildFormModalProps> = ({
|
|||
duration: 10000,
|
||||
})
|
||||
},
|
||||
onError: error => {
|
||||
onError: (error) => {
|
||||
toast({
|
||||
title: "An error occurred",
|
||||
description: error.message,
|
||||
|
|
@ -235,9 +235,9 @@ const BuildFormModal: React.FC<BuildFormModalProps> = ({
|
|||
}
|
||||
|
||||
const abilitiesFilled =
|
||||
build.headgear?.every(ability => ability !== "UNKNOWN") &&
|
||||
build.clothing?.every(ability => ability !== "UNKNOWN") &&
|
||||
build.shoes?.every(ability => ability !== "UNKNOWN")
|
||||
build.headgear?.every((ability) => ability !== "UNKNOWN") &&
|
||||
build.clothing?.every((ability) => ability !== "UNKNOWN") &&
|
||||
build.shoes?.every((ability) => ability !== "UNKNOWN")
|
||||
|
||||
if (!abilitiesFilled) {
|
||||
return false
|
||||
|
|
@ -269,7 +269,7 @@ const BuildFormModal: React.FC<BuildFormModalProps> = ({
|
|||
value={build.weapon}
|
||||
/>
|
||||
{build.weapon && (
|
||||
<WeaponImage englishName={build.weapon as Weapon} size="MEDIUM" />
|
||||
<WeaponImage englishName={build.weapon as Weapon} size="BIG" />
|
||||
)}
|
||||
<Box asFlex mt="1em" justifyContent="space-between" flexWrap="wrap">
|
||||
<Box asFlex flexDirection="column" alignItems="center">
|
||||
|
|
@ -283,7 +283,7 @@ const BuildFormModal: React.FC<BuildFormModalProps> = ({
|
|||
setValue={(headgearItem: HeadGear) => {
|
||||
if (
|
||||
(!build.headgear ||
|
||||
build.headgear.every(ability => ability === "UNKNOWN")) &&
|
||||
build.headgear.every((ability) => ability === "UNKNOWN")) &&
|
||||
existingGear.hasOwnProperty(headgearItem)
|
||||
) {
|
||||
handleChange({
|
||||
|
|
@ -313,7 +313,7 @@ const BuildFormModal: React.FC<BuildFormModalProps> = ({
|
|||
setValue={(clothingItem: ClothingGear) => {
|
||||
if (
|
||||
(!build.clothing ||
|
||||
build.clothing.every(ability => ability === "UNKNOWN")) &&
|
||||
build.clothing.every((ability) => ability === "UNKNOWN")) &&
|
||||
existingGear.hasOwnProperty(clothingItem)
|
||||
) {
|
||||
handleChange({
|
||||
|
|
@ -343,7 +343,7 @@ const BuildFormModal: React.FC<BuildFormModalProps> = ({
|
|||
setValue={(shoesItem: ShoesGear) => {
|
||||
if (
|
||||
(!build.shoes ||
|
||||
build.shoes.every(ability => ability === "UNKNOWN")) &&
|
||||
build.shoes.every((ability) => ability === "UNKNOWN")) &&
|
||||
existingGear.hasOwnProperty(shoesItem)
|
||||
) {
|
||||
handleChange({
|
||||
|
|
@ -376,7 +376,7 @@ const BuildFormModal: React.FC<BuildFormModalProps> = ({
|
|||
</Box>
|
||||
<Box mt="1em">
|
||||
<AbilityButtons
|
||||
onClick={ability => handleAbilityButtonClick(ability)}
|
||||
onClick={(ability) => handleAbilityButtonClick(ability)}
|
||||
/>
|
||||
</Box>
|
||||
<Box mt="1em">
|
||||
|
|
|
|||
102
frontend-react/src/components/xtrends/ModeButtons.tsx
Normal file
102
frontend-react/src/components/xtrends/ModeButtons.tsx
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import React from "react"
|
||||
import { Flex, Box, Image, PseudoBox } from "@chakra-ui/core"
|
||||
import sz from "../../assets/sz.png"
|
||||
import tc from "../../assets/tc.png"
|
||||
import rm from "../../assets/rm.png"
|
||||
import cb from "../../assets/cb.png"
|
||||
|
||||
interface ModeButtonsProps {
|
||||
mode: "SZ" | "TC" | "RM" | "CB"
|
||||
setMode: React.Dispatch<React.SetStateAction<"SZ" | "TC" | "RM" | "CB">>
|
||||
}
|
||||
|
||||
const iconSize = "45px"
|
||||
|
||||
const ModeButtons: React.FC<ModeButtonsProps> = ({ mode, setMode }) => {
|
||||
return (
|
||||
<Flex>
|
||||
<Flex
|
||||
flexDir="column"
|
||||
p="10px"
|
||||
style={{ filter: mode === "SZ" ? undefined : "grayscale(100%)" }}
|
||||
cursor="pointer"
|
||||
onClick={() => setMode("SZ")}
|
||||
alignItems="center"
|
||||
>
|
||||
<PseudoBox
|
||||
_hover={{ transform: mode === "SZ" ? undefined : "scale(1.2)" }}
|
||||
transition="all 0.2s"
|
||||
>
|
||||
<Image src={sz} display="inline-block" w={iconSize} h={iconSize} />
|
||||
</PseudoBox>
|
||||
{mode === "SZ" && (
|
||||
<Box fontSize="1.25em" fontWeight="bold">
|
||||
SZ
|
||||
</Box>
|
||||
)}
|
||||
</Flex>
|
||||
<Flex
|
||||
flexDir="column"
|
||||
p="10px"
|
||||
style={{ filter: mode === "TC" ? undefined : "grayscale(100%)" }}
|
||||
cursor="pointer"
|
||||
onClick={() => setMode("TC")}
|
||||
alignItems="center"
|
||||
>
|
||||
<PseudoBox
|
||||
_hover={{ transform: mode === "TC" ? undefined : "scale(1.2)" }}
|
||||
transition="all 0.2s"
|
||||
>
|
||||
<Image src={tc} display="inline-block" w={iconSize} h={iconSize} />
|
||||
</PseudoBox>
|
||||
{mode === "TC" && (
|
||||
<Box fontSize="1.25em" fontWeight="bold">
|
||||
TC
|
||||
</Box>
|
||||
)}
|
||||
</Flex>
|
||||
<Flex
|
||||
flexDir="column"
|
||||
p="10px"
|
||||
style={{ filter: mode === "RM" ? undefined : "grayscale(100%)" }}
|
||||
cursor="pointer"
|
||||
onClick={() => setMode("RM")}
|
||||
alignItems="center"
|
||||
>
|
||||
<PseudoBox
|
||||
_hover={{ transform: mode === "RM" ? undefined : "scale(1.2)" }}
|
||||
transition="all 0.2s"
|
||||
>
|
||||
<Image src={rm} display="inline-block" w={iconSize} h={iconSize} />
|
||||
</PseudoBox>
|
||||
{mode === "RM" && (
|
||||
<Box fontSize="1.25em" fontWeight="bold">
|
||||
RM
|
||||
</Box>
|
||||
)}
|
||||
</Flex>
|
||||
<Flex
|
||||
flexDir="column"
|
||||
p="10px"
|
||||
style={{ filter: mode === "CB" ? undefined : "grayscale(100%)" }}
|
||||
cursor="pointer"
|
||||
onClick={() => setMode("CB")}
|
||||
alignItems="center"
|
||||
>
|
||||
<PseudoBox
|
||||
_hover={{ transform: mode === "CB" ? undefined : "scale(1.2)" }}
|
||||
transition="all 0.2s"
|
||||
>
|
||||
<Image src={cb} display="inline-block" w={iconSize} h={iconSize} />
|
||||
</PseudoBox>
|
||||
{mode === "CB" && (
|
||||
<Box fontSize="1.25em" fontWeight="bold">
|
||||
CB
|
||||
</Box>
|
||||
)}
|
||||
</Flex>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
export default ModeButtons
|
||||
|
|
@ -1,24 +1,200 @@
|
|||
import React from "react"
|
||||
import React, { useEffect, useState, useContext } from "react"
|
||||
import { RouteComponentProps } from "@reach/router"
|
||||
import { useQuery } from "@apollo/react-hooks"
|
||||
import { XTrendsData, X_TRENDS } from "../../graphql/queries/xTrends"
|
||||
import Loading from "../common/Loading"
|
||||
import Error from "../common/Error"
|
||||
import PageHeader from "../common/PageHeader"
|
||||
import { months, weapons } from "../../utils/lists"
|
||||
import { Weapon } from "../../types"
|
||||
import {
|
||||
Flex,
|
||||
Box,
|
||||
Popover,
|
||||
PopoverTrigger,
|
||||
PopoverContent,
|
||||
PopoverArrow,
|
||||
} from "@chakra-ui/core"
|
||||
import WeaponImage from "../common/WeaponImage"
|
||||
import MyThemeContext from "../../themeContext"
|
||||
import ModeButtons from "./ModeButtons"
|
||||
import Select from "../elements/Select"
|
||||
|
||||
interface XTrendsPageProps {}
|
||||
const tiers = [
|
||||
{
|
||||
label: "X",
|
||||
criteria: 6,
|
||||
color: "purple.700",
|
||||
},
|
||||
{
|
||||
label: "S+",
|
||||
criteria: 5,
|
||||
color: "red.700",
|
||||
},
|
||||
{
|
||||
label: "S",
|
||||
criteria: 4,
|
||||
color: "red.700",
|
||||
},
|
||||
{
|
||||
label: "A+",
|
||||
criteria: 3,
|
||||
color: "orange.700",
|
||||
},
|
||||
{
|
||||
label: "A",
|
||||
criteria: 2,
|
||||
color: "orange.700",
|
||||
},
|
||||
{
|
||||
label: "B+",
|
||||
criteria: 1.5,
|
||||
color: "yellow.700",
|
||||
},
|
||||
{
|
||||
label: "B",
|
||||
criteria: 1,
|
||||
color: "yellow.700",
|
||||
},
|
||||
{
|
||||
label: "C+",
|
||||
criteria: 0.5,
|
||||
color: "green.700",
|
||||
},
|
||||
{
|
||||
label: "C",
|
||||
criteria: 0.002, //1 in 500
|
||||
color: "green.700",
|
||||
},
|
||||
] as const
|
||||
|
||||
const XTrendsPage: React.FC<RouteComponentProps> = () => {
|
||||
const { grayWithShade, darkerBgColor } = useContext(MyThemeContext)
|
||||
const { data, error, loading } = useQuery<XTrendsData>(X_TRENDS)
|
||||
const [month, setMonth] = useState("March 2020")
|
||||
const [mode, setMode] = useState<"SZ" | "TC" | "RM" | "CB">("SZ")
|
||||
const [weaponMonths, setWeaponMonths] = useState<Record<
|
||||
string,
|
||||
Record<"SZ" | "TC" | "RM" | "CB", { name: Weapon; amount: number }[]>
|
||||
> | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (loading || error || !!weaponMonths) return
|
||||
|
||||
const newWeaponMonths: Record<
|
||||
string,
|
||||
Record<"SZ" | "TC" | "RM" | "CB", { name: Weapon; amount: number }[]>
|
||||
> = {}
|
||||
data!.xTrends.forEach((weaponObj) => {
|
||||
weaponObj.counts.forEach((count) => {
|
||||
const arrays = [count.SZ, count.TC, count.RM, count.CB]
|
||||
arrays.forEach((arr, modeIndex) => {
|
||||
const modes = ["SZ", "TC", "RM", "CB"] as const
|
||||
const mode = modes[modeIndex]
|
||||
arr.forEach((num, numIndex) => {
|
||||
if (num === null || num === 0) return
|
||||
const monthString = `${months[numIndex]} ${count.year}`
|
||||
if (!newWeaponMonths[monthString]) {
|
||||
newWeaponMonths[monthString] = { SZ: [], TC: [], RM: [], CB: [] }
|
||||
}
|
||||
let weaponMonth = newWeaponMonths[monthString][mode]
|
||||
weaponMonth.push({ name: weaponObj.weapon as Weapon, amount: num })
|
||||
newWeaponMonths[monthString][mode] = weaponMonth
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
setWeaponMonths(newWeaponMonths)
|
||||
}, [data, loading, error, weaponMonths])
|
||||
|
||||
if (error) return <Error errorMessage={error.message} />
|
||||
if (loading) return <Loading />
|
||||
if (loading || !weaponMonths) return <Loading />
|
||||
|
||||
const weaponsOrdered = weaponMonths[month][mode].sort((a, b) => {
|
||||
const comparision = b.amount - a.amount
|
||||
|
||||
if (comparision !== 0) return comparision
|
||||
|
||||
return weapons.indexOf(a.name) - weapons.indexOf(b.name)
|
||||
})
|
||||
|
||||
console.log("weaponMonths", weaponMonths)
|
||||
|
||||
console.log("xtrends", data!.xTrends)
|
||||
return (
|
||||
<>
|
||||
<PageHeader title="X Trends" />
|
||||
{data!.xTrends.length}
|
||||
<Select
|
||||
value={month}
|
||||
setValue={(value) => setMonth(value)}
|
||||
options={Object.keys(weaponMonths)
|
||||
.sort((a, b) => {
|
||||
const partsA = a.split(" ")
|
||||
const partsB = b.split(" ")
|
||||
if (partsA[1] !== partsB[1]) {
|
||||
return parseInt(partsB[1]) - parseInt(partsA[1])
|
||||
}
|
||||
|
||||
return (
|
||||
months.indexOf(partsB[0] as any) -
|
||||
months.indexOf(partsA[0] as any)
|
||||
)
|
||||
})
|
||||
.map((month) => ({ label: month, value: month }))}
|
||||
/>
|
||||
<Box my="1em">
|
||||
<ModeButtons mode={mode} setMode={setMode} />
|
||||
</Box>
|
||||
{tiers.map((tier, index, tiers) => (
|
||||
<Flex key={tier.criteria}>
|
||||
<Flex
|
||||
flexDir="column"
|
||||
w="100px"
|
||||
minH="100px"
|
||||
padding="10px"
|
||||
borderRight="5px solid"
|
||||
borderColor={tier.color}
|
||||
marginRight="1em"
|
||||
justifyContent="center"
|
||||
>
|
||||
<Box fontSize="2em" fontWeight="bolder">
|
||||
{tier.label}
|
||||
</Box>
|
||||
<Box color={grayWithShade}>
|
||||
{tier.criteria === 0.002 ? "At least 1" : `${tier.criteria}%`}
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex flexDir="row" flex={1} flexWrap="wrap" alignItems="center">
|
||||
{weaponsOrdered
|
||||
.filter((weapon) => {
|
||||
const previousCriteria =
|
||||
index === 0 ? 101 : tiers[index - 1].criteria
|
||||
const percentsInTop500 = weapon.amount / 5
|
||||
return (
|
||||
percentsInTop500 < previousCriteria &&
|
||||
percentsInTop500 >= tier.criteria
|
||||
)
|
||||
})
|
||||
.map((weapon) => (
|
||||
<Popover key={weapon.name} placement="top-start">
|
||||
<PopoverTrigger>
|
||||
<Box mx="0.25em">
|
||||
<WeaponImage
|
||||
englishName={weapon.name}
|
||||
size="MEDIUM"
|
||||
noTitle
|
||||
/>
|
||||
</Box>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent zIndex={4} p="0.5em" bg={darkerBgColor}>
|
||||
<PopoverArrow />
|
||||
{weapon.name} - {weapon.amount}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
))}
|
||||
</Flex>
|
||||
</Flex>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ export interface XTrendsData {
|
|||
weapon: string
|
||||
counts: {
|
||||
year: number
|
||||
SZ: number[]
|
||||
TC: number[]
|
||||
RM: number[]
|
||||
CB: number[]
|
||||
SZ: (null | number)[]
|
||||
TC: (null | number)[]
|
||||
RM: (null | number)[]
|
||||
CB: (null | number)[]
|
||||
}[]
|
||||
}[]
|
||||
}
|
||||
|
|
|
|||
868
package-lock.json
generated
868
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
|
@ -34,6 +34,6 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^7.0.2",
|
||||
"nodemon": "^2.0.2"
|
||||
"nodemon": "^2.0.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user