diff --git a/frontend-react/package-lock.json b/frontend-react/package-lock.json index 1f325f44d..b55852c2e 100644 --- a/frontend-react/package-lock.json +++ b/frontend-react/package-lock.json @@ -12160,6 +12160,11 @@ "prop-types": "^15.5.8" } }, + "react-super-responsive-table": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-super-responsive-table/-/react-super-responsive-table-5.1.1.tgz", + "integrity": "sha512-YKynBZSUA4QcN+CJgQYvb4RSv8eXHO/8J2cJPAycW5DwdENRd0KgtE7myclnjQeDMxafiFTDILV73DIX2fRRXw==" + }, "react-transition-group": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", @@ -13065,6 +13070,26 @@ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==" }, + "serialize-query-params": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/serialize-query-params/-/serialize-query-params-0.3.0.tgz", + "integrity": "sha512-gtarsAa5B7L+v2mxbm0zTq8WjqwjgYHZmLsyvxGnlSfW2bWkokV0QKzRxLCGHF2aDqbQYCCNaj1/NP6DqbcEKQ==", + "requires": { + "query-string": "^5.0.0" + }, + "dependencies": { + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + } + } + }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -14597,6 +14622,14 @@ "@use-it/event-listener": "^0.1.2" } }, + "use-query-params": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/use-query-params/-/use-query-params-0.6.0.tgz", + "integrity": "sha512-AEZm0+TTYuV3/l/IC+Iyqkvol1muXWJd2hlgY2erFESvtZNIpU4BrsTo6jnOBFd/t6rTOQuFjKSmW/+TAy8mzQ==", + "requires": { + "serialize-query-params": "^0.3.0" + } + }, "use-sidecar": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.0.2.tgz", diff --git a/frontend-react/package.json b/frontend-react/package.json index 9adc4fa06..f49722fb0 100644 --- a/frontend-react/package.json +++ b/frontend-react/package.json @@ -38,8 +38,10 @@ "react-infinite-scroller": "^1.2.4", "react-scripts": "^3.4.0", "react-select": "^3.0.8", + "react-super-responsive-table": "^5.1.1", "react-tweet-embed": "^1.2.2", - "typescript": "^3.8.2" + "typescript": "^3.8.2", + "use-query-params": "^0.6.0" }, "scripts": { "start": "react-scripts start", diff --git a/frontend-react/src/components/common/Pagination.css b/frontend-react/src/components/common/Pagination.css new file mode 100644 index 000000000..64d3e0514 --- /dev/null +++ b/frontend-react/src/components/common/Pagination.css @@ -0,0 +1,21 @@ +.pagination { + display: inline-block; + border-color: red; +} + +.pagination a { + color: black; + float: left; + padding: 8px 16px; + text-decoration: none; + font-weight: bold; +} + +.pagination a.active { + border-bottom: 3px solid; +} + +.pagination a:hover:not(.active) { + background-color: rgba(165, 165, 165, 0.15); + border-radius: 5px; +} diff --git a/frontend-react/src/components/common/Pagination.tsx b/frontend-react/src/components/common/Pagination.tsx new file mode 100644 index 000000000..a47cefb4b --- /dev/null +++ b/frontend-react/src/components/common/Pagination.tsx @@ -0,0 +1,36 @@ +import React, { useContext } from "react" +import "./Pagination.css" +import { Box } from "@chakra-ui/core" +import { Link } from "@reach/router" +import MyThemeContext from "../../themeContext" + +interface PaginationProps {} + +const Pagination: React.FC = ({}) => { + const { colorMode, themeColorHex } = useContext(MyThemeContext) + return ( + + + « + + + 1 + + + 2 + + + » + + + ) +} + +export default Pagination diff --git a/frontend-react/src/components/common/UserAvatar.tsx b/frontend-react/src/components/common/UserAvatar.tsx index 42847e49a..44d44dc66 100644 --- a/frontend-react/src/components/common/UserAvatar.tsx +++ b/frontend-react/src/components/common/UserAvatar.tsx @@ -4,7 +4,7 @@ import { Avatar, BoxProps } from "@chakra-ui/core" interface UserAvatarProps { name: string twitterName?: string - size?: undefined | "2xl" + size?: undefined | "2xl" | "sm" } const UserAvatar: React.FC = ({ diff --git a/frontend-react/src/components/root/Routes.tsx b/frontend-react/src/components/root/Routes.tsx index 2a9328da9..9b6913b4d 100644 --- a/frontend-react/src/components/root/Routes.tsx +++ b/frontend-react/src/components/root/Routes.tsx @@ -11,6 +11,7 @@ const CalendarPage = lazy(() => import("../calendar/CalendarPage")) const MapPlannerPage = lazy(() => import("../plans/MapPlannerPage")) const FreeAgentsPage = lazy(() => import("../freeagents/FreeAgentsPage")) const TeamPage = lazy(() => import("../team/TeamPage")) +const XSearch = lazy(() => import("../xsearch/Top500BrowserPage")) const About = lazy(() => import("./About")) const Links = lazy(() => import("./Links")) @@ -26,6 +27,7 @@ const Routes: React.FC = () => { + diff --git a/frontend-react/src/components/team/Results.tsx b/frontend-react/src/components/team/Results.tsx index 45221e6f2..72eb329b6 100644 --- a/frontend-react/src/components/team/Results.tsx +++ b/frontend-react/src/components/team/Results.tsx @@ -10,27 +10,13 @@ import { IconButton } from "@chakra-ui/core" import { FaTwitter } from "react-icons/fa" import TweetEmbed from "react-tweet-embed" import useBreakPoints from "../../hooks/useBreakPoints" +import { ordinal_suffix_of } from "../../utils/helperFunctions" interface ResultsProps { results: TournamentResult[] canAddResults: boolean } -function ordinal_suffix_of(i: number) { - var j = i % 10, - k = i % 100 - if (j === 1 && k !== 11) { - return "st" - } - if (j === 2 && k !== 12) { - return "nd" - } - if (j === 3 && k !== 13) { - return "rd" - } - return "th" -} - const Results: React.FC = ({ results, canAddResults }) => { const [showModal, setShowModal] = useState(false) const [expandedTweets, setExpandedTweets] = useState<{ @@ -39,7 +25,6 @@ const Results: React.FC = ({ results, canAddResults }) => { const { grayWithShade } = useContext(MyThemeContext) const isSmall = useBreakPoints(350) - console.log("results", results) return ( <> {showModal && setShowModal(false)} />} diff --git a/frontend-react/src/components/xsearch/Top500BrowserPage.css b/frontend-react/src/components/xsearch/Top500BrowserPage.css new file mode 100644 index 000000000..5582fbdf3 --- /dev/null +++ b/frontend-react/src/components/xsearch/Top500BrowserPage.css @@ -0,0 +1,11 @@ +tr:nth-child(even) { + background-color: rgba(165, 165, 165, 0.15); +} + +tr { + border-radius: 5px; +} + +.responsiveTable tbody tr { + border: none; +} diff --git a/frontend-react/src/components/xsearch/Top500BrowserPage.tsx b/frontend-react/src/components/xsearch/Top500BrowserPage.tsx new file mode 100644 index 000000000..a385e7542 --- /dev/null +++ b/frontend-react/src/components/xsearch/Top500BrowserPage.tsx @@ -0,0 +1,217 @@ +import React, { useState, useContext } from "react" +import { useQuery } from "@apollo/react-hooks" +import { useQueryParams, StringParam, NumberParam } from "use-query-params" + +import Loading from "../common/Loading" +import Error from "../common/Error" +import { SEARCH_FOR_PLACEMENTS } from "../../graphql/queries/searchForPlacements" +//import Top500Forms from "./Top500Forms" +import WpnImage from "../common/WeaponImage" +import { months, modesShort } from "../../utils/lists" +import { RouteComponentProps } from "@reach/router" +import { Helmet } from "react-helmet-async" +import { Box, Flex, Icon } from "@chakra-ui/core" +import { Table, Thead, Tbody, Tr, Th, Td } from "react-super-responsive-table" +import "react-super-responsive-table/dist/SuperResponsiveTableStyle.css" +import { ordinal_suffix_of } from "../../utils/helperFunctions" +import { Weapon } from "../../types" +import UserAvatar from "../common/UserAvatar" +import MyThemeContext from "../../themeContext" +import useBreakPoints from "../../hooks/useBreakPoints" +import "./Top500BrowserPage.css" +import Pagination from "../common/Pagination" + +/**/ + +interface Placement { + id: string + mode: number + name: string + player?: { + twitter: string + } + rank: number + unique_id: string + weapon: string + x_power: number + month: number + year: number +} + +interface SearchForPlacementsData { + searchForPlacements: { + placements: Placement[] + pageCount: number + } +} + +interface SearchForPlacementsVars { + page?: number + name?: string + weapon?: string + mode?: number + unique_id?: string + month?: number + year?: number +} + +const Top500BrowserPage: React.FC = () => { + const { themeColorWithShade } = useContext(MyThemeContext) + const isSmall = useBreakPoints(640) + const [query, setQuery] = useQueryParams({ + page: NumberParam, + name: StringParam, + weapon: StringParam, + mode: NumberParam, + unique_id: StringParam, + month: NumberParam, + year: NumberParam, + }) + const [forms, setForms] = useState({ + page: query.page ?? 1, + name: query.name, + weapon: query.weapon, + mode: query.mode, + unique_id: query.unique_id, + month: query.month, + year: query.year, + }) + + const { data, error, loading } = useQuery< + SearchForPlacementsData, + SearchForPlacementsVars + >(SEARCH_FOR_PLACEMENTS, { + variables: query, + }) + + const handleClear = () => { + setForms({}) + } + + if (error) return + if (loading || !data) return + + const placements = data.searchForPlacements.placements + + console.log("placements[0]", placements) + + return ( + <> + + Top 500 Browser + + {/* + setQuery(forms)} + onClear={handleClear} + /> + */} + + + + + + + + + + + + + + + + {placements.map(placement => ( + + + + + + + + + + ))} + +
NameWeaponX PowerPlacementModeMonthYear
+ + {placement.player?.twitter && ( + + )} + + {placement.name} + + + + + + + + + {placement.x_power} + {placement.rank} + {ordinal_suffix_of(placement.rank)} + + + {months[placement.month]}{placement.year}
+
+ + + + {/*
+ { + setForms({ ...forms, page: activePage }) + setQuery({ ...query, page: activePage }) + }} + totalPages={data.searchForPlacements.pageCount} + firstItem={null} + lastItem={null} + prevItem={{ content: , icon: true }} + nextItem={{ content: , icon: true }} + /> +
*/} + {/*
+ { + setForms({ ...forms, page: activePage }) + setQuery({ ...query, page: activePage }) + window.scrollTo(0, 0) + }} + totalPages={data.searchForPlacements.pageCount} + firstItem={null} + lastItem={null} + prevItem={{ content: , icon: true }} + nextItem={{ content: , icon: true }} + /> +
*/} + + ) +} + +export default Top500BrowserPage diff --git a/frontend-react/src/graphql/queries/searchForPlacements.js b/frontend-react/src/graphql/queries/searchForPlacements.js deleted file mode 100644 index 47a0e44df..000000000 --- a/frontend-react/src/graphql/queries/searchForPlacements.js +++ /dev/null @@ -1,40 +0,0 @@ -import { gql } from 'apollo-boost' - -export const searchForPlacements = gql` -query searchForPlacements( - $name: String - $weapon: String - $mode: Int - $unique_id: String - $month: Int - $year: Int - $page: Int -) { - searchForPlacements( - name: $name - weapon: $weapon - mode: $mode - unique_id: $unique_id - month: $month - year: $year - page: $page - ) { - placements { - name - x_power - weapon - rank - id - unique_id - month - year - mode - player { - twitter - } - } - pageCount - } -} - -` \ No newline at end of file diff --git a/frontend-react/src/graphql/queries/searchForPlacements.ts b/frontend-react/src/graphql/queries/searchForPlacements.ts new file mode 100644 index 000000000..164b51d45 --- /dev/null +++ b/frontend-react/src/graphql/queries/searchForPlacements.ts @@ -0,0 +1,39 @@ +import { gql, DocumentNode } from "apollo-boost" + +export const SEARCH_FOR_PLACEMENTS: DocumentNode = gql` + query searchForPlacements( + $name: String + $weapon: String + $mode: Int + $unique_id: String + $month: Int + $year: Int + $page: Int + ) { + searchForPlacements( + name: $name + weapon: $weapon + mode: $mode + unique_id: $unique_id + month: $month + year: $year + page: $page + ) { + placements { + name + x_power + weapon + rank + id + unique_id + month + year + mode + player { + twitter + } + } + pageCount + } + } +` diff --git a/frontend-react/src/react-app-env.d.ts b/frontend-react/src/react-app-env.d.ts index f4c47f777..9d033394b 100644 --- a/frontend-react/src/react-app-env.d.ts +++ b/frontend-react/src/react-app-env.d.ts @@ -6,3 +6,4 @@ declare module "*.png" { } declare module "@sendou/react-sketch" +declare module "react-super-responsive-table" diff --git a/frontend-react/src/utils/helperFunctions.ts b/frontend-react/src/utils/helperFunctions.ts index 57fbb79cb..9ec9e202f 100644 --- a/frontend-react/src/utils/helperFunctions.ts +++ b/frontend-react/src/utils/helperFunctions.ts @@ -2,3 +2,18 @@ export function choose(choices: any[]) { var index = Math.floor(Math.random() * choices.length) return choices[index] } + +export function ordinal_suffix_of(i: number) { + var j = i % 10, + k = i % 100 + if (j === 1 && k !== 11) { + return "st" + } + if (j === 2 && k !== 12) { + return "nd" + } + if (j === 3 && k !== 13) { + return "rd" + } + return "th" +}