draft cup detail page data queried

This commit is contained in:
Sendou
2020-03-29 15:43:24 +03:00
parent 3cb319379b
commit d7fe26326a
11 changed files with 320 additions and 66 deletions

View File

@@ -2153,9 +2153,9 @@
}
},
"@testing-library/user-event": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-10.0.0.tgz",
"integrity": "sha512-ygQ1SaX3AzWDGPer5e2LF7FvWwLPG+XYViHvpW4ObseOkqmJI2ruawp9iLmEwxQW88jNCCExvonh0jBAwwiYZw=="
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-10.0.1.tgz",
"integrity": "sha512-M63ftowo1QpAGMnWyz7df0ygqnu4XyF68Sty7mivMAz2HLcY1uLoN3qcen6WMobdY0MoZUi4+BLsziSDAP62Vg=="
},
"@types/babel__core": {
"version": "7.1.6",
@@ -2392,9 +2392,9 @@
}
},
"@types/react": {
"version": "16.9.26",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.26.tgz",
"integrity": "sha512-dGuSM+B0Pq1MKXYUMlUQWeS6Jj9IhSAUf9v8Ikaimj+YhkBcQrihWBkmyEhK/1fzkJTwZQkhZp5YhmWa2CH+Rw==",
"version": "16.9.27",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.27.tgz",
"integrity": "sha512-j+RvQb9w7a2kZFBOgTh+s/elCwtqWUMN6RJNdmz0ntmwpeoMHKnyhUcmYBu7Yw94Rtj9938D+TJSn6WGcq2+OA==",
"requires": {
"@types/prop-types": "*",
"csstype": "^2.2.0"

View File

@@ -12,10 +12,10 @@
"@sendou/react-sketch": "^0.5.2",
"@testing-library/jest-dom": "^5.3.0",
"@testing-library/react": "^10.0.1",
"@testing-library/user-event": "^10.0.0",
"@testing-library/user-event": "^10.0.1",
"@types/jest": "^25.1.4",
"@types/reach__router": "^1.3.1",
"@types/react": "^16.9.26",
"@types/react": "^16.9.27",
"@types/react-color": "^3.0.1",
"@types/react-datepicker": "^2.11.0",
"@types/react-dom": "^16.9.5",

View File

@@ -0,0 +1,50 @@
import React from "react"
import { RouteComponentProps } from "@reach/router"
import {
SEARCH_FOR_DRAFT_CUP,
SearchForDraftCupData,
SearchForDraftCupVars,
} from "../../graphql/queries/searchForDraftCup"
import { useQuery } from "@apollo/react-hooks"
import Loading from "../common/Loading"
import Error from "../common/Error"
import { DraftTournamentCard } from "./DraftTournamentCards"
import Button from "../elements/Button"
import { FaExternalLinkAlt } from "react-icons/fa"
import { Box } from "@chakra-ui/core"
interface DraftCupDetailsProps {
id?: string
}
const DraftCupDetails: React.FC<RouteComponentProps & DraftCupDetailsProps> = ({
id,
}) => {
const idParts = id!.split("-")
const { data, error, loading } = useQuery<
SearchForDraftCupData,
SearchForDraftCupVars
>(SEARCH_FOR_DRAFT_CUP, { variables: { name: "+2 Draft Cup March 2020" } })
if (loading) return <Loading />
if (error) return <Error errorMessage={error.message} />
console.log("data", data)
const { tournament, matches } = data!.searchForDraftCup
return (
<>
<DraftTournamentCard tournament={tournament} />
<Box mt="1em">
<a href={tournament.bracket_url}>
<Button icon={FaExternalLinkAlt} outlined>
Bracket
</Button>
</a>
</Box>
</>
)
}
export default DraftCupDetails

View File

@@ -23,7 +23,6 @@ interface DraftTournamentCardsProps {
top_3_team_names: string[]
top_3_discord_users: {
username: string
discord_id: string
discriminator: string
twitter_name?: string
}[][]
@@ -33,10 +32,24 @@ interface DraftTournamentCardsProps {
}[]
}
interface DraftTournamentCardProps {
tournament: {
name: string
top_3_team_names: string[]
top_3_discord_users: {
username: string
discriminator: string
twitter_name?: string
}[][]
bracket_url: string
date: string
type: "DRAFTONE" | "DRAFTTWO"
}
}
interface MedalRowProps {
players: {
username: string
discord_id: string
discriminator: string
twitter_name?: string
}[]
@@ -44,10 +57,14 @@ interface MedalRowProps {
small?: boolean
}
const DraftTournamentCards: React.FC<DraftTournamentCardsProps> = ({
tournaments,
export const DraftTournamentCard: React.FC<DraftTournamentCardProps> = ({
tournament,
}) => {
const { grayWithShade, darkerBgColor } = useContext(MyThemeContext)
const a = new Date(parseInt(tournament.date))
const dateStr = `${a.getDate()} ${
months[a.getMonth() + 1]
} ${a.getFullYear()}`
const MedalRow: React.FC<MedalRowProps> = ({
players,
@@ -56,9 +73,14 @@ const DraftTournamentCards: React.FC<DraftTournamentCardsProps> = ({
}) => {
return (
<Flex alignItems="center" mt="1.5em" fontWeight="semibold" as="h4">
<Image w="30px" h="auto" src={medalImage} mr="0.5em" />{" "}
<Image
w={small ? "30px" : "40px"}
h="auto"
src={medalImage}
mr="0.5em"
/>{" "}
{players.map(user => (
<Box key={user.discord_id} mx="0.2em">
<Box key={`${user.username}#${user.discriminator}`} mx="0.2em">
<Popover trigger="hover" placement="top-start">
<PopoverTrigger>
<Box>
@@ -85,6 +107,56 @@ const DraftTournamentCards: React.FC<DraftTournamentCardsProps> = ({
)
}
return (
<Box
display="flex"
rounded="lg"
overflow="hidden"
boxShadow="0px 0px 16px 6px rgba(0,0,0,0.1)"
p="25px"
w="100%"
h="100%"
flexDirection="column"
justifyContent="space-between"
transition="all 0.2s"
>
<Box fontWeight="semibold" as="h4" lineHeight="tight">
{tournament.name}
</Box>
<Box
color={grayWithShade}
fontWeight="semibold"
letterSpacing="wide"
fontSize="xs"
mt="0.5em"
>
{dateStr}
</Box>
<MedalRow
players={tournament.top_3_discord_users[0]}
medalImage={trophy}
/>
<Flex>
<MedalRow
players={tournament.top_3_discord_users[1]}
medalImage={medalEmoji[2]}
small
/>
<Box ml="1.5em">
<MedalRow
players={tournament.top_3_discord_users[2]}
medalImage={medalEmoji[3]}
small
/>
</Box>
</Flex>
</Box>
)
}
const DraftTournamentCards: React.FC<DraftTournamentCardsProps> = ({
tournaments,
}) => {
return (
<>
<Grid
@@ -93,55 +165,17 @@ const DraftTournamentCards: React.FC<DraftTournamentCardsProps> = ({
mt="1em"
>
{tournaments.map(tournament => {
const a = new Date(parseInt(tournament.date))
const dateStr = `${a.getDate()} ${
months[a.getMonth() + 1]
} ${a.getFullYear()}`
const date = new Date(parseInt(tournament.date))
return (
<Link key={tournament.bracket_url} to="/">
<Box
display="flex"
rounded="lg"
overflow="hidden"
boxShadow="0px 0px 16px 6px rgba(0,0,0,0.1)"
p="25px"
w="100%"
h="100%"
flexDirection="column"
justifyContent="space-between"
transition="all 0.2s"
>
<Box fontWeight="semibold" as="h4" lineHeight="tight">
{tournament.name}
</Box>
<Box
color={grayWithShade}
fontWeight="semibold"
letterSpacing="wide"
fontSize="xs"
mt="0.5em"
>
{dateStr}
</Box>
<MedalRow
players={tournament.top_3_discord_users[0]}
medalImage={trophy}
/>
<Flex>
<MedalRow
players={tournament.top_3_discord_users[1]}
medalImage={medalEmoji[2]}
small
/>
<Box ml="1.5em">
<MedalRow
players={tournament.top_3_discord_users[2]}
medalImage={medalEmoji[3]}
small
/>
</Box>
</Flex>
</Box>
<Link
key={tournament.bracket_url}
to={`/plus/draft/${
tournament.type === "DRAFTTWO" ? "2" : "1"
}-${months[
date.getMonth() + 1
].toLowerCase()}-${date.getFullYear()}`}
>
<DraftTournamentCard tournament={tournament} />
</Link>
)
})}

View File

@@ -19,6 +19,7 @@ const TeamPage = lazy(() => import("../team/TeamPage"))
const XSearch = lazy(() => import("../xsearch/Top500BrowserPage"))
const PlusPage = lazy(() => import("../plus/PlusPage"))
const DraftCupPage = lazy(() => import("../plusdraftcup/DraftCupPage"))
const DraftCupDetails = lazy(() => import("../plusdraftcup/DraftCupDetails"))
const Access = lazy(() => import("./Access"))
const VotingHistoryPage = lazy(() => import("../plus/VotingHistoryPage"))
const MapVotingHistoryPage = lazy(() => import("../plus/MapVotingHistoryPage"))
@@ -47,6 +48,7 @@ const Routes: React.FC = () => {
<Access path="/access" />
<PlusPage path="/plus" />
<DraftCupPage path="/plus/draft" />
<DraftCupDetails path="/plus/draft/:id" />
<VotingHistoryPage path="/plus/history" />
<MapVotingHistoryPage path="/plus/maphistory" />
<MapVoting path="/plus/mapvoting" />

View File

@@ -7,7 +7,6 @@ export interface PlusDraftCupsData {
top_3_team_names: string[]
top_3_discord_users: {
username: string
discord_id: string
discriminator: string
twitter_name?: string
}[][]
@@ -41,7 +40,6 @@ export const PLUS_DRAFT_CUPS: DocumentNode = gql`
top_3_team_names
top_3_discord_users {
username
discord_id
discriminator
twitter_name
}

View File

@@ -0,0 +1,91 @@
import { gql, DocumentNode } from "apollo-boost"
import { DetailedTeamInfo } from "../../types"
export interface SearchForDraftCupData {
searchForDraftCup: {
tournament: {
name: string
bracket_url: string
date: string
top_3_team_names: string[]
top_3_discord_users: {
username: string
discriminator: string
twitter_name?: string
}[][]
participant_discord_ids: [string]
type: "DRAFTONE" | "DRAFTTWO"
}
matches: {
round_name: string
round_number: number
map_details: {
stage: string
mode: "TW" | "SZ" | "TC" | "RM" | "CB"
duration: number
winners: DetailedTeamInfo
losers: DetailedTeamInfo
}
}[]
}
}
export interface SearchForDraftCupVars {
name: string
}
export const SEARCH_FOR_DRAFT_CUP: DocumentNode = gql`
query searchForDraftCup($name: String!) {
searchForDraftCup(name: $name) {
tournament {
name
bracket_url
date
top_3_team_names
top_3_discord_users {
username
discriminator
twitter_name
}
participant_discord_ids
type
}
matches {
round_name
round_number
map_details {
stage
mode
duration
winners {
...teamInfoFields
}
losers {
...teamInfoFields
}
}
}
}
}
fragment teamInfoFields on TeamInfo {
team_name
score
players {
discord_user {
username
discriminator
twitter_name
}
weapon
main_abilities
sub_abilities
kills
assists
deaths
specials
paint
gear
}
}
`

View File

@@ -186,6 +186,27 @@ export interface Team {
tournament_results: TournamentResult[]
}
export interface DetailedTeamInfo {
team_name: string
score: number
players: {
discord_user: {
username: string
discriminator: string
twitter_name: string
}
weapon: Weapon
main_abilities: Ability[]
sub_abilities: Ability[][]
kills: number
assists: number
deaths: number
specials: number
paint: number
gear: (HeadGear | ClothingGear | ShoesGear)[]
}[]
}
//==============================================================================
// Apollo
//==============================================================================

View File

@@ -15,6 +15,7 @@ const {
const typeDef = gql`
extend type Query {
plusDraftCups: DraftCupCollection!
searchForDraftCup(name: String!): DraftCupDetailCollection!
}
extend type Mutation {
@@ -31,6 +32,11 @@ const typeDef = gql`
tournaments: [DetailedTournament!]!
}
type DraftCupDetailCollection {
tournament: DetailedTournament!
matches: [DetailedMatch!]!
}
input DetailedTournamentInput {
name: String!
bracket_url: String!
@@ -108,7 +114,7 @@ const typeDef = gql`
}
type DetailedPlayer {
discord_id: String!
discord_user: User!
weapon: String!
main_abilities: [Ability!]!
sub_abilities: [[Ability]!]!
@@ -275,6 +281,26 @@ const resolvers = {
return { leaderboards, tournaments }
},
searchForDraftCup: async (root, args) => {
// \ to escape + in the name
const tournament = await DetailedTournament.findOne({
name: { $regex: "\\" + args.name, $options: "i" },
}).populate("top_3_discord_users")
if (!tournament) return []
const matches = await DetailedMatch.find({
tournament_id: tournament._id,
})
.sort({
round_number: "asc",
game_number: "asc",
})
.populate("map_details.winners.players.discord_user")
.populate("map_details.losers.players.discord_user")
return { tournament, matches }
},
},
Mutation: {
addDetailedTournament: async (root, args) => {

View File

@@ -4,7 +4,7 @@ const {
gql,
} = require("apollo-server-express")
const Maplist = require("../mongoose-models/maplist")
const MapBallot = require("../mongoose-models/mapballot")
const MapBallot = require("../mongoose-models/mapballot") //[PositiveVoteCount!]!
const maps = require("../utils/maps")
const typeDef = gql`
@@ -12,6 +12,7 @@ const typeDef = gql`
maplists: [Maplist!]!
plusMaplists: [Maplist!]!
mapVotes: [MapVote!]
positiveVotes(mode: Mode = SZ): Boolean
}
input MapVoteInput {
@@ -92,6 +93,23 @@ const resolvers = {
return mapBallot.maps
},
positiveVotes: async (root, args, ctx) => {
const ballots = await MapBallot.find({})
const count = {}
ballots.forEach(ballot => {
ballot.maps.forEach(stage => {
let toIcrement = 0
if (stage[args.mode.toLowerCase()] === 1) toIcrement = 1
const votes = count[stage.name] ? count[stage.name] : 0
count[stage.name] = votes + toIcrement
})
})
console.log(count)
return true
},
},
Mutation: {
addMapVotes: async (root, args, ctx) => {

View File

@@ -38,4 +38,18 @@ const detailedMatchSchema = new mongoose.Schema({
type: String,
})
detailedMatchSchema.virtual("map_details.winners.players.discord_user", {
ref: "User",
localField: "map_details.winners.players.discord_id",
foreignField: "discord_id",
justOne: true,
})
detailedMatchSchema.virtual("map_details.losers.players.discord_user", {
ref: "User",
localField: "map_details.losers.players.discord_id",
foreignField: "discord_id",
justOne: true,
})
module.exports = mongoose.model("DetailedMatch", detailedMatchSchema)