top 500 progress

This commit is contained in:
Sendou
2020-02-25 03:11:23 +02:00
parent 0ae439044a
commit 8401729f43
13 changed files with 380 additions and 58 deletions

View File

@@ -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",

View File

@@ -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",

View File

@@ -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;
}

View File

@@ -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<PaginationProps> = ({}) => {
const { colorMode, themeColorHex } = useContext(MyThemeContext)
return (
<Box className="pagination">
<Link to="/" style={{ color: colorMode === "light" ? "black" : "white" }}>
&laquo;
</Link>
<Link to="/" style={{ color: colorMode === "light" ? "black" : "white" }}>
1
</Link>
<Link
to="/"
className="active"
style={{
color: colorMode === "light" ? "black" : "white",
borderBottomColor: themeColorHex,
}}
>
2
</Link>
<Link to="/" style={{ color: colorMode === "light" ? "black" : "white" }}>
&raquo;
</Link>
</Box>
)
}
export default Pagination

View File

@@ -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<UserAvatarProps & BoxProps> = ({

View File

@@ -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 = () => {
<MapPlannerPage path="/plans" />
<CalendarPage path="/calendar" />
<FreeAgentsPage path="/freeagents" />
<XSearch path="/xsearch" />
<About path="/about" />
<Links path="/links" />
<NotFound default />

View File

@@ -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<ResultsProps> = ({ results, canAddResults }) => {
const [showModal, setShowModal] = useState(false)
const [expandedTweets, setExpandedTweets] = useState<{
@@ -39,7 +25,6 @@ const Results: React.FC<ResultsProps> = ({ results, canAddResults }) => {
const { grayWithShade } = useContext(MyThemeContext)
const isSmall = useBreakPoints(350)
console.log("results", results)
return (
<>
{showModal && <AddResultModal closeModal={() => setShowModal(false)} />}

View File

@@ -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;
}

View File

@@ -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"
/*<Icon
name={key as any}
color={themeColorWithShade}
size="5em"
/>*/
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<RouteComponentProps> = () => {
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<SearchForPlacementsVars>({
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 <Error errorMessage={error.message} />
if (loading || !data) return <Loading />
const placements = data.searchForPlacements.placements
console.log("placements[0]", placements)
return (
<>
<Helmet>
<title>Top 500 Browser</title>
</Helmet>
{/*<Box mt="1em">
<Top500Forms
forms={forms}
setForms={setForms}
onSubmit={() => setQuery(forms)}
onClear={handleClear}
/>
</Box>*/}
<Pagination />
<Box textAlign="center">
<Table>
<Thead>
<Tr>
<Th>Name</Th>
<Th>Weapon</Th>
<Th>X Power</Th>
<Th>Placement</Th>
<Th>Mode</Th>
<Th>Month</Th>
<Th>Year</Th>
</Tr>
</Thead>
<Tbody>
{placements.map(placement => (
<Tr key={placement.id}>
<Td>
<Flex alignItems="center">
{placement.player?.twitter && (
<UserAvatar
name={placement.name}
twitterName={placement.player.twitter}
size="sm"
/>
)}
<Box
as="span"
ml={placement.player?.twitter ? "0.5em" : undefined}
>
{placement.name}
</Box>
</Flex>
</Td>
<Td>
<Flex alignItems="center">
<Box
ml={isSmall ? undefined : "auto"}
mr={isSmall ? undefined : "auto"}
>
<WpnImage
englishName={placement.weapon as Weapon}
size="SMALL"
/>
</Box>
</Flex>
</Td>
<Td>{placement.x_power}</Td>
<Td>
{placement.rank}
{ordinal_suffix_of(placement.rank)}
</Td>
<Td>
<Icon
name={modesShort[placement.mode] as any}
color={themeColorWithShade}
size="2em"
/>
</Td>
<Td>{months[placement.month]}</Td>
<Td>{placement.year}</Td>
</Tr>
))}
</Tbody>
</Table>
</Box>
<Pagination />
{/*<div style={{ margin: "1em 0 1em 0" }}>
<Pagination
activePage={forms.page}
onPageChange={(e, { activePage }) => {
setForms({ ...forms, page: activePage })
setQuery({ ...query, page: activePage })
}}
totalPages={data.searchForPlacements.pageCount}
firstItem={null}
lastItem={null}
prevItem={{ content: <Icon name="angle left" />, icon: true }}
nextItem={{ content: <Icon name="angle right" />, icon: true }}
/>
</div>*/}
{/*<div style={{ margin: "1em 0 1em 0" }}>
<Pagination
activePage={forms.page}
onPageChange={(e, { activePage }) => {
setForms({ ...forms, page: activePage })
setQuery({ ...query, page: activePage })
window.scrollTo(0, 0)
}}
totalPages={data.searchForPlacements.pageCount}
firstItem={null}
lastItem={null}
prevItem={{ content: <Icon name="angle left" />, icon: true }}
nextItem={{ content: <Icon name="angle right" />, icon: true }}
/>
</div>*/}
</>
)
}
export default Top500BrowserPage

View File

@@ -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
}
}
`

View File

@@ -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
}
}
`

View File

@@ -6,3 +6,4 @@ declare module "*.png" {
}
declare module "@sendou/react-sketch"
declare module "react-super-responsive-table"

View File

@@ -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"
}