diff --git a/frontend-react/src/assets/icons.tsx b/frontend-react/src/assets/icons.tsx
new file mode 100644
index 000000000..e112a7834
--- /dev/null
+++ b/frontend-react/src/assets/icons.tsx
@@ -0,0 +1,46 @@
+import React from "react"
+
+const customIcons = {
+ //sz.svg
+ sz: {
+ path: (
+
+ ),
+ viewBox: "0 0 128 128",
+ },
+ //tc.svg
+ tc: {
+ path: (
+
+ ),
+ viewBox: "0 0 128 128",
+ },
+ //rm.svg
+ rm: {
+ path: (
+
+ ),
+ viewBox: "0 0 128 128",
+ },
+ //cb.svg
+ cb: {
+ path: (
+
+ ),
+ viewBox: "0 0 128 128",
+ },
+}
+
+export default customIcons
diff --git a/frontend-react/src/components/builds/BuildCard.tsx b/frontend-react/src/components/builds/BuildCard.tsx
index 7c6ef569b..06fa5894a 100644
--- a/frontend-react/src/components/builds/BuildCard.tsx
+++ b/frontend-react/src/components/builds/BuildCard.tsx
@@ -47,7 +47,7 @@ const BuildCard: React.FC = ({ build, defaultToAPView }) => {
diff --git a/frontend-react/src/components/user/UserPage.tsx b/frontend-react/src/components/user/UserPage.tsx
index 68a59926b..353025b3b 100644
--- a/frontend-react/src/components/user/UserPage.tsx
+++ b/frontend-react/src/components/user/UserPage.tsx
@@ -12,6 +12,8 @@ import {
UserData,
SearchForBuildsData,
SearchForBuildsVars,
+ PlayerInfoData,
+ PlayerInfoVars,
} from "../../types"
import { FaTshirt, FaTrophy } from "react-icons/fa"
import { IconType } from "react-icons/lib/cjs"
@@ -22,6 +24,8 @@ import { Helmet } from "react-helmet-async"
import { SEARCH_FOR_BUILDS } from "../../graphql/queries/searchForBuilds"
import BuildTab from "./BuildTab"
import MyThemeContext from "../../themeContext"
+import { PLAYER_INFO } from "../../graphql/queries/playerInfo"
+import XRankTab from "./XRankTab"
interface Tab {
id: number
@@ -41,9 +45,11 @@ const UserPage: React.FC = ({ id }) => {
>(SEARCH_FOR_USER, {
variables: isNaN(id as any) ? { custom_url: id } : { discord_id: id },
})
+
const { data: userData, error: userError, loading: userLoading } = useQuery<
UserData
>(USER)
+
const {
data: buildsData,
error: buildsError,
@@ -53,14 +59,25 @@ const UserPage: React.FC = ({ id }) => {
skip: !data || !data.searchForUser,
})
+ const {
+ data: playerData,
+ error: playerError,
+ loading: playerLoading,
+ } = useQuery(PLAYER_INFO, {
+ variables: { twitter: data?.searchForUser?.twitter_name as any },
+ skip: !data || !data.searchForUser || !data.searchForUser.twitter_name,
+ })
+
const { textColor, themeColor, themeColorWithShade } = useContext(
MyThemeContext
)
- if (loading || userLoading || buildsLoading) return
+ if (loading || userLoading || buildsLoading || playerLoading)
+ return
if (error) return
if (userError) return
if (buildsError) return
+ if (playerError) return
if (!data || !data.searchForUser || !userData || !buildsData)
return
@@ -70,7 +87,8 @@ const UserPage: React.FC = ({ id }) => {
const tabs = [] as Tab[]
- if (builds.length > 0 || userLean?.discord_id === user.discord_id) {
+ //if (builds.length > 0 || userLean?.discord_id === user.discord_id) {
+ if (false) {
tabs.push({
id: 1,
icon: FaTshirt,
@@ -86,14 +104,25 @@ const UserPage: React.FC = ({ id }) => {
})
}
- if (true) {
+ if (playerData?.playerInfo?.placements) {
tabs.push({
id: 2,
icon: FaTrophy,
title: "X Rank Top 500",
content: (
- hi
+
+
+ ),
+ })
+ } else if (userLean?.discord_id === user.discord_id) {
+ tabs.push({
+ id: 2,
+ icon: FaTrophy,
+ title: "X Rank Top 500",
+ content: (
+
+ you are noob :)
),
})
diff --git a/frontend-react/src/components/user/XRankTab.tsx b/frontend-react/src/components/user/XRankTab.tsx
new file mode 100644
index 000000000..43fef4cae
--- /dev/null
+++ b/frontend-react/src/components/user/XRankTab.tsx
@@ -0,0 +1,164 @@
+import React, { useContext } from "react"
+import { Placement } from "../../types"
+import { modesShort, months } from "../../utils/lists"
+import {
+ Accordion,
+ AccordionItem,
+ AccordionHeader,
+ AccordionIcon,
+ AccordionPanel,
+ Flex,
+ Icon,
+ Box,
+} from "@chakra-ui/core"
+import MyThemeContext from "../../themeContext"
+
+interface XRankTabProps {
+ placements: Placement[]
+}
+
+interface AllModesAccordionData {
+ sz?: ModeAccordionData
+ tc?: ModeAccordionData
+ rm?: ModeAccordionData
+ cb?: ModeAccordionData
+}
+
+interface ModeAccordionData {
+ highestPlacement: number
+ highestPlacementDate: string
+ highestXPower: number
+ highestXPowerDate: string
+ placements: Placement[]
+}
+
+interface StyleBoxProps {
+ children: string | string[] | number | undefined
+ color?: string
+ size?: string
+}
+
+const StyledBox: React.FC = ({ children, color, size }) => (
+
+ {children}
+
+)
+
+const accordionReducer = function(
+ acc: AllModesAccordionData,
+ cur: Placement
+): AllModesAccordionData {
+ const key = modesShort[cur.mode]
+ const modeData = acc[key]
+ const date = `${months[cur.month]} ${cur.year}`
+ if (!modeData) {
+ acc[key] = {
+ highestPlacement: cur.rank,
+ highestPlacementDate: date,
+ highestXPower: cur.x_power,
+ highestXPowerDate: date,
+ placements: [cur],
+ }
+ } else {
+ modeData.placements.push(cur)
+
+ if (cur.x_power > modeData.highestXPower) {
+ modeData.highestXPower = cur.x_power
+ modeData.highestXPowerDate = date
+ }
+
+ if (cur.rank < modeData.highestPlacement) {
+ modeData.highestPlacement = cur.rank
+ modeData.highestPlacementDate = date
+ }
+ }
+
+ return acc
+}
+
+const XRankTab: React.FC = ({ placements }) => {
+ const { themeColorWithShade, grayWithShade } = useContext(MyThemeContext)
+
+ const allModesTabsData: AllModesAccordionData = placements.reduce(
+ accordionReducer,
+ {}
+ )
+ console.log(allModesTabsData)
+ return (
+ <>
+
+ {(["sz", "tc", "rm", "cb"] as const)
+ .filter(key => allModesTabsData.hasOwnProperty(key))
+ .map(key => {
+ return (
+
+
+
+
+ {" "}
+
+
+ Best placement
+
+
+ {allModesTabsData[key]?.highestPlacement}
+
+
+ {allModesTabsData[key]?.highestPlacementDate}
+
+
+
+
+ Highest X Power
+
+
+ {allModesTabsData[key]?.highestXPower}
+
+
+ {allModesTabsData[key]?.highestXPowerDate}
+
+
+
+
+ Number of placements
+
+
+ {allModesTabsData[key]?.placements.length}
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
+ do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco
+ laboris nisi ut aliquip ex ea commodo consequat.
+
+
+ )
+ })}
+
+ >
+ )
+}
+
+export default XRankTab
diff --git a/frontend-react/src/graphql/queries/playerInfo.js b/frontend-react/src/graphql/queries/playerInfo.js
deleted file mode 100644
index c554a6d1e..000000000
--- a/frontend-react/src/graphql/queries/playerInfo.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { gql } from 'apollo-boost'
-
-export const playerInfo = gql`
-query playerInfo($uid: String, $twitter: String) {
- playerInfo(uid: $uid, twitter: $twitter) {
- player {
- name
- weapons
- alias
- twitter
- discord_id
- topTotalScore
- topShooterScore
- topBlasterScore
- topRollerScore
- topChargerScore
- topSlosherScore
- topSplatlingScore
- topDualiesScore
- topBrellaScore
- }
- placements {
- id
- name
- weapon
- rank
- mode
- x_power
- month
- year
- }
- }
-}
-`
\ No newline at end of file
diff --git a/frontend-react/src/graphql/queries/playerInfo.ts b/frontend-react/src/graphql/queries/playerInfo.ts
new file mode 100644
index 000000000..0f4448fd4
--- /dev/null
+++ b/frontend-react/src/graphql/queries/playerInfo.ts
@@ -0,0 +1,18 @@
+import { gql, DocumentNode } from "apollo-boost"
+
+export const PLAYER_INFO: DocumentNode = gql`
+ query playerInfo($twitter: String) {
+ playerInfo(twitter: $twitter) {
+ placements {
+ id
+ name
+ weapon
+ rank
+ mode
+ x_power
+ month
+ year
+ }
+ }
+ }
+`
diff --git a/frontend-react/src/index.tsx b/frontend-react/src/index.tsx
index 2076570b8..2ce9655b8 100644
--- a/frontend-react/src/index.tsx
+++ b/frontend-react/src/index.tsx
@@ -1,11 +1,17 @@
import React, { StrictMode } from "react"
import ReactDOM from "react-dom"
import App from "./components/root/App"
-import { ThemeProvider, ColorModeProvider, CSSReset } from "@chakra-ui/core"
+import {
+ ThemeProvider,
+ ColorModeProvider,
+ CSSReset,
+ theme,
+} from "@chakra-ui/core"
import { ApolloProvider } from "@apollo/react-hooks"
import { HelmetProvider } from "react-helmet-async"
import ApolloClient from "apollo-boost"
import * as serviceWorker from "./serviceWorker"
+import customIcons from "./assets/icons"
const client = new ApolloClient({
uri:
@@ -14,11 +20,13 @@ const client = new ApolloClient({
: "http://localhost:3001/graphql",
})
+const customTheme = { ...theme, icons: { ...theme.icons, ...customIcons } }
+
ReactDOM.render(
-
+
diff --git a/frontend-react/src/types.ts b/frontend-react/src/types.ts
index 42eb36dd2..ea40f8e30 100644
--- a/frontend-react/src/types.ts
+++ b/frontend-react/src/types.ts
@@ -112,6 +112,18 @@ export interface Build {
top: boolean
}
+export interface Placement {
+ id: string
+ name: string
+ weapon: Weapon
+ rank: number
+ mode: 1 | 2 | 3 | 4
+ x_power: number
+ unique_id: string
+ month: number
+ year: number
+}
+
//==============================================================================
// Apollo
//==============================================================================
@@ -136,3 +148,13 @@ export interface SearchForBuildsData {
export interface SearchForBuildsVars {
discord_id: string
}
+
+export interface PlayerInfoData {
+ playerInfo?: {
+ placements: Placement[]
+ }
+}
+
+export interface PlayerInfoVars {
+ twitter: string
+}
diff --git a/frontend-react/src/utils/lists.ts b/frontend-react/src/utils/lists.ts
index 817c8f67c..dd9820497 100644
--- a/frontend-react/src/utils/lists.ts
+++ b/frontend-react/src/utils/lists.ts
@@ -766,6 +766,8 @@ export const modes = [
"Clam Blitz",
] as const
+export const modesShort = ["", "sz", "tc", "rm", "cb"] as const
+
export const months = [
"",
"January",
diff --git a/frontend-react/tsconfig.json b/frontend-react/tsconfig.json
index af10394b4..74ed9bb87 100644
--- a/frontend-react/tsconfig.json
+++ b/frontend-react/tsconfig.json
@@ -2,7 +2,7 @@
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
- "allowJs": true,
+ "allowJs": false,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
diff --git a/graphql-schemas/placement.js b/graphql-schemas/placement.js
index c0807448b..ba9bf5f66 100644
--- a/graphql-schemas/placement.js
+++ b/graphql-schemas/placement.js
@@ -5,7 +5,7 @@ const Player = require("../mongoose-models/player")
const typeDef = gql`
extend type Query {
topPlayers(weapon: String!): topPlayer!
- playerInfo(uid: String, twitter: String): PlayerWithPlacements!
+ playerInfo(uid: String, twitter: String): PlayerWithPlacements
searchForPlayers(name: String!, exact: Boolean): [Placement]!
searchForPlacements(
name: String
@@ -92,12 +92,11 @@ const resolvers = {
})
if (!player) {
- throw new UserInputError("player not found", {
- invalidArgs: args,
- })
+ return null
}
+
const placements = await Placement.find({ unique_id: player.unique_id })
- .sort({ year: "desc", month: "desc", mode: "asc" })
+ .sort({ year: "desc", month: "desc" })
.catch(e => {
throw new UserInputError(e.message, {
invalidArgs: args,
diff --git a/package-lock.json b/package-lock.json
index b8fd60805..c6175fa54 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -559,9 +559,9 @@
}
},
"axios": {
- "version": "0.19.1",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.1.tgz",
- "integrity": "sha512-Yl+7nfreYKaLRvAvjNPkvfjnQHJM1yLBY3zhqAwcJSwR/6ETkanUgylgtIvkvz0xJ+p/vZuNw8X7Hnb7Whsbpw==",
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
+ "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
"requires": {
"follow-redirects": "1.5.10"
}
diff --git a/package.json b/package.json
index 5679a6979..05fb3bb12 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
"@types/react-color": "^3.0.1",
"apollo-server": "^2.9.16",
"apollo-server-express": "^2.9.16",
- "axios": "^0.19.1",
+ "axios": "^0.19.2",
"btoa": "^1.2.1",
"connect-mongo": "^3.2.0",
"cors": "^2.8.5",