mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-26 13:17:15 -05:00
draft cup detail page data queried
This commit is contained in:
12
frontend-react/package-lock.json
generated
12
frontend-react/package-lock.json
generated
@@ -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"
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
91
frontend-react/src/graphql/queries/searchForDraftCup.ts
Normal file
91
frontend-react/src/graphql/queries/searchForDraftCup.ts
Normal 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
|
||||
}
|
||||
}
|
||||
`
|
||||
@@ -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
|
||||
//==============================================================================
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user