From 62a11ddd41979aaa44fca200005a4ee1031cfee0 Mon Sep 17 00:00:00 2001 From: Sendou Date: Thu, 23 Jan 2020 01:43:41 +0200 Subject: [PATCH] x rank tab progress --- frontend-react/src/assets/icons.tsx | 46 +++++ .../src/components/builds/BuildCard.tsx | 2 +- .../src/components/user/UserPage.tsx | 37 +++- .../src/components/user/XRankTab.tsx | 164 ++++++++++++++++++ .../src/graphql/queries/playerInfo.js | 34 ---- .../src/graphql/queries/playerInfo.ts | 18 ++ frontend-react/src/index.tsx | 12 +- frontend-react/src/types.ts | 22 +++ frontend-react/src/utils/lists.ts | 2 + frontend-react/tsconfig.json | 2 +- graphql-schemas/placement.js | 9 +- package-lock.json | 6 +- package.json | 2 +- 13 files changed, 305 insertions(+), 51 deletions(-) create mode 100644 frontend-react/src/assets/icons.tsx create mode 100644 frontend-react/src/components/user/XRankTab.tsx delete mode 100644 frontend-react/src/graphql/queries/playerInfo.js create mode 100644 frontend-react/src/graphql/queries/playerInfo.ts 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 }) => { x rank top 500 logo 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",