diff --git a/frontend-react/package-lock.json b/frontend-react/package-lock.json index b5884fe0b..18e66b654 100644 --- a/frontend-react/package-lock.json +++ b/frontend-react/package-lock.json @@ -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" diff --git a/frontend-react/package.json b/frontend-react/package.json index bab56f5e2..c59edec4f 100644 --- a/frontend-react/package.json +++ b/frontend-react/package.json @@ -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", diff --git a/frontend-react/src/components/plusdraftcup/DraftCupDetails.tsx b/frontend-react/src/components/plusdraftcup/DraftCupDetails.tsx new file mode 100644 index 000000000..22e92e186 --- /dev/null +++ b/frontend-react/src/components/plusdraftcup/DraftCupDetails.tsx @@ -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 = ({ + 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 + if (error) return + + console.log("data", data) + + const { tournament, matches } = data!.searchForDraftCup + + return ( + <> + + + + + + + + ) +} + +export default DraftCupDetails diff --git a/frontend-react/src/components/plusdraftcup/DraftTournamentCards.tsx b/frontend-react/src/components/plusdraftcup/DraftTournamentCards.tsx index 3a7ac2261..b6dcd21f0 100644 --- a/frontend-react/src/components/plusdraftcup/DraftTournamentCards.tsx +++ b/frontend-react/src/components/plusdraftcup/DraftTournamentCards.tsx @@ -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 = ({ - tournaments, +export const DraftTournamentCard: React.FC = ({ + 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 = ({ players, @@ -56,9 +73,14 @@ const DraftTournamentCards: React.FC = ({ }) => { return ( - {" "} + {" "} {players.map(user => ( - + @@ -85,6 +107,56 @@ const DraftTournamentCards: React.FC = ({ ) } + return ( + + + {tournament.name} + + + {dateStr} + + + + + + + + + + ) +} + +const DraftTournamentCards: React.FC = ({ + tournaments, +}) => { return ( <> = ({ 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 ( - - - - {tournament.name} - - - {dateStr} - - - - - - - - - + + ) })} diff --git a/frontend-react/src/components/root/Routes.tsx b/frontend-react/src/components/root/Routes.tsx index 368fd67d6..5757dd49c 100644 --- a/frontend-react/src/components/root/Routes.tsx +++ b/frontend-react/src/components/root/Routes.tsx @@ -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 = () => { + diff --git a/frontend-react/src/graphql/queries/plusDraftCups.ts b/frontend-react/src/graphql/queries/plusDraftCups.ts index 47b044bf9..667baaed4 100644 --- a/frontend-react/src/graphql/queries/plusDraftCups.ts +++ b/frontend-react/src/graphql/queries/plusDraftCups.ts @@ -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 } diff --git a/frontend-react/src/graphql/queries/searchForDraftCup.ts b/frontend-react/src/graphql/queries/searchForDraftCup.ts new file mode 100644 index 000000000..9c368bb0a --- /dev/null +++ b/frontend-react/src/graphql/queries/searchForDraftCup.ts @@ -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 + } + } +` diff --git a/frontend-react/src/types.ts b/frontend-react/src/types.ts index 4a52a693c..8ffdf1970 100644 --- a/frontend-react/src/types.ts +++ b/frontend-react/src/types.ts @@ -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 //============================================================================== diff --git a/graphql-schemas/detailedtournament.js b/graphql-schemas/detailedtournament.js index c19e7070d..afeef7372 100644 --- a/graphql-schemas/detailedtournament.js +++ b/graphql-schemas/detailedtournament.js @@ -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) => { diff --git a/graphql-schemas/maps.js b/graphql-schemas/maps.js index 942b29350..050ad0c8a 100644 --- a/graphql-schemas/maps.js +++ b/graphql-schemas/maps.js @@ -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) => { diff --git a/mongoose-models/detailedmatch.js b/mongoose-models/detailedmatch.js index c0fd7b08f..c4d7f463c 100644 --- a/mongoose-models/detailedmatch.js +++ b/mongoose-models/detailedmatch.js @@ -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)