work on the new design

This commit is contained in:
Sendou
2019-08-22 15:44:32 +03:00
parent e9736fe57e
commit bc79d1d3c1
167 changed files with 1631 additions and 8433 deletions

View File

@@ -0,0 +1,6 @@
{
"ExpandedNodes": [
""
],
"PreviewInSolutionExplorer": false
}

BIN
.vs/sendou-ink/v16/.suo Normal file

Binary file not shown.

BIN
.vs/slnx.sqlite Normal file

Binary file not shown.

View File

@@ -11,4 +11,11 @@ const placementSchema = new mongoose.Schema({
year: {type: Number, min: 2017, required: true}
})
placementSchema.virtual('player', {
ref: 'Player',
localField: 'unique_id',
foreignField: 'unique_id',
justOne: true
})
module.exports = mongoose.model('Placement', placementSchema)

32
react-ui/src/App.js vendored
View File

@@ -5,18 +5,17 @@ import MainMenu from './components/Misc/MainMenu'
import NotFound from './components/Misc/NotFound'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import WeaponLeaderboardSelector from './components/XLeaderboard/WeaponLeaderboardSelector'
import PageXLeaderboard from './components/XLeaderboard/PageXLeaderboard'
import XSearch from './components/XSearch/XSearch'
import InfoPlayer from './components/XSearch/InfoPlayer'
import InfoWeapon from './components/XSearch/InfoWeapon'
import ScrollToTop from './utils/ScrollToTop'
import MapListGenerator from './components/Tools/MapListGenerator'
import Rotations from './components/Tools/Rotations'
import MapPlanner from './components/Tools/MapPlanner'
import PageMapListGenerator from './components/Tools/PageMapListGenerator'
import PageRotations from './components/Tools/PageRotations'
import PageMapPlanner from './components/Tools/PageMapPlanner'
import Links from './components/Misc/Links'
import UserPage from './components/SoloLadder/UserPage'
import HomePage from './components/Misc/HomePage'
import BuildSearch from './components/SoloLadder/BuildSearch'
import PageHome from './components/Misc/PageHome'
import PageBuilds from './components/Tools/PageBuilds'
import Admin from './components/Misc/Admin'
import Calendar from './components/Tools/Calendar'
import XTrends from './components/XSearch/XTrends'
@@ -28,23 +27,19 @@ const App = () => {
<Router>
<Container>
<MainMenu menuSelection={menuSelection} setMenuSelection={setMenuSelection} />
<div>
<ScrollToTop />
<Switch>
<Route exact path="/" render={() => <HomePage setMenuSelection={setMenuSelection} />} />
<Route path="/xleaderboard" render={() => <WeaponLeaderboardSelector setMenuSelection={setMenuSelection} />} />
<Route exact path="/" render={() => <PageHome setMenuSelection={setMenuSelection} />} />
<Route path="/xleaderboard" render={() => <PageXLeaderboard setMenuSelection={setMenuSelection} />} />
<Route exact path="/xsearch" render={() => <XSearch setMenuSelection={setMenuSelection} />} />
<Route exact path="/xsearch/w/:wpn" render={({ match }) =>
<InfoWeapon wpn={match.params.wpn.replace(/-/g, '_')} />
} />
<Route exact path="/xsearch/p/:uid" render={({ match }) =>
<InfoPlayer uid={match.params.uid} setMenuSelection={setMenuSelection} />
} />
<Route exact path="/maps" render={() =>
<MapListGenerator setMenuSelection={setMenuSelection} />
<PageMapListGenerator setMenuSelection={setMenuSelection} />
} />
<Route exact path="/rotation" render={() =>
<Rotations setMenuSelection={setMenuSelection} />
<PageRotations setMenuSelection={setMenuSelection} />
} />
<Route exact path="/links" render={() =>
<Links setMenuSelection={setMenuSelection} />
@@ -53,16 +48,16 @@ const App = () => {
<UserPage userIdOrName={match.params.user}/>
} />
<Route exact path="/builds" render={() =>
<BuildSearch setMenuSelection={setMenuSelection} />
<PageBuilds setMenuSelection={setMenuSelection} />
} />
<Route exact path="/builds/:weapon" render={({ match }) =>
<BuildSearch
<PageBuilds
setMenuSelection={setMenuSelection}
weaponFromUrl={match.params.weapon.replace(/_/g, ' ')}
/>
} />
<Route exact path="/plans" render={() =>
<MapPlanner
<PageMapPlanner
setMenuSelection={setMenuSelection}
/>
} />
@@ -80,7 +75,6 @@ const App = () => {
<Route path="/admin" render={() => <Admin />} />
<Route path="*" render={() => <NotFound />} />
</Switch>
</div>
<Footer />
</Container>
</Router>

View File

@@ -1,12 +1,15 @@
import React from 'react'
import { Menu, Button, Image, Dropdown } from 'semantic-ui-react'
import { useQuery } from '@apollo/react-hooks'
import { userLean } from '../../graphql/queries/userLean'
import { withRouter } from 'react-router-dom'
import memcake from '../img/misc/sink_logo.png'
import React from "react"
import { Menu, Button, Image, Dropdown } from "semantic-ui-react"
import { useQuery } from "@apollo/react-hooks"
import { userLean } from "../../graphql/queries/userLean"
import { withRouter } from "react-router-dom"
import { useSelector, useDispatch } from 'react-redux'
import memcake from "../../img/misc/sink_logo.png"
const MainMenu = withRouter(({ history, menuSelection, setMenuSelection }) => {
const { data, error, loading } = useQuery(userLean)
const localization = useSelector(state => state.localization)
const dispatch = useDispatch()
const logIn = () => {
if (loading) {
@@ -16,11 +19,8 @@ const MainMenu = withRouter(({ history, menuSelection, setMenuSelection }) => {
if (!data.user || error) {
return (
<Menu.Item>
<a href='/auth/discord'>
<Button
style={{'color': '#7289DA'}}
inverted
>
<a href="/auth/discord">
<Button style={{ color: "#7289DA" }} inverted>
Login via Discord
</Button>
</a>
@@ -31,106 +31,163 @@ const MainMenu = withRouter(({ history, menuSelection, setMenuSelection }) => {
const user = data.user
const userMenuOptions = [
{ key: 'user', text: 'User Page', icon: 'user', onClick: () => history.push(`/u/${user.discord_id}`) },
{
key: "user",
text: "User Page",
icon: "user",
onClick: () => history.push(`/u/${user.discord_id}`)
},
//{ key: 'settings', text: 'Settings', icon: 'settings', onClick: () => history.push('/u/settings') },
{ key: 'sign-out', text: 'Sign Out', icon: 'sign out', onClick: () => window.location.assign('/logout') },
{
key: "sign-out",
text: "Sign Out",
icon: "sign out",
onClick: () => window.location.assign("/logout")
}
]
const userMenuTrigger = (
<span>
<span style={{"paddingRight": "5px"}}>{user.username}</span>
<Image src={user.avatar ?
`https://cdn.discordapp.com/avatars/${user.discord_id}/${user.avatar}.png` :
'https://cdn.discordapp.com/avatars/455039198672453645/088ae3838cc3b08b73f79aab0fefec2f.png'} avatar /> {/* If User has no avatar defaults to N-Zap user's avatar*/}
<span style={{ paddingRight: "5px" }}>{user.username}</span>
<Image
src={
user.avatar
? `https://cdn.discordapp.com/avatars/${user.discord_id}/${
user.avatar
}.png`
: "https://cdn.discordapp.com/avatars/455039198672453645/088ae3838cc3b08b73f79aab0fefec2f.png"
}
avatar
/>{" "}
{/* If User has no avatar defaults to N-Zap user's avatar*/}
</span>
)
return (
<div>
<Menu.Item>
<Dropdown item icon={null} options={userMenuOptions} trigger={userMenuTrigger}/>
<Dropdown
item
icon={null}
options={userMenuOptions}
trigger={userMenuTrigger}
/>
</Menu.Item>
</div>
)
}
const language = localization.getLanguage()
const handleLanguageChange = (e, { value }) => {
dispatch({ type: 'SET_LANGUAGE', languageCode: value})
window.location.reload()
}
return (
<Menu stackable borderless>
<Menu.Item>
<img src={memcake} alt='memcake logo' />
<img src={memcake} alt="memcake logo" />
</Menu.Item>
<Menu.Item
name='home'
active={menuSelection === 'home'}
onClick={() => { history.push('/') }}
<Menu.Item
name="home"
active={menuSelection === "home"}
onClick={() => {
history.push("/")
}}
/>
<Dropdown item text='Tools'>
<Dropdown item text="Tools">
<Dropdown.Menu>
<Menu.Item
name='maplists'
active={menuSelection === 'maplists'}
onClick={() => { history.push('/maps') }}
/>
<Menu.Item
name='rotation'
active={menuSelection === 'rotations'}
onClick={() => {
history.push('/rotation')
setMenuSelection('rotations')
}}
/>
<Menu.Item
name='builds'
active={menuSelection === 'builds'}
onClick={() => {
history.push('/builds')
setMenuSelection('builds')
}}
/>
<Menu.Item
name='plan'
active={menuSelection === 'plans'}
onClick={() => {
history.push('/plans')
setMenuSelection('plans')
}}
/>
<Menu.Item
name="maplists"
active={menuSelection === "maplists"}
onClick={() => {
history.push("/maps")
}}
/>
<Menu.Item
name="rotation"
active={menuSelection === "rotations"}
onClick={() => {
history.push("/rotation")
setMenuSelection("rotations")
}}
/>
<Menu.Item
name="builds"
active={menuSelection === "builds"}
onClick={() => {
history.push("/builds")
setMenuSelection("builds")
}}
/>
<Menu.Item
name="plan"
active={menuSelection === "plans"}
onClick={() => {
history.push("/plans")
setMenuSelection("plans")
}}
/>
</Dropdown.Menu>
</Dropdown>
<Dropdown item text='X Rank'>
<Dropdown.Menu>
<Dropdown item text="X Rank">
<Dropdown.Menu>
<Menu.Item
name='leaderboards'
active={menuSelection === 'leaderboards'}
onClick={() => { history.push('/xleaderboard') }}
name="leaderboards"
active={menuSelection === "leaderboards"}
onClick={() => {
history.push("/xleaderboard")
}}
/>
<Menu.Item
name='top 500 search'
active={menuSelection === 'search'}
onClick={() => { history.push('/xsearch') }}
name="top 500 search"
active={menuSelection === "search"}
onClick={() => {
history.push("/xsearch")
}}
/>
<Menu.Item
name='trends'
active={menuSelection === 'trends'}
onClick={() => { history.push('/trends') }}
name="trends"
active={menuSelection === "trends"}
onClick={() => {
history.push("/trends")
}}
/>
</Dropdown.Menu>
</Dropdown.Menu>
</Dropdown>
<Menu.Item
name='calendar'
active={menuSelection === 'calendar'}
onClick={() => { history.push('/calendar') }}
name="calendar"
active={menuSelection === "calendar"}
onClick={() => {
history.push("/calendar")
}}
/>
<Menu.Item
name='links'
active={menuSelection === 'links'}
onClick={() => { history.push('/links') }}
name="links"
active={menuSelection === "links"}
onClick={() => {
history.push("/links")
}}
/>
<Menu.Menu position='right'>
<Menu.Menu position="right">
<Dropdown item icon="globe" simple>
<Dropdown.Menu>
<Dropdown.Item value="en-us" active={language === 'en-us'} onClick={handleLanguageChange}>English</Dropdown.Item>
<Dropdown.Item value="ja-jp" active={language === 'ja-jp'} onClick={handleLanguageChange}>日本語</Dropdown.Item>
<Dropdown.Item value="fr-eu" active={language === 'fr-eu'} onClick={handleLanguageChange}>Français</Dropdown.Item>
<Dropdown.Item value="de-eu" active={language === 'de-eu'} onClick={handleLanguageChange}>Deutsch</Dropdown.Item>
<Dropdown.Item value="es-eu" active={language === 'es-eu'} onClick={handleLanguageChange}>Español</Dropdown.Item>
<Dropdown.Item value="it-eu" active={language === 'it-eu'} onClick={handleLanguageChange}>Italiano</Dropdown.Item>
<Dropdown.Item value="ch" active={language === 'ch'} onClick={handleLanguageChange}>简体中文</Dropdown.Item>
<Dropdown.Item value="ru-eu" active={language === 'ru-eu'} onClick={handleLanguageChange}>Русский</Dropdown.Item>
<Dropdown.Item value="nl-eu" active={language === 'nl-eu'} onClick={handleLanguageChange}>Nederlands</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
{logIn()}
</Menu.Menu>
</Menu>
)
})
export default MainMenu
export default MainMenu

View File

@@ -1,13 +1,13 @@
import React from 'react'
import { Header } from 'semantic-ui-react'
import bridge from '../img/s1Maps/bridge.png'
import depot from '../img/s1Maps/depot.png'
import heights from '../img/s1Maps/heights.png'
import mahi from '../img/s1Maps/mahi.png'
import museum from '../img/s1Maps/museum.png'
import rig from '../img/s1Maps/rig.png'
import underpass from '../img/s1Maps/underpass.png'
import bridge from '../../img/s1Maps/bridge.png'
import depot from '../../img/s1Maps/depot.png'
import heights from '../../img/s1Maps/heights.png'
import mahi from '../../img/s1Maps/mahi.png'
import museum from '../../img/s1Maps/museum.png'
import rig from '../../img/s1Maps/rig.png'
import underpass from '../../img/s1Maps/underpass.png'
const NotFound = () => {
const maps = [

View File

@@ -1,15 +1,12 @@
import React, { useState } from "react"
import React from "react"
import { Header, Image, Segment } from "semantic-ui-react"
import { Link } from "react-router-dom"
import { useSelector } from 'react-redux'
import { Button } from 'antd'
import koshienBanner from "../img/misc/koshienBanner.png"
import koshienBanner from "../../img/misc/koshienBanner.png"
const HomePage = ({ setMenuSelection }) => {
const PageHome = ({ setMenuSelection }) => {
setMenuSelection("home")
return (
<div>
<Segment>
<Segment>
<div style={{ padding: "5px" }}>
<div style={{ textAlign: "center" }}>
<Header as="h2">
@@ -31,7 +28,7 @@ const HomePage = ({ setMenuSelection }) => {
- Generate a maplist to use when scrimming. You can choose the map
pool to be used including monthly ranked maps or an upcoming event.
Any maps you don't feel like you need to practice can be excluded
from the pool. <Button type='primary'>Buttoni</Button>
from the pool.
</div>
<div style={{ paddingTop: "15px" }}>
<b>
@@ -87,9 +84,8 @@ const HomePage = ({ setMenuSelection }) => {
<Image rounded src={koshienBanner} size="huge" centered />
</div>
</div>
</Segment>
</div>
</Segment>
)
}
export default HomePage
export default PageHome

View File

@@ -3,32 +3,32 @@ import { Grid, Comment } from "semantic-ui-react"
import { clothingGear, shoesGear, headGear, choose } from "../../utils/lists"
import useWindowDimensions from "../hooks/useWindowDimensions"
import BDU from "../img/abilityIcons/BDU.png"
import BRU from "../img/abilityIcons/BRU.png"
import CB from "../img/abilityIcons/CB.png"
import DR from "../img/abilityIcons/DR.png"
import H from "../img/abilityIcons/H.png"
import ISM from "../img/abilityIcons/ISM.png"
import ISS from "../img/abilityIcons/ISS.png"
import LDE from "../img/abilityIcons/LDE.png"
import MPU from "../img/abilityIcons/MPU.png"
import NS from "../img/abilityIcons/NS.png"
import OG from "../img/abilityIcons/OG.png"
import QR from "../img/abilityIcons/QR.png"
import QSJ from "../img/abilityIcons/QSJ.png"
import REC from "../img/abilityIcons/REC.png"
import RES from "../img/abilityIcons/RES.png"
import RP from "../img/abilityIcons/RP.png"
import RSU from "../img/abilityIcons/RSU.png"
import SCU from "../img/abilityIcons/SCU.png"
import SJ from "../img/abilityIcons/SJ.png"
import SPU from "../img/abilityIcons/SPU.png"
import SS from "../img/abilityIcons/SS.png"
import SSU from "../img/abilityIcons/SSU.png"
import T from "../img/abilityIcons/T.png"
import TI from "../img/abilityIcons/TI.png"
import OS from "../img/abilityIcons/OS.png"
import murchpfp from "../img/misc/murchpfp.png"
import BDU from '../../img/abilityIcons/BDU.png'
import BRU from "../../img/abilityIcons/BRU.png"
import CB from "../../img/abilityIcons/CB.png"
import DR from "../../img/abilityIcons/DR.png"
import H from "../../img/abilityIcons/H.png"
import ISM from "../../img/abilityIcons/ISM.png"
import ISS from "../../img/abilityIcons/ISS.png"
import LDE from "../../img/abilityIcons/LDE.png"
import MPU from "../../img/abilityIcons/MPU.png"
import NS from "../../img/abilityIcons/NS.png"
import OG from "../../img/abilityIcons/OG.png"
import QR from "../../img/abilityIcons/QR.png"
import QSJ from "../../img/abilityIcons/QSJ.png"
import REC from "../../img/abilityIcons/REC.png"
import RES from "../../img/abilityIcons/RES.png"
import RP from "../../img/abilityIcons/RP.png"
import RSU from "../../img/abilityIcons/RSU.png"
import SCU from "../../img/abilityIcons/SCU.png"
import SJ from "../../img/abilityIcons/SJ.png"
import SPU from "../../img/abilityIcons/SPU.png"
import SS from "../../img/abilityIcons/SS.png"
import SSU from "../../img/abilityIcons/SSU.png"
import T from "../../img/abilityIcons/T.png"
import TI from "../../img/abilityIcons/TI.png"
import OS from "../../img/abilityIcons/OS.png"
import murchpfp from "../../img/misc/murchpfp.png"
import head from "../../utils/head.json"
import clothes from "../../utils/clothes.json"
import shoes from "../../utils/shoes.json"

View File

@@ -2,31 +2,31 @@
import React from 'react'
import { Button } from 'semantic-ui-react'
import BDU from '../img/abilityIcons/BDU.png'
import BRU from '../img/abilityIcons/BRU.png'
import CB from '../img/abilityIcons/CB.png'
import DR from '../img/abilityIcons/DR.png'
import H from '../img/abilityIcons/H.png'
import ISM from '../img/abilityIcons/ISM.png'
import ISS from '../img/abilityIcons/ISS.png'
import LDE from '../img/abilityIcons/LDE.png'
import MPU from '../img/abilityIcons/MPU.png'
import NS from '../img/abilityIcons/NS.png'
import OG from '../img/abilityIcons/OG.png'
import QR from '../img/abilityIcons/QR.png'
import QSJ from '../img/abilityIcons/QSJ.png'
import REC from '../img/abilityIcons/REC.png'
import RES from '../img/abilityIcons/RES.png'
import RP from '../img/abilityIcons/RP.png'
import RSU from '../img/abilityIcons/RSU.png'
import SCU from '../img/abilityIcons/SCU.png'
import SJ from '../img/abilityIcons/SJ.png'
import SPU from '../img/abilityIcons/SPU.png'
import SS from '../img/abilityIcons/SS.png'
import SSU from '../img/abilityIcons/SSU.png'
import T from '../img/abilityIcons/T.png'
import TI from '../img/abilityIcons/TI.png'
import OS from '../img/abilityIcons/OS.png'
import BDU from '../../img/abilityIcons/BDU.png'
import BRU from '../../img/abilityIcons/BRU.png'
import CB from '../../img/abilityIcons/CB.png'
import DR from '../../img/abilityIcons/DR.png'
import H from '../../img/abilityIcons/H.png'
import ISM from '../../img/abilityIcons/ISM.png'
import ISS from '../../img/abilityIcons/ISS.png'
import LDE from '../../img/abilityIcons/LDE.png'
import MPU from '../../img/abilityIcons/MPU.png'
import NS from '../../img/abilityIcons/NS.png'
import OG from '../../img/abilityIcons/OG.png'
import QR from '../../img/abilityIcons/QR.png'
import QSJ from '../../img/abilityIcons/QSJ.png'
import REC from '../../img/abilityIcons/REC.png'
import RES from '../../img/abilityIcons/RES.png'
import RP from '../../img/abilityIcons/RP.png'
import RSU from '../../img/abilityIcons/RSU.png'
import SCU from '../../img/abilityIcons/SCU.png'
import SJ from '../../img/abilityIcons/SJ.png'
import SPU from '../../img/abilityIcons/SPU.png'
import SS from '../../img/abilityIcons/SS.png'
import SSU from '../../img/abilityIcons/SSU.png'
import T from '../../img/abilityIcons/T.png'
import TI from '../../img/abilityIcons/TI.png'
import OS from '../../img/abilityIcons/OS.png'
const headOnly = ["CB", "LDE", "OG", "T"]
const clothingOnly = ["H", "NS", "TI", "RP"]

View File

@@ -4,32 +4,32 @@ import { Header, Segment, List, Grid, Button, Popup } from 'semantic-ui-react'
import weaponDict from '../../utils/english_internal.json'
import BuildForm from './BuildForm'
import BDU from '../img/abilityIcons/BDU.png'
import BRU from '../img/abilityIcons/BRU.png'
import CB from '../img/abilityIcons/CB.png'
import DR from '../img/abilityIcons/DR.png'
import H from '../img/abilityIcons/H.png'
import ISM from '../img/abilityIcons/ISM.png'
import ISS from '../img/abilityIcons/ISS.png'
import LDE from '../img/abilityIcons/LDE.png'
import MPU from '../img/abilityIcons/MPU.png'
import NS from '../img/abilityIcons/NS.png'
import OG from '../img/abilityIcons/OG.png'
import QR from '../img/abilityIcons/QR.png'
import QSJ from '../img/abilityIcons/QSJ.png'
import REC from '../img/abilityIcons/REC.png'
import RES from '../img/abilityIcons/RES.png'
import RP from '../img/abilityIcons/RP.png'
import RSU from '../img/abilityIcons/RSU.png'
import SCU from '../img/abilityIcons/SCU.png'
import SJ from '../img/abilityIcons/SJ.png'
import SPU from '../img/abilityIcons/SPU.png'
import SS from '../img/abilityIcons/SS.png'
import SSU from '../img/abilityIcons/SSU.png'
import T from '../img/abilityIcons/T.png'
import TI from '../img/abilityIcons/TI.png'
import OS from '../img/abilityIcons/OS.png'
import EMPTY from '../img/abilityIcons/EMPTY.png'
import BDU from '../../img/abilityIcons/BDU.png'
import BRU from '../../img/abilityIcons/BRU.png'
import CB from '../../img/abilityIcons/CB.png'
import DR from '../../img/abilityIcons/DR.png'
import H from '../../img/abilityIcons/H.png'
import ISM from '../../img/abilityIcons/ISM.png'
import ISS from '../../img/abilityIcons/ISS.png'
import LDE from '../../img/abilityIcons/LDE.png'
import MPU from '../../img/abilityIcons/MPU.png'
import NS from '../../img/abilityIcons/NS.png'
import OG from '../../img/abilityIcons/OG.png'
import QR from '../../img/abilityIcons/QR.png'
import QSJ from '../../img/abilityIcons/QSJ.png'
import REC from '../../img/abilityIcons/REC.png'
import RES from '../../img/abilityIcons/RES.png'
import RP from '../../img/abilityIcons/RP.png'
import RSU from '../../img/abilityIcons/RSU.png'
import SCU from '../../img/abilityIcons/SCU.png'
import SJ from '../../img/abilityIcons/SJ.png'
import SPU from '../../img/abilityIcons/SPU.png'
import SS from '../../img/abilityIcons/SS.png'
import SSU from '../../img/abilityIcons/SSU.png'
import T from '../../img/abilityIcons/T.png'
import TI from '../../img/abilityIcons/TI.png'
import OS from '../../img/abilityIcons/OS.png'
import EMPTY from '../../img/abilityIcons/EMPTY.png'
const Build = ({ build, existingAbilities, setAbilities, removeBuildFunction, editBuildFunction }) => {
const [showEdit, setShowEdit] = useState(false)

View File

@@ -1,163 +0,0 @@
import React from 'react'
import { useQuery } from '@apollo/react-hooks'
import { Table, Loader, Image, Pagination, Header, Popup, Icon } from 'semantic-ui-react'
import { Link, Redirect } from 'react-router-dom'
import { searchForBuildsByWeapon } from '../../graphql/queries/searchForBuildsByWeapon'
import weaponDict from '../../utils/english_internal.json'
import top500 from '../img/misc/top500.png'
import BDU from '../img/abilityIcons/BDU.png'
import BRU from '../img/abilityIcons/BRU.png'
import CB from '../img/abilityIcons/CB.png'
import DR from '../img/abilityIcons/DR.png'
import H from '../img/abilityIcons/H.png'
import ISM from '../img/abilityIcons/ISM.png'
import ISS from '../img/abilityIcons/ISS.png'
import LDE from '../img/abilityIcons/LDE.png'
import MPU from '../img/abilityIcons/MPU.png'
import NS from '../img/abilityIcons/NS.png'
import OG from '../img/abilityIcons/OG.png'
import QR from '../img/abilityIcons/QR.png'
import QSJ from '../img/abilityIcons/QSJ.png'
import REC from '../img/abilityIcons/REC.png'
import RES from '../img/abilityIcons/RES.png'
import RP from '../img/abilityIcons/RP.png'
import RSU from '../img/abilityIcons/RSU.png'
import SCU from '../img/abilityIcons/SCU.png'
import SJ from '../img/abilityIcons/SJ.png'
import SPU from '../img/abilityIcons/SPU.png'
import SS from '../img/abilityIcons/SS.png'
import SSU from '../img/abilityIcons/SSU.png'
import T from '../img/abilityIcons/T.png'
import TI from '../img/abilityIcons/TI.png'
import OS from '../img/abilityIcons/OS.png'
const abilities = {
"BDU": {image: BDU, fullName: "Bomb Defense Up DX"},
"BRU": {image: BRU, fullName: "Sub Power Up"},
"CB": {image: CB, fullName: "Comeback", mainOnly: true},
"DR": {image: DR, fullName: "Drop Roller", mainOnly: true},
"H": {image: H, fullName: "Haunt", mainOnly: true},
"ISM": {image: ISM, fullName: "Ink Saver (Main)"},
"ISS": {image: ISS, fullName: "Ink Saver (Sub)"},
"LDE": {image: LDE, fullName: "Last-Ditch Effort", mainOnly: true},
"MPU": {image: MPU, fullName: "Main Power Up"},
"NS": {image: NS, fullName: "Ninja Squid", mainOnly: true},
"OG": {image: OG, fullName: "Opening Gambit", mainOnly: true},
"QR": {image: QR, fullName: "Quick Respawn"},
"QSJ": {image: QSJ, fullName: "Quick Super Jump"},
"REC": {image: REC, fullName: "Ink Recovery Up"},
"RES": {image: RES, fullName: "Ink Resistance Up"},
"RP": {image: RP, fullName: "Respawn Punisher", mainOnly: true},
"RSU": {image: RSU, fullName: "Run Speed Up"},
"SCU": {image: SCU, fullName: "Special Charge Up"},
"SJ": {image: SJ, fullName: "Stealth Jump", mainOnly: true},
"SPU": {image: SPU, fullName: "Special Power Up"},
"SS": {image: SS, fullName: "Special Saver"},
"SSU": {image: SSU, fullName: "Swim Speed Up"},
"T": {image: T, fullName: "Tenacity", mainOnly: true},
"TI": {image: TI, fullName: "Thermal Ink", mainOnly: true},
"OS": {image: OS, fullName: "Object Shredder", mainOnly: true}
}
const BuildCollection = ({ weapon, page, setPage }) => {
const { data, error, loading } = useQuery(searchForBuildsByWeapon, { variables: { weapon, page }})
if (loading) {
return <div style={{"paddingTop": "25px", "paddingBottom": "20000px"}} ><Loader active inline='centered' /></div>
}
if (error) {
return <div style={{"color": "red"}}>{error.message}</div>
}
const builds = data.searchForBuildsByWeapon.builds
if (!builds) return <Redirect to='/404' />
if (builds.length === 0) return <div style={{'paddingTop': '10px'}}>No builds with this weapon yet. You can be the first to submit one!</div>
return (
<div>
<div style={{'paddingTop': '10px'}}>
<Header size='large'>
<img
src={`https://raw.githubusercontent.com/Leanny/leanny.github.io/master/splat2/weapons/Wst_${weaponDict[weapon]}.png`}
alt={weapon}
/> {weapon} Builds
</Header>
<Header size='tiny'></Header>
</div>
<div>
<Table celled padded>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Discord Tag</Table.HeaderCell>
<Table.HeaderCell textAlign='center'>
<Popup
trigger={<Icon name='question circle'/>}
content='If the player who posted the build has placed Top 500 in X Rank with the weapon in question Top 500 crown is displayed in this column.'
position='top center'
/>
</Table.HeaderCell>
<Table.HeaderCell>Headgear</Table.HeaderCell>
<Table.HeaderCell>Clothing</Table.HeaderCell>
<Table.HeaderCell>Shoes</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{builds.map(b => {
return (
<Table.Row key={b.id}>
<Table.Cell>
<Link to={`/u/${b.discord_id}`}>{`${b.discord_user.username}#${b.discord_user.discriminator}`}</Link>
</Table.Cell>
<Table.Cell collapsing>
{b.top ? <Image src={top500} style={{ "maxWidth": "40px", "height": "auto" }} /> : null}
</Table.Cell>
<Table.Cell singleLine>
<Image src={abilities[b.headgear[0]].image} inline />
<Image src={abilities[b.headgear[1]].image} style={{ "maxWidth": "40px", "height": "auto" }} inline />
<Image src={abilities[b.headgear[2]].image} style={{ "maxWidth": "40px", "height": "auto" }} inline />
<Image src={abilities[b.headgear[3]].image} style={{ "maxWidth": "40px", "height": "auto" }} inline />
</Table.Cell>
<Table.Cell singleLine>
<Image src={abilities[b.clothing[0]].image} inline />
<Image src={abilities[b.clothing[1]].image} style={{ "maxWidth": "40px", "height": "auto" }} inline />
<Image src={abilities[b.clothing[2]].image} style={{ "maxWidth": "40px", "height": "auto" }} inline />
<Image src={abilities[b.clothing[3]].image} style={{ "maxWidth": "40px", "height": "auto" }} inline />
</Table.Cell>
<Table.Cell singleLine>
<Image src={abilities[b.shoes[0]].image} inline />
<Image src={abilities[b.shoes[1]].image} style={{ "maxWidth": "40px", "height": "auto" }} inline />
<Image src={abilities[b.shoes[2]].image} style={{ "maxWidth": "40px", "height": "auto" }} inline />
<Image src={abilities[b.shoes[3]].image} style={{ "maxWidth": "40px", "height": "auto" }} inline />
</Table.Cell>
</Table.Row>
)
})}
</Table.Body>
</Table>
<div>
{data.searchForBuildsByWeapon.pageCount > 1 ?
<Pagination
activePage={page}
boundaryRange={0}
onPageChange={(e, { activePage }) => {
window.scrollTo(0, 0)
setPage(activePage)}}
ellipsisItem={null}
firstItem={null}
lastItem={null}
siblingRange={1}
totalPages={data.searchForBuildsByWeapon.pageCount}
/> : null}
</div>
</div>
</div>
)
}
export default BuildCollection

View File

@@ -4,6 +4,7 @@ import WeaponForm from '../XSearch/WeaponForm'
import Build from './Build'
import AbilityButtons from './AbilityButtons'
// TODO: Bug with editing build.
const BuildForm = ({ addBuild, setShowForm, setSuccessMsg, existingBuild, setShowEdit, editBuildFunction }) => {
const [weaponForm, setWeaponForm] = useState(existingBuild ? existingBuild.weapon : '')
const [title, setTitle] = useState(existingBuild ? existingBuild.title : '')

View File

@@ -1,26 +0,0 @@
import React, { useState, useEffect } from 'react'
import WeaponForm from '../XSearch/WeaponForm'
import BuildCollection from './BuildCollection'
const BuildSearch = ({ setMenuSelection, weaponFromUrl }) => {
const [weapon, setWeapon] = useState(weaponFromUrl)
const [page, setPage] = useState(1)
useEffect(() => {
setMenuSelection('builds')
document.title = "Builds - sendou.ink"
}, [setMenuSelection])
return (
<div>
<div>
<WeaponForm weaponForm={weapon} setWeaponForm={setWeapon} push setPage={setPage} />
</div>
<div>
{!weapon ? null : <BuildCollection weapon={weapon} page={page} setPage={setPage} />}
</div>
</div>
)
}
export default BuildSearch

View File

@@ -0,0 +1,53 @@
import React, { useState, useEffect } from "react"
import { useQuery } from "@apollo/react-hooks"
import { Spin, List, Pagination, Empty } from "antd"
import { useSelector } from 'react-redux'
import { searchForBuildsByWeapon } from "../../graphql/queries/searchForBuildsByWeapon"
import BuildCard from "../elements/BuildCard"
import useWindowDimensions from "../hooks/useWindowDimensions";
const BuildsList = ({ weapon }) => {
const { containerWidth } = useWindowDimensions()
const localization = useSelector(state => state.localization)
const [page, setPage] = useState(1)
const { data, error, loading } = useQuery(searchForBuildsByWeapon, {
variables: { weapon, page }
})
useEffect(() => {
setPage(1)
if (weapon) document.title = `${localization[weapon]} ${localization["Builds"]} - sendou.ink`
}, [weapon, localization])
if (error) return <div style={{ color: "red" }}>{error.message}</div>
if (loading) return <Spin />
const builds = data.searchForBuildsByWeapon.builds
if (builds.length === 0) return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={localization["No builds for this weapon yet. You can submit the first one!"]} />
let column = 1
if (containerWidth > 933) column = 4
else if (containerWidth > 723) column = 3
else if (containerWidth > 500) column = 2
const pageCount = data.searchForBuildsByWeapon.pageCount
return (
<>
<List
grid={{ gutter: 16, column }}
dataSource={builds}
renderItem={item => (
<List.Item>
<BuildCard build={item} />
</List.Item>
)}
/>
<div>
{pageCount > 1 && <Pagination current={page} onChange={(page) => setPage(page)} total={pageCount * 10} />}
</div>
</>
)
}
export default BuildsList

View File

@@ -1,286 +0,0 @@
import React, { useState, useEffect, useRef } from 'react'
import { SketchField, Tools } from 'react-sketch'
import { CirclePicker } from 'react-color'
import { Dropdown, Button, Icon, Input, Grid, Label, Message } from 'semantic-ui-react'
import WeaponForm from '../XSearch/WeaponForm'
import weaponDict from '../../utils/english_internal.json'
import academy from '../img/plannerMaps/academy-sz.png'
import arena from '../img/plannerMaps/arena-sz.png'
import camp from '../img/plannerMaps/camp-sz.png'
import canal from '../img/plannerMaps/canal-sz.png'
import dome from '../img/plannerMaps/dome-sz.png'
import fitness from '../img/plannerMaps/fitness-sz.png'
import games from '../img/plannerMaps/games-sz.png'
import hotel from '../img/plannerMaps/hotel-sz.png'
import institute from '../img/plannerMaps/institute-sz.png'
import mainstage from '../img/plannerMaps/mainstage-sz.png'
import mall from '../img/plannerMaps/mall-sz.png'
import manta from '../img/plannerMaps/manta-sz.png'
import mart from '../img/plannerMaps/mart-sz.png'
import pavilion from '../img/plannerMaps/pavilion-sz.png'
import pit from '../img/plannerMaps/pit-sz.png'
import pitrm from '../img/plannerMaps/pit-rm.png'
import port from '../img/plannerMaps/port-sz.png'
import pumptrack from '../img/plannerMaps/pumptrack-sz.png'
import reef from '../img/plannerMaps/reef-sz.png'
import shipyard from '../img/plannerMaps/shipyard-sz.png'
import skatepark from '../img/plannerMaps/skatepark-sz.png'
import towers from '../img/plannerMaps/towers-sz.png'
import warehouse from '../img/plannerMaps/warehouse-sz.png'
import world from '../img/plannerMaps/world-sz.png'
const MapPlanner = ({ setMenuSelection }) => {
let sketch = null
const isMobile = window.innerWidth <= 1000
const defaultValue = {
shadowWidth: 0,
shadowOffset: 0,
enableRemoveSelected: false,
fillWithColor: false,
fillWithBackgroundColor: false,
drawings: [],
canUndo: false,
canRedo: false,
controlledSize: false,
sketchWidth: 600,
sketchHeight: 600,
stretched: true,
stretchedX: false,
stretchedY: false,
originX: 'left',
originY: 'top',
expandTools: false,
expandControls: false,
expandColors: false,
expandBack: false,
expandImages: false,
expandControlled: false,
enableCopyPaste: false,
}
const fileInput = useRef(null)
const [tool, setTool] = useState(Tools.Pencil)
const [color, setColor] = useState('#f44336')
const [weapon, setWeapon] = useState('')
const [canUndo, setCanUndo] = useState(false)
const [canRedo, setCanRedo] = useState(false)
const [text, setText] = useState('')
const [bg, setBg] = useState(null)
const [uploadError, setUploadError] = useState(null)
const [controlledValue, setControlledValue] = useState(defaultValue)
useEffect(() => {
if (!sketch) return
setMenuSelection('plans')
document.title = 'Planner - sendou.ink'
}, [sketch, setMenuSelection, bg])
const tools = [
{ key: 1, text: 'Pencil', value: Tools.Pencil, icon: 'pencil' },
{ key: 2, text: 'Line', value: Tools.Line, icon: 'window minimize outline' },
{ key: 3, text: 'Rectangle', value: Tools.Rectangle, icon: 'square outline' },
{ key: 4, text: 'Circle', value: Tools.Circle, icon: 'circle outline' },
{ key: 5, text: 'Select', value: Tools.Select, icon: 'object group outline' }
]
const maps = [
{ key: 'The Reef', text: 'The Reef', value: reef },
{ key: 'Musselforge Fitness', text: 'Musselforge Fitness', value: fitness },
{ key: 'Starfish Mainstage', text: 'Starfish Mainstage', value: mainstage },
{ key: 'Humpback Pumptrack', text: 'Humpback Pumptrack', value: pumptrack },
{ key: 'Inkblot Art Academy', text: 'Inkblot Art Academy', value: academy },
{ key: 'Sturgeon Shipyard', text: 'Sturgeon Shipyard', value: shipyard },
{ key: 'Moray Towers', text: 'Moray Towers', value: towers },
{ key: 'Port Mackerel', text: 'Port Mackerel', value: port },
{ key: 'Manta Maria', text: 'Manta Maria', value: manta },
{ key: 'Kelp Dome', text: 'Kelp Dome', value: dome },
{ key: 'Snapper Canal', text: 'Snapper Canal', value: canal },
{ key: 'Blackbelly Skatepark', text: 'Blackbelly Skatepark', value: skatepark },
{ key: 'MakoMart', text: 'MakoMart', value: mart },
{ key: 'Walleye Warehouse', text: 'Walleye Warehouse', value: warehouse },
{ key: 'Shellendorf Institute', text: 'Shellendorf Institute', value: institute },
{ key: 'Arowana Mall', text: 'Arowana Mall', value: mall },
{ key: 'Goby Arena', text: 'Goby Arena', value: arena },
{ key: 'Piranha Pit', text: 'Piranha Pit', value: pit },
{ key: 'Piranha Pit (RM)', text: 'Piranha Pit (RM)', value: pitrm },
{ key: 'Camp Triggerfish', text: 'Camp Triggerfish', value: camp },
{ key: 'Wahoo World', text: 'Wahoo World', value: world },
{ key: 'New Albacore Hotel', text: 'New Albacore Hotel', value: hotel },
{ key: 'Ancho-V Games', text: 'Ancho-V Games', value: games },
{ key: 'Skipper Pavilion', text: 'Skipper Pavilion', value: pavilion },
]
const addImageToSketch = () => {
sketch.addImg(process.env.PUBLIC_URL + `/wpnMedium/Wst_${weaponDict[weapon]}.png`)
setTool(Tools.Select)
}
const addTextToSketch = () => {
sketch.addText(text,
{
fill: color,
fontFamily: "lato",
stroke: '#000000',
strokeWidth: 3,
paintFirst: "stroke" })
setTool(Tools.Select)
}
const undo = () => {
sketch.undo()
setCanUndo(sketch.canUndo())
setCanRedo(sketch.canRedo())
}
const redo = () => {
sketch.redo()
setCanUndo(sketch.canUndo())
setCanRedo(sketch.canRedo())
}
const removeSelected = () => {
sketch.removeSelected()
}
const onSketchChange = () => {
let prev = canUndo
let now = sketch.canUndo()
if (prev !== now) {
setCanUndo(now)
}
}
const getDateFormatted = () => {
const today = new Date()
const date = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate()
const time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds()
return date+' '+time
}
const download = (dataUrl, extension) => {
let a = document.createElement("a")
document.body.appendChild(a)
a.style = "display: none"
a.href = dataUrl
a.download = `${bg.replace('/static/media/', '').split('-')[0]} plans ${getDateFormatted()}.${extension}`
a.click()
window.URL.revokeObjectURL(dataUrl)
}
const handleUpload = () => {
if (fileInput.current.files.length === 0) {
setUploadError('Upload file')
setTimeout(() => setUploadError(null), 5000)
return
}
const fileObj = fileInput.current.files[0]
const reader = new FileReader()
reader.onload = function(event) {
const jsonObj = JSON.parse(event.target.result)
setControlledValue(jsonObj)
}
reader.readAsText(fileObj)
}
const onBgChange = (value) => {
sketch.clear()
setBg(value)
setCanUndo(false)
sketch.setBackgroundFromDataUrl(value)
}
return (
<div>
<h1>Make your plans!</h1>
{isMobile && <Message negative>Unfortunately this tool isn't designed for narrow screens but you can still give it a go.</Message>}
<div>
<SketchField
name="sketch"
className="canvas-area"
ref={c => (sketch = c)}
lineColor={color}
lineWidth={5}
width={1280}
height={720}
/*width={
this.state.controlledSize ? this.state.sketchWidth : null
}
height={
this.state.controlledSize ? this.state.sketchHeight : null
}*/
/*defaultValue={dataJson}*/
value={controlledValue}
/*forceValue*/
onChange={onSketchChange}
tool={tool}
/>
</div>
<div style={{"paddingTop": "10px"}}>
<Button primary icon disabled={!canUndo} onClick={() => undo()}><Icon name='undo' /> Undo</Button>
<Button primary icon disabled={!canRedo} onClick={() => redo()}><Icon name='redo' /> Redo</Button>
<Button primary icon disabled={tool !== Tools.Select} onClick={() => removeSelected()}><Icon name='trash' /> Delete selected</Button>
<Button secondary icon onClick={() => download(sketch.toDataURL(), 'png')}><Icon name='download' /> Download as .png</Button>
<Button secondary icon onClick={() => download("data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(sketch.toJSON())), 'json')}><Icon name='cloud download' /> Download as .json</Button>
<Button secondary icon onClick={() => handleUpload()}><Icon name='cloud upload' /> Load from .json</Button>
<input type="file" accept=".json" ref={fileInput}/>
{uploadError && <span style={{'color': 'red'}}>{uploadError}</span>}
</div>
<div style={{"paddingTop": "10px"}}>
<Grid columns={3}>
<Grid.Column>
<CirclePicker
color={color}
onChangeComplete={(newColor) => setColor(newColor.hex)}
/>
</Grid.Column>
<Grid.Column>
<h3>Tools</h3>
<Dropdown
onChange={(e, { value }) => setTool(value)}
options={tools}
selection
value={tool}
/>
</Grid.Column>
<Grid.Column>
<h3>Add text</h3>
<Input
value={text}
onChange={e => setText(e.target.value)}
/>
<div style={{ "paddingTop": "7px"}}>
<Button
icon='plus'
circular
onClick={() => addTextToSketch()}
/>
</div>
</Grid.Column>
</Grid>
</div>
<h3>Choose the map</h3>
<Dropdown
onChange={(e, { value }) => onBgChange(value)}
options={maps}
selection
value={bg}
/>
<Label basic color='red' pointing='left'>
Please note that changing the map also clears all the drawings
</Label>
<h3>Choose a weapon to add</h3>
<WeaponForm weaponForm={weapon} setWeaponForm={setWeapon} />
<div style={{'paddingTop': '7px'}}>
<Button
icon='plus'
circular
onClick={() => addImageToSketch()}
/>
</div>
</div>
)
}
export default MapPlanner

View File

@@ -0,0 +1,39 @@
import React, { useState, useEffect } from 'react'
import { PageHeader } from 'antd'
import { Segment } from 'semantic-ui-react'
import { withRouter } from "react-router-dom"
import { useSelector } from 'react-redux'
import Select from '../elements/Select'
import BuildsList from '../Tools/BuildsList'
const PageBuilds = withRouter(({ history, weaponFromUrl, setMenuSelection }) => {
const [weapon, setWeapon] = useState(weaponFromUrl ? weaponFromUrl : null)
const localization = useSelector(state => state.localization)
const handleFormChange = (value) => {
setWeapon(value)
history.push(`/builds/${value.replace(/ /g, "_")}`)
}
useEffect(() => {
if (!weapon) document.title = `${localization["Builds"]} - sendou.ink`
setMenuSelection("builds")
}, [localization, weapon, setMenuSelection])
return (
<Segment>
<div>
<PageHeader title={localization["Build Search"]} subTitle={localization["Learn how others spend those valuable Ability Points"]} />
</div>
<div style={{margin: "0 1.5em"}}>
<Select content="MAINWEAPONS" value={weapon} onChange={handleFormChange} />
</div>
<div style={{margin: "2em 1.5em 1.5em"}}>
{weaponFromUrl && <BuildsList weapon={weaponFromUrl} />}
</div>
</Segment>
)
})
export default PageBuilds

View File

@@ -14,14 +14,15 @@ import {
Label,
Segment
} from "semantic-ui-react"
import { useSelector } from "react-redux"
import { useQuery } from "@apollo/react-hooks"
import { maplists } from "../../graphql/queries/maplists"
import szIcon from "../img/modeIcons/sz.png"
import tcIcon from "../img/modeIcons/tc.png"
import rmIcon from "../img/modeIcons/rm.png"
import cbIcon from "../img/modeIcons/cb.png"
import szIcon from "../../img/modeIcons/sz.png"
import tcIcon from "../../img/modeIcons/tc.png"
import rmIcon from "../../img/modeIcons/rm.png"
import cbIcon from "../../img/modeIcons/cb.png"
const MapListGenerator = ({ setMenuSelection }) => {
const PageMapListGenerator = ({ setMenuSelection }) => {
const { data, error, loading } = useQuery(maplists)
const [maps, setMaps] = useState([])
const [boxValue, setBoxValue] = useState(0)
@@ -30,6 +31,7 @@ const MapListGenerator = ({ setMenuSelection }) => {
const [generatedMaps, setGeneratedMaps] = useState([])
const [generationType, setGenerationType] = useState("rotate")
const [copySuccess, setCopySuccess] = useState("")
const localization = useSelector(state => state.localization)
const textAreaRef = useRef(null)
useEffect(() => {
@@ -88,10 +90,12 @@ const MapListGenerator = ({ setMenuSelection }) => {
}
let mapsWithModes = [
...szMaps.map(m => `Splat Zones on ${m}`),
...tcMaps.map(m => `Tower Control on ${m}`),
...rmMaps.map(m => `Rainmaker on ${m}`),
...cbMaps.map(m => `Clam Blitz on ${m}`)
...szMaps.map(m => `${localization["Splat Zones"]} - ${localization[m]}`),
...tcMaps.map(
m => `${localization["Tower Control"]} - ${localization[m]}`
),
...rmMaps.map(m => `${localization["Rainmaker"]} - ${localization[m]}`),
...cbMaps.map(m => `${localization["Clam Blitz"]} - ${localization[m]}`)
]
const toSetAsState = []
let usedMaps = []
@@ -121,13 +125,23 @@ const MapListGenerator = ({ setMenuSelection }) => {
return
}
let szMapMode = [...szMaps.map(m => `Splat Zones on ${m}`)]
let szMapMode = [
...szMaps.map(m => `${localization["Splat Zones"]} - ${localization[m]}`)
]
let usedSz = []
let tcMapMode = [...tcMaps.map(m => `Tower Control on ${m}`)]
let tcMapMode = [
...tcMaps.map(
m => `${localization["Tower Control"]} - ${localization[m]}`
)
]
let usedTc = []
let rmMapMode = [...rmMaps.map(m => `Rainmaker on ${m}`)]
let rmMapMode = [
...rmMaps.map(m => `${localization["Rainmaker"]} - ${localization[m]}`)
]
let usedRm = []
let cbMapMode = [...cbMaps.map(m => `Clam Blitz on ${m}`)]
let cbMapMode = [
...cbMaps.map(m => `${localization["Clam Blitz"]} - ${localization[m]}`)
]
let usedCb = []
const toSetAsState = []
@@ -210,12 +224,12 @@ const MapListGenerator = ({ setMenuSelection }) => {
}
return (
<Segment>
<div style={{"padding": "5px"}}>
<Segment>
<div style={{ margin: "1em" }}>
<Divider horizontal>
<Header as="h4">
<Icon name="map" />
Choose the map pool to use
{localization["Choose the map pool to use"]}
</Header>
</Divider>
<Form>
@@ -237,7 +251,7 @@ const MapListGenerator = ({ setMenuSelection }) => {
<Divider horizontal>
<Header as="h4">
<Icon name="checkmark box" />
Choose the maps to include
{localization["Choose the maps to include"]}
</Header>
</Divider>
<Grid relaxed="very" columns={4} stackable>
@@ -249,7 +263,7 @@ const MapListGenerator = ({ setMenuSelection }) => {
return (
<List.Item key={m}>
<Checkbox
label={m}
label={localization[m]}
checked={mapValues[boxValue].sz[i]}
onChange={() => {
const copy = [...mapValues]
@@ -270,7 +284,7 @@ const MapListGenerator = ({ setMenuSelection }) => {
return (
<List.Item key={m}>
<Checkbox
label={m}
label={localization[m]}
checked={mapValues[boxValue].tc[i]}
onChange={() => {
const copy = [...mapValues]
@@ -291,7 +305,7 @@ const MapListGenerator = ({ setMenuSelection }) => {
return (
<List.Item key={m}>
<Checkbox
label={m}
label={localization[m]}
checked={mapValues[boxValue].rm[i]}
onChange={() => {
const copy = [...mapValues]
@@ -312,7 +326,7 @@ const MapListGenerator = ({ setMenuSelection }) => {
return (
<List.Item key={m}>
<Checkbox
label={m}
label={localization[m]}
checked={mapValues[boxValue].cb[i]}
onChange={() => {
const copy = [...mapValues]
@@ -331,20 +345,24 @@ const MapListGenerator = ({ setMenuSelection }) => {
<Divider horizontal>
<Header as="h4">
<Icon name="clipboard list" />
Set the final preferences & generate!
{localization["Set the final preferences & generate!"]}
</Header>
</Divider>
<Input
type="number"
placeholder="Choose amount"
label="Choose the amount of maps to generate"
placeholder={localization["Choose amount"]}
label={localization["Choose the amount of maps to generate"]}
value={amountToGenerate}
onChange={e => setAmountToGenerate(e.target.value)}
error={amountToGenerate < 1 || amountToGenerate > 100}
/>
{amountToGenerate < 1 || amountToGenerate > 100 ? (
<Label basic color="red" pointing="left">
Amount of maps to generate has to be between 1 and 100
{
localization[
"Amount of maps to generate has to be between 1 and 100"
]
}
</Label>
) : null}
</div>
@@ -352,7 +370,7 @@ const MapListGenerator = ({ setMenuSelection }) => {
<Form.Field>
<Checkbox
radio
label="Rotate mode SZ->TC->CB->RM"
label={localization["Rotate mode SZ->TC->CB->RM"]}
name="rotateMode"
checked={generationType === "rotate"}
onChange={() => setGenerationType("rotate")}
@@ -360,7 +378,7 @@ const MapListGenerator = ({ setMenuSelection }) => {
<br />
<Checkbox
radio
label="SZ every other map"
label={localization["SZ every other map"]}
name="szEveryOther"
checked={generationType === "everyOther"}
onChange={() => setGenerationType("everyOther")}
@@ -368,7 +386,7 @@ const MapListGenerator = ({ setMenuSelection }) => {
<br />
<Checkbox
radio
label="Total randomness"
label={localization["Total randomness"]}
name="random"
checked={generationType === "random"}
onChange={() => setGenerationType("random")}
@@ -384,7 +402,7 @@ const MapListGenerator = ({ setMenuSelection }) => {
: generateEvenMapPool(generationType === "everyOther")
}}
>
Go!
{localization["Go!"]}
</Button>
</div>
<div style={{ paddingTop: "5px" }}>
@@ -409,9 +427,9 @@ const MapListGenerator = ({ setMenuSelection }) => {
</div>
) : null}
</div>
</div>
</Segment>
</div>
</Segment>
)
}
export default MapListGenerator
export default PageMapListGenerator

View File

@@ -0,0 +1,414 @@
import React, { useState, useEffect, useRef } from "react"
import { SketchField, Tools } from "react-sketch"
import { CirclePicker } from "react-color"
import {
Dropdown,
Button,
Icon,
Input,
Grid,
Label,
Message,
Segment
} from "semantic-ui-react"
import { useSelector } from "react-redux"
import weaponDict from "../../utils/english_internal.json"
import useWindowDimensions from "../hooks/useWindowDimensions"
import Select from "../elements/Select"
import academy from "../../img/plannerMaps/academy-sz.png"
import arena from "../../img/plannerMaps/arena-sz.png"
import camp from "../../img/plannerMaps/camp-sz.png"
import canal from "../../img/plannerMaps/canal-sz.png"
import dome from "../../img/plannerMaps/dome-sz.png"
import fitness from "../../img/plannerMaps/fitness-sz.png"
import games from "../../img/plannerMaps/games-sz.png"
import hotel from "../../img/plannerMaps/hotel-sz.png"
import institute from "../../img/plannerMaps/institute-sz.png"
import mainstage from "../../img/plannerMaps/mainstage-sz.png"
import mall from "../../img/plannerMaps/mall-sz.png"
import manta from "../../img/plannerMaps/manta-sz.png"
import mart from "../../img/plannerMaps/mart-sz.png"
import pavilion from "../../img/plannerMaps/pavilion-sz.png"
import pit from "../../img/plannerMaps/pit-sz.png"
import pitrm from "../../img/plannerMaps/pit-rm.png"
import port from "../../img/plannerMaps/port-sz.png"
import pumptrack from "../../img/plannerMaps/pumptrack-sz.png"
import reef from "../../img/plannerMaps/reef-sz.png"
import shipyard from "../../img/plannerMaps/shipyard-sz.png"
import skatepark from "../../img/plannerMaps/skatepark-sz.png"
import towers from "../../img/plannerMaps/towers-sz.png"
import warehouse from "../../img/plannerMaps/warehouse-sz.png"
import world from "../../img/plannerMaps/world-sz.png"
// TODO: When going to another page and coming back the map flickers.
const PageMapPlanner = ({ setMenuSelection }) => {
let sketch = null
const { containerWidth } = useWindowDimensions()
const defaultValue = {
shadowWidth: 0,
shadowOffset: 0,
enableRemoveSelected: false,
fillWithColor: false,
fillWithBackgroundColor: false,
drawings: [],
canUndo: false,
canRedo: false,
controlledSize: false,
sketchWidth: 600,
sketchHeight: 600,
stretched: true,
stretchedX: false,
stretchedY: false,
originX: "left",
originY: "top",
expandTools: false,
expandControls: false,
expandColors: false,
expandBack: false,
expandImages: false,
expandControlled: false,
enableCopyPaste: false
}
const fileInput = useRef(null)
const [tool, setTool] = useState(Tools.Pencil)
const [color, setColor] = useState("#f44336")
const [weapon, setWeapon] = useState("")
const [canUndo, setCanUndo] = useState(false)
const [canRedo, setCanRedo] = useState(false)
const [text, setText] = useState("")
const [bg, setBg] = useState(null)
const [uploadError, setUploadError] = useState(null)
const [controlledValue, setControlledValue] = useState(defaultValue)
const localization = useSelector(state => state.localization)
useEffect(() => {
setMenuSelection("plans")
document.title = "Planner - sendou.ink"
}, [setMenuSelection])
useEffect(() => {
if (!sketch) return
sketch.clear()
setBg(reef)
setCanUndo(false)
sketch.setBackgroundFromDataUrl(reef)
}, [sketch])
const tools = [
{
key: 1,
text: localization["Pencil"],
value: Tools.Pencil,
icon: "pencil"
},
{
key: 2,
text: localization["Line"],
value: Tools.Line,
icon: "window minimize outline"
},
{
key: 3,
text: localization["Rectangle"],
value: Tools.Rectangle,
icon: "square outline"
},
{
key: 4,
text: localization["Circle"],
value: Tools.Circle,
icon: "circle outline"
},
{
key: 5,
text: localization["Select"],
value: Tools.Select,
icon: "object group outline"
}
]
const maps = [
{ key: "The Reef", text: localization["The Reef"], value: reef },
{
key: "Musselforge Fitness",
text: localization["Musselforge Fitness"],
value: fitness
},
{
key: "Starfish Mainstage",
text: localization["Starfish Mainstage"],
value: mainstage
},
{
key: "Humpback Pump Track",
text: localization["Humpback Pump Track"],
value: pumptrack
},
{
key: "Inkblot Art Academy",
text: localization["Inkblot Art Academy"],
value: academy
},
{
key: "Sturgeon Shipyard",
text: localization["Sturgeon Shipyard"],
value: shipyard
},
{ key: "Moray Towers", text: localization["Moray Towers"], value: towers },
{ key: "Port Mackerel", text: localization["Port Mackerel"], value: port },
{ key: "Manta Maria", text: localization["Manta Maria"], value: manta },
{ key: "Kelp Dome", text: localization["Kelp Dome"], value: dome },
{ key: "Snapper Canal", text: localization["Snapper Canal"], value: canal },
{
key: "Blackbelly Skatepark",
text: localization["Blackbelly Skatepark"],
value: skatepark
},
{ key: "MakoMart", text: localization["MakoMart"], value: mart },
{
key: "Walleye Warehouse",
text: localization["Walleye Warehouse"],
value: warehouse
},
{
key: "Shellendorf Institute",
text: localization["Shellendorf Institute"],
value: institute
},
{ key: "Arowana Mall", text: localization["Arowana Mall"], value: mall },
{ key: "Goby Arena", text: localization["Goby Arena"], value: arena },
{ key: "Piranha Pit", text: localization["Piranha Pit"], value: pit },
{
key: "Piranha Pit (RM)",
text: localization["Piranha Pit (RM)"],
value: pitrm
},
{
key: "Camp Triggerfish",
text: localization["Camp Triggerfish"],
value: camp
},
{ key: "Wahoo World", text: localization["Wahoo World"], value: world },
{
key: "New Albacore Hotel",
text: localization["New Albacore Hotel"],
value: hotel
},
{ key: "Ancho-V Games", text: localization["Ancho-V Games"], value: games },
{
key: "Skipper Pavilion",
text: localization["Skipper Pavilion"],
value: pavilion
}
]
const addImageToSketch = () => {
sketch.addImg(
process.env.PUBLIC_URL + `/wpnMedium/Wst_${weaponDict[weapon]}.png`
)
setTool(Tools.Select)
}
const addTextToSketch = () => {
sketch.addText(text, {
fill: color,
fontFamily: "lato",
stroke: "#000000",
strokeWidth: 3,
paintFirst: "stroke"
})
setTool(Tools.Select)
}
const undo = () => {
sketch.undo()
setCanUndo(sketch.canUndo())
setCanRedo(sketch.canRedo())
}
const redo = () => {
sketch.redo()
setCanUndo(sketch.canUndo())
setCanRedo(sketch.canRedo())
}
const removeSelected = () => {
sketch.removeSelected()
}
const onSketchChange = () => {
let prev = canUndo
let now = sketch.canUndo()
if (prev !== now) {
setCanUndo(now)
}
}
const getDateFormatted = () => {
const today = new Date()
const date =
today.getFullYear() + "-" + (today.getMonth() + 1) + "-" + today.getDate()
const time =
today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds()
return date + " " + time
}
const download = (dataUrl, extension) => {
let a = document.createElement("a")
document.body.appendChild(a)
a.style = "display: none"
a.href = dataUrl
a.download = `${
bg.replace("/static/media/", "").split("-")[0]
} plans ${getDateFormatted()}.${extension}`
a.click()
window.URL.revokeObjectURL(dataUrl)
}
const handleUpload = () => {
if (fileInput.current.files.length === 0) {
setUploadError("Upload file")
setTimeout(() => setUploadError(null), 5000)
return
}
const fileObj = fileInput.current.files[0]
const reader = new FileReader()
reader.onload = function(event) {
const jsonObj = JSON.parse(event.target.result)
setControlledValue(jsonObj)
}
reader.readAsText(fileObj)
}
const onBgChange = value => {
sketch.clear()
setBg(value)
setCanUndo(false)
sketch.setBackgroundFromDataUrl(value)
}
return (
<div>
{containerWidth < 1127 && (
<Message negative>
Unfortunately this tool isn't designed for narrow screens but you can
still give it a go.
</Message>
)}
<SketchField
name="sketch"
className="canvas-area"
ref={c => (sketch = c)}
lineColor={color}
lineWidth={5}
width={1127}
height={634}
/*width={
this.state.controlledSize ? this.state.sketchWidth : null
}
height={
this.state.controlledSize ? this.state.sketchHeight : null
}*/
/*defaultValue={dataJson}*/
value={controlledValue}
/*forceValue*/
onChange={onSketchChange}
tool={tool}
/>
<Segment>
<Button primary icon disabled={!canUndo} onClick={() => undo()}>
<Icon name="undo" /> {localization["Undo"]}
</Button>
<Button primary icon disabled={!canRedo} onClick={() => redo()}>
<Icon name="redo" /> {localization["Redo"]}
</Button>
<Button
primary
icon
disabled={tool !== Tools.Select}
onClick={() => removeSelected()}
>
<Icon name="trash" /> {localization["Delete selected"]}
</Button>
<Button
secondary
icon
onClick={() => download(sketch.toDataURL(), "png")}
>
<Icon name="download" /> {localization["Download as .png"]}
</Button>
<Button
secondary
icon
onClick={() =>
download(
"data:text/json;charset=utf-8," +
encodeURIComponent(JSON.stringify(sketch.toJSON())),
"json"
)
}
>
<Icon name="cloud download" /> {localization["Download as .json"]}
</Button>
<Button secondary icon onClick={() => handleUpload()}>
<Icon name="cloud upload" /> {localization["Load from .json"]}
</Button>
<input type="file" accept=".json" ref={fileInput} />
{uploadError && <span style={{ color: "red" }}>{uploadError}</span>}
<div style={{ paddingTop: "10px" }}>
<Grid columns={3}>
<Grid.Column>
<CirclePicker
color={color}
onChangeComplete={newColor => setColor(newColor.hex)}
/>
</Grid.Column>
<Grid.Column>
<h3>{localization["Tools"]}</h3>
<Dropdown
onChange={(e, { value }) => setTool(value)}
options={tools}
selection
value={tool}
/>
</Grid.Column>
<Grid.Column>
<h3>{localization["Add text"]}</h3>
<Input value={text} onChange={e => setText(e.target.value)} />
<div style={{ paddingTop: "7px" }}>
<Button
icon="plus"
circular
onClick={() => addTextToSketch()}
/>
</div>
</Grid.Column>
</Grid>
</div>
<h3>{localization["Choose the map"]}</h3>
<Dropdown
onChange={(e, { value }) => onBgChange(value)}
options={maps}
selection
value={bg}
/>
<Label basic color="red" pointing="left">
{
localization[
"Please note that changing the map also clears all the drawings"
]
}
</Label>
<h3>{localization["Choose a weapon to add"]}</h3>
<Select content="MAINWEAPONS" value={weapon} onChange={setWeapon} />
<div style={{ paddingTop: "7px" }}>
<Button icon="plus" circular onClick={() => addImageToSketch()} />
</div>
</Segment>
</div>
)
}
export default PageMapPlanner

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from "react"
import { useQuery } from "@apollo/react-hooks"
import { useSelector } from "react-redux"
import { rotationData } from "../../graphql/queries/rotationData"
import { maplists } from "../../graphql/queries/maplists"
import {
@@ -13,36 +14,36 @@ import {
Checkbox
} from "semantic-ui-react"
import arowana_mall from "../img/mapIcons/arowana_mall.png"
import anchov_games from "../img/mapIcons/ancho-v_games.png"
import blackbelly_skatepark from "../img/mapIcons/blackbelly_skatepark.png"
import camp_triggerfish from "../img/mapIcons/camp_triggerfish.png"
import goby_arena from "../img/mapIcons/goby_arena.png"
import humpback_pump_track from "../img/mapIcons/humpback_pump_track.png"
import inkblot_art_academy from "../img/mapIcons/inkblot_art_academy.png"
import kelp_dome from "../img/mapIcons/kelp_dome.png"
import makomart from "../img/mapIcons/makomart.png"
import manta_maria from "../img/mapIcons/manta_maria.png"
import moray_towers from "../img/mapIcons/moray_towers.png"
import musselforge_fitness from "../img/mapIcons/musselforge_fitness.png"
import new_albacore_hotel from "../img/mapIcons/new_albacore_hotel.png"
import piranha_pit from "../img/mapIcons/piranha_pit.png"
import port_mackerel from "../img/mapIcons/port_mackerel.png"
import shellendorf_institute from "../img/mapIcons/shellendorf_institute.png"
import skipper_pavilion from "../img/mapIcons/skipper_pavilion.png"
import snapper_canal from "../img/mapIcons/snapper_canal.png"
import starfish_mainstage from "../img/mapIcons/starfish_mainstage.png"
import sturgeon_shipyard from "../img/mapIcons/sturgeon_shipyard.png"
import the_reef from "../img/mapIcons/the_reef.png"
import wahoo_world from "../img/mapIcons/wahoo_world.png"
import walleye_warehouse from "../img/mapIcons/walleye_warehouse.png"
import rankedIcon from "../img/modeIcons/ranked.png"
import regularIcon from "../img/modeIcons/regular.png"
import leagueIcon from "../img/modeIcons/league.png"
import szIcon from "../img/modeIcons/sz.png"
import tcIcon from "../img/modeIcons/tc.png"
import rmIcon from "../img/modeIcons/rm.png"
import cbIcon from "../img/modeIcons/cb.png"
import arowana_mall from "../../img/mapIcons/arowana_mall.png"
import anchov_games from "../../img/mapIcons/ancho-v_games.png"
import blackbelly_skatepark from "../../img/mapIcons/blackbelly_skatepark.png"
import camp_triggerfish from "../../img/mapIcons/camp_triggerfish.png"
import goby_arena from "../../img/mapIcons/goby_arena.png"
import humpback_pump_track from "../../img/mapIcons/humpback_pump_track.png"
import inkblot_art_academy from "../../img/mapIcons/inkblot_art_academy.png"
import kelp_dome from "../../img/mapIcons/kelp_dome.png"
import makomart from "../../img/mapIcons/makomart.png"
import manta_maria from "../../img/mapIcons/manta_maria.png"
import moray_towers from "../../img/mapIcons/moray_towers.png"
import musselforge_fitness from "../../img/mapIcons/musselforge_fitness.png"
import new_albacore_hotel from "../../img/mapIcons/new_albacore_hotel.png"
import piranha_pit from "../../img/mapIcons/piranha_pit.png"
import port_mackerel from "../../img/mapIcons/port_mackerel.png"
import shellendorf_institute from "../../img/mapIcons/shellendorf_institute.png"
import skipper_pavilion from "../../img/mapIcons/skipper_pavilion.png"
import snapper_canal from "../../img/mapIcons/snapper_canal.png"
import starfish_mainstage from "../../img/mapIcons/starfish_mainstage.png"
import sturgeon_shipyard from "../../img/mapIcons/sturgeon_shipyard.png"
import the_reef from "../../img/mapIcons/the_reef.png"
import wahoo_world from "../../img/mapIcons/wahoo_world.png"
import walleye_warehouse from "../../img/mapIcons/walleye_warehouse.png"
import rankedIcon from "../../img/modeIcons/ranked.png"
import regularIcon from "../../img/modeIcons/regular.png"
import leagueIcon from "../../img/modeIcons/league.png"
import szIcon from "../../img/modeIcons/sz.png"
import tcIcon from "../../img/modeIcons/tc.png"
import rmIcon from "../../img/modeIcons/rm.png"
import cbIcon from "../../img/modeIcons/cb.png"
const mapIcons = {
"Arowana Mall": arowana_mall,
@@ -53,7 +54,7 @@ const mapIcons = {
"Humpback Pump Track": humpback_pump_track,
"Inkblot Art Academy": inkblot_art_academy,
"Kelp Dome": kelp_dome,
"MakoMart": makomart,
MakoMart: makomart,
"Manta Maria": manta_maria,
"Moray Towers": moray_towers,
"Musselforge Fitness": musselforge_fitness,
@@ -84,7 +85,8 @@ const modeShort = {
"Clam Blitz": "cb"
}
const Rotations = ({ setMenuSelection }) => {
// TODO: Salmon Run rotations
const PageRotations = ({ setMenuSelection }) => {
const { data, error, loading } = useQuery(rotationData)
const monthly = useQuery(maplists)
const [rotation, setRotation] = useState([])
@@ -94,10 +96,12 @@ const Rotations = ({ setMenuSelection }) => {
rm: {},
cb: {}
})
const [show, setShow] = useState(false)
const [currentTime, setCurrentTime] = useState(
new Date(Math.floor(Date.now() / 1000))
)
const localization = useSelector(state => state.localization)
useEffect(() => {
if (loading || monthly.loading) {
@@ -152,16 +156,20 @@ const Rotations = ({ setMenuSelection }) => {
<Button icon="cog" onClick={() => setShow(!show)} />
{show ? (
<Segment>
<div style={{"padding": "5px"}}>
Uncheck a map in the ranked rotation to mark it as a disliked map.
<div style={{ padding: "5px" }}>
{
localization[
"Uncheck a map in the ranked rotation to mark it as a disliked map."
]
}
<Grid relaxed columns={4}>
<Grid.Column>
<b>Splat Zones</b>
<b>{localization["Splat Zones"]}</b>
{monthlyMaps.sz.map(m => {
return (
<div key={m}>
<Checkbox
label={m}
label={localization[m]}
checked={!preferences.sz[m]}
onChange={() => {
preferences.sz[m] = !preferences.sz[m]
@@ -177,12 +185,12 @@ const Rotations = ({ setMenuSelection }) => {
})}
</Grid.Column>
<Grid.Column>
<b>Tower Control</b>
<b>{localization["Tower Control"]}</b>
{monthlyMaps.tc.map(m => {
return (
<div key={m}>
<Checkbox
label={m}
label={localization[m]}
checked={!preferences.tc[m]}
onChange={() => {
preferences.tc[m] = !preferences.tc[m]
@@ -198,12 +206,12 @@ const Rotations = ({ setMenuSelection }) => {
})}
</Grid.Column>
<Grid.Column>
<b>Rainmaker</b>
<b>{localization["Rainmaker"]}</b>
{monthlyMaps.rm.map(m => {
return (
<div key={m}>
<Checkbox
label={m}
label={localization[m]}
checked={!preferences.rm[m]}
onChange={() => {
preferences.rm[m] = !preferences.rm[m]
@@ -219,12 +227,12 @@ const Rotations = ({ setMenuSelection }) => {
})}
</Grid.Column>
<Grid.Column>
<b>Clam Blitz</b>
<b>{localization["Clam Blitz"]}</b>
{monthlyMaps.cb.map(m => {
return (
<div key={m}>
<Checkbox
label={m}
label={localization[m]}
checked={!preferences.cb[m]}
onChange={() => {
preferences.cb[m] = !preferences.cb[m]
@@ -253,35 +261,22 @@ const Rotations = ({ setMenuSelection }) => {
const timeUntil = r.start_time - currentTime
const hours = Math.floor(timeUntil / 3600)
const minutes = Math.floor((timeUntil % 3600) / 60)
const seconds = (timeUntil % 3600) % 60
let header = "Current"
if (hours >= 2) {
if (minutes === 1) {
header = `In ${hours} hours ${minutes} minute (${new Date(
r.start_time * 1000
).toLocaleString("en-GB")})`
} else {
header = `In ${hours} hours ${minutes} minutes (${new Date(
r.start_time * 1000
).toLocaleString("en-GB")})`
}
} else if (hours > 0) {
if (minutes === 1) {
header = `In ${hours} hour ${minutes} minute ${seconds} seconds`
} else {
header = `In ${hours} hour ${minutes} minutes ${seconds} seconds`
}
} else if (minutes > 0) {
if (minutes === 1) {
header = `In ${hours} hour ${minutes} minute ${seconds} seconds`
} else {
header = `In ${minutes} minutes ${seconds} seconds`
}
let header = localization["Current"]
if (r.start_time > currentTime) {
header = localization.formatString(
localization["Rotation header"],
{
hours,
minutes,
date: new Date(r.start_time * 1000).toLocaleString("en-GB")
}
)
}
return (
<div key={r.start_time} style={{ paddingTop: "25px" }}>
<Header
size="small"
style={{color: "white", textShadow: "1px 1px black"}}
disabled={
preferences[modeShort[r.rule.name]][r.stage_a.name] &&
preferences[modeShort[r.rule.name]][r.stage_b.name]
@@ -311,7 +306,7 @@ const Rotations = ({ setMenuSelection }) => {
src={modeIcons[rotation.league[i].rule.name]}
avatar
/>
<b>{rotation.league[i].rule.name}</b>
<b>{localization[rotation.league[i].rule.name]}</b>
</Header.Subheader>
</Header>
</Grid.Column>
@@ -328,7 +323,7 @@ const Rotations = ({ setMenuSelection }) => {
src={modeIcons[r.rule.name]}
avatar
/>
<b>{r.rule.name}</b>
<b>{localization[r.rule.name]}</b>
</Header.Subheader>
</Header>
</Grid.Column>
@@ -360,7 +355,9 @@ const Rotations = ({ setMenuSelection }) => {
rounded
/>
}
content={rotation.league[i].stage_a.name}
content={
localization[rotation.league[i].stage_a.name]
}
basic
/>
<Popup
@@ -370,7 +367,9 @@ const Rotations = ({ setMenuSelection }) => {
rounded
/>
}
content={rotation.league[i].stage_b.name}
content={
localization[rotation.league[i].stage_b.name]
}
basic
/>
</div>
@@ -395,7 +394,7 @@ const Rotations = ({ setMenuSelection }) => {
}
/>
}
content={r.stage_a.name}
content={localization[r.stage_a.name]}
basic
/>
<Popup
@@ -410,7 +409,7 @@ const Rotations = ({ setMenuSelection }) => {
}
/>
}
content={r.stage_b.name}
content={localization[r.stage_b.name]}
basic
/>
</div>
@@ -430,7 +429,9 @@ const Rotations = ({ setMenuSelection }) => {
rounded
/>
}
content={rotation.regular[i].stage_a.name}
content={
localization[rotation.regular[i].stage_a.name]
}
basic
/>
<Popup
@@ -440,7 +441,9 @@ const Rotations = ({ setMenuSelection }) => {
rounded
/>
}
content={rotation.regular[i].stage_b.name}
content={
localization[rotation.regular[i].stage_b.name]
}
basic
/>
</div>
@@ -456,4 +459,4 @@ const Rotations = ({ setMenuSelection }) => {
)
}
export default Rotations
export default PageRotations

View File

@@ -1,6 +1,7 @@
import React from 'react'
import { Table, Icon, Popup, Segment } from 'semantic-ui-react'
import { useQuery } from '@apollo/react-hooks'
import { useSelector } from "react-redux"
import { Loader } from 'semantic-ui-react'
import { Link } from 'react-router-dom'
@@ -8,6 +9,7 @@ import { topFlex } from '../../graphql/queries/topFlex'
const FlexLeaderboard = ({ setActiveItem }) => {
const result = useQuery(topFlex)
const localization = useSelector(state => state.localization)
setActiveItem('topFlex')
if (result.loading) {
@@ -26,9 +28,9 @@ const FlexLeaderboard = ({ setActiveItem }) => {
<Table.Header>
<Table.Row>
<Table.HeaderCell></Table.HeaderCell>
<Table.HeaderCell>Name</Table.HeaderCell>
<Table.HeaderCell>{localization['Name']}</Table.HeaderCell>
<Table.HeaderCell>
Flex Power
{localization['Power']}
<Popup
trigger={<Icon name='question circle'/>}
content="Flex Power is the amount of unique weapons the player has reached top 500 with. Different kits count as unique weapons but reskins (e.g. Tentatek & Octoshot) don't."

View File

@@ -1,60 +1,37 @@
import React from 'react'
import { Popup } from 'semantic-ui-react'
import weaponDict from '../../utils/english_internal.json'
import { modes, months, getNumberWithOrdinal } from '../../utils/lists'
import React from "react"
import { Popup } from "semantic-ui-react"
import { useSelector } from "react-redux"
import weaponDict from "../../utils/english_internal.json"
import { modes, months } from "../../utils/lists"
const FourWeapons = ({ weapons }) => {
const localization = useSelector(state => state.localization)
return (
<>
<Popup
trigger={
<img
style={{"height": "60px", "width": "60px"}}
src={`https://raw.githubusercontent.com/Leanny/leanny.github.io/master/splat2/weapons/Wst_${weaponDict[weapons[0]["weapon"]]}.png`}
alt={weapons[0].name}
/>
}
header={weapons[0].name}
content={`${weapons[0].x_power} (${getNumberWithOrdinal(weapons[0].rank)} ${modes[weapons[0].mode]} - ${months[weapons[0].month]} ${weapons[0].year})`}
/>
<Popup
trigger={
<img
style={{"height": "60px", "width": "60px"}}
src={`https://raw.githubusercontent.com/Leanny/leanny.github.io/master/splat2/weapons/Wst_${weaponDict[weapons[1]["weapon"]]}.png`}
alt={weapons[1].name}
/>
}
header={weapons[1].name}
content={`${weapons[1].x_power} (${getNumberWithOrdinal(weapons[1].rank)} ${modes[weapons[1].mode]} - ${months[weapons[1].month]} ${weapons[1].year})`}
/>
<Popup
trigger={
<img
style={{"height": "60px", "width": "60px"}}
src={`https://raw.githubusercontent.com/Leanny/leanny.github.io/master/splat2/weapons/Wst_${weaponDict[weapons[2]["weapon"]]}.png`}
alt={weapons[2].name}
/>
}
header={weapons[2].name}
content={`${weapons[2].x_power} (${getNumberWithOrdinal(weapons[2].rank)} ${modes[weapons[2].mode]} - ${months[weapons[2].month]} ${weapons[2].year})`}
/>
<Popup
trigger={
<img
style={{"height": "60px", "width": "60px"}}
src={`https://raw.githubusercontent.com/Leanny/leanny.github.io/master/splat2/weapons/Wst_${weaponDict[weapons[3]["weapon"]]}.png`}
alt={weapons[3].name}
/>
}
header={weapons[3].name}
content={`${weapons[3].x_power} (${getNumberWithOrdinal(weapons[3].rank)} ${modes[weapons[3].mode]} - ${months[weapons[3].month]} ${weapons[3].year})`}
/>
</>
<>
{weapons.map(w => {
const mode = modes[w.mode]
const month = months[w.month]
return (
<Popup
key={`${mode}${month}${w.year}`}
trigger={
<img
style={{ height: "60px", width: "60px" }}
src={`https://raw.githubusercontent.com/Leanny/leanny.github.io/master/splat2/weapons/Wst_${
weaponDict[w["weapon"]]
}.png`}
alt={w.name}
/>
}
header={w.name}
content={`${w.x_power} (${w.rank} ${
localization[mode]
} - ${localization[month]} ${w.year})`}
/>
)
})}
</>
)
}
export default FourWeapons
export default FourWeapons

View File

@@ -0,0 +1,367 @@
import React, { useState } from "react"
import { Menu, Responsive, Segment } from "semantic-ui-react"
import { Route, withRouter } from "react-router-dom"
import { useSelector } from "react-redux"
import WeaponLeaderboard from "./WeaponLeaderboard"
import { topTotalPlayers } from "../../graphql/queries/topPlayers"
import { topShooterPlayers } from "../../graphql/queries/topShooters"
import { topBlasterPlayers } from "../../graphql/queries/topBlasters"
import { topBrellaPlayers } from "../../graphql/queries/topBrellas"
import { topChargerPlayers } from "../../graphql/queries/topChargers"
import { topDualiesPlayers } from "../../graphql/queries/topDualies"
import { topRollerPlayers } from "../../graphql/queries/topRollers"
import { topSlosherPlayers } from "../../graphql/queries/topSloshers"
import { topSplatlingPlayers } from "../../graphql/queries/topSplatlings"
import allIcon from "../../img/wpnIcons/all.png"
import blasterIcon from "../../img/wpnIcons/blasters.png"
import brellaIcon from "../../img/wpnIcons/brellas.png"
import chargerIcon from "../../img/wpnIcons/chargers.png"
import dualieIcon from "../../img/wpnIcons/dualies.png"
import rollerIcon from "../../img/wpnIcons/rollers.png"
import shooterIcon from "../../img/wpnIcons/shooters.png"
import slosherIcon from "../../img/wpnIcons/sloshers.png"
import splatlingIcon from "../../img/wpnIcons/splatlings.png"
const PageXLeaderboard = withRouter(({ history, setMenuSelection }) => {
const [activeItem, setActiveItem] = useState("")
const localization = useSelector(state => state.localization)
const wpnIcon = {
paddingBottom: "5px"
}
setMenuSelection("leaderboards")
return (
<Segment>
<div className="ui centered grid">
<div className="center aligned column">
<Responsive minWidth={800}>
<Menu compact icon="labeled">
<Menu.Item
name="all"
active={activeItem === "topTotal"}
onClick={() => {
history.push("/xleaderboard")
}}
>
<img style={wpnIcon} src={allIcon} alt="All Icon" />
{localization['All']}
</Menu.Item>
<Menu.Item
name="shooters"
active={activeItem === "topShooter"}
onClick={() => {
history.push("/xleaderboard/shooters")
}}
>
<img style={wpnIcon} src={shooterIcon} alt="Shooter Icon" />
{localization['Shooters']}
</Menu.Item>
<Menu.Item
name="blasters"
active={activeItem === "topBlaster"}
onClick={() => {
history.push("/xleaderboard/blasters")
}}
>
<img style={wpnIcon} src={blasterIcon} alt="Blaster Icon" />
{localization['Blasters']}
</Menu.Item>
<Menu.Item
name="rollers"
active={activeItem === "topRoller"}
onClick={() => {
history.push("/xleaderboard/rollers")
}}
>
<img style={wpnIcon} src={rollerIcon} alt="Roller Icon" />
{localization['Rollers']}
</Menu.Item>
<Menu.Item
name="chargers"
active={activeItem === "topCharger"}
onClick={() => {
history.push("/xleaderboard/chargers")
}}
>
<img style={wpnIcon} src={chargerIcon} alt="Charger Icon" />
{localization['Chargers']}
</Menu.Item>
<Menu.Item
name="splatlings"
active={activeItem === "topSplatling"}
onClick={() => {
history.push("/xleaderboard/splatlings")
}}
>
<img style={wpnIcon} src={splatlingIcon} alt="Splatling Icon" />
{localization['Splatlings']}
</Menu.Item>
<Menu.Item
name="sloshers"
active={activeItem === "topSlosher"}
onClick={() => {
history.push("/xleaderboard/sloshers")
}}
>
<img style={wpnIcon} src={slosherIcon} alt="Slosher Icon" />
{localization['Sloshers']}
</Menu.Item>
<Menu.Item
name="dualies"
active={activeItem === "topDualies"}
onClick={() => {
history.push("/xleaderboard/dualies")
}}
>
<img style={wpnIcon} src={dualieIcon} alt="Dualie Icon" />
{localization['Dualies']}
</Menu.Item>
<Menu.Item
name="brella"
active={activeItem === "topBrella"}
onClick={() => {
history.push("/xleaderboard/brellas")
}}
>
<img style={wpnIcon} src={brellaIcon} alt="Brella Icon" />
{localization['Brellas']}
</Menu.Item>
</Menu>
</Responsive>
<Responsive maxWidth={799}>
<Menu compact icon="labeled">
<Menu.Item
name="all"
active={activeItem === "topTotal"}
onClick={() => {
history.push("/xleaderboard")
}}
>
<img style={wpnIcon} src={allIcon} alt="All Icon" />
{localization['All']}
</Menu.Item>
</Menu>
<Menu compact icon="labeled">
<Menu.Item
name="shooters"
active={activeItem === "topShooter"}
onClick={() => {
history.push("/xleaderboard/shooters")
}}
>
<img style={wpnIcon} src={shooterIcon} alt="Shooter Icon" />
{localization['Shooters']}
</Menu.Item>
<Menu.Item
name="blasters"
active={activeItem === "topBlaster"}
onClick={() => {
history.push("/xleaderboard/blasters")
}}
>
<img style={wpnIcon} src={blasterIcon} alt="Blaster Icon" />
{localization['Blasters']}
</Menu.Item>
<Menu.Item
name="rollers"
active={activeItem === "topRoller"}
onClick={() => {
history.push("/xleaderboard/rollers")
}}
>
<img style={wpnIcon} src={rollerIcon} alt="Roller Icon" />
{localization['Rollers']}
</Menu.Item>
<Menu.Item
name="chargers"
active={activeItem === "topCharger"}
onClick={() => {
history.push("/xleaderboard/chargers")
}}
>
<img style={wpnIcon} src={chargerIcon} alt="Charger Icon" />
{localization['Chargers']}
</Menu.Item>
</Menu>
<Menu compact icon="labeled">
<Menu.Item
name="splatlings"
active={activeItem === "topSplatling"}
onClick={() => {
history.push("/xleaderboard/splatlings")
}}
>
<img style={wpnIcon} src={splatlingIcon} alt="Splatling Icon" />
{localization['Splatlings']}
</Menu.Item>
<Menu.Item
name="sloshers"
active={activeItem === "topSlosher"}
onClick={() => {
history.push("/xleaderboard/sloshers")
}}
>
<img style={wpnIcon} src={slosherIcon} alt="Slosher Icon" />
{localization['Sloshers']}
</Menu.Item>
<Menu.Item
name="dualies"
active={activeItem === "topDualies"}
onClick={() => {
history.push("/xleaderboard/dualies")
}}
>
<img style={wpnIcon} src={dualieIcon} alt="Dualie Icon" />
{localization['Dualies']}
</Menu.Item>
<Menu.Item
name="brella"
active={activeItem === "topBrella"}
onClick={() => {
history.push("/xleaderboard/brellas")
}}
>
<img style={wpnIcon} src={brellaIcon} alt="Brella Icon" />
{localization['Brellas']}
</Menu.Item>
</Menu>
</Responsive>
</div>
</div>
<Route
exact
path="/xleaderboard"
render={() => (
<WeaponLeaderboard
query={topTotalPlayers}
queryName="topTotalPlayers"
scoreField="topTotalScore"
weaponsField="topTotal"
setActiveItem={setActiveItem}
/>
)}
/>
<Route
exact
path="/xleaderboard/shooters"
render={() => (
<WeaponLeaderboard
query={topShooterPlayers}
queryName="topShooterPlayers"
scoreField="topShooterScore"
weaponsField="topShooter"
setActiveItem={setActiveItem}
/>
)}
/>
<Route
exact
path="/xleaderboard/blasters"
render={() => (
<WeaponLeaderboard
query={topBlasterPlayers}
queryName="topBlasterPlayers"
scoreField="topBlasterScore"
weaponsField="topBlaster"
setActiveItem={setActiveItem}
/>
)}
/>
<Route
exact
path="/xleaderboard/rollers"
render={() => (
<WeaponLeaderboard
query={topRollerPlayers}
queryName="topRollerPlayers"
scoreField="topRollerScore"
weaponsField="topRoller"
setActiveItem={setActiveItem}
/>
)}
/>
<Route
exact
path="/xleaderboard/chargers"
render={() => (
<WeaponLeaderboard
query={topChargerPlayers}
queryName="topChargerPlayers"
scoreField="topChargerScore"
weaponsField="topCharger"
setActiveItem={setActiveItem}
/>
)}
/>
<Route
exact
path="/xleaderboard/splatlings"
render={() => (
<WeaponLeaderboard
query={topSplatlingPlayers}
queryName="topSplatlingPlayers"
scoreField="topSplatlingScore"
weaponsField="topSplatling"
setActiveItem={setActiveItem}
/>
)}
/>
<Route
exact
path="/xleaderboard/sloshers"
render={() => (
<WeaponLeaderboard
query={topSlosherPlayers}
queryName="topSlosherPlayers"
scoreField="topSlosherScore"
weaponsField="topSlosher"
setActiveItem={setActiveItem}
/>
)}
/>
<Route
exact
path="/xleaderboard/dualies"
render={() => (
<WeaponLeaderboard
query={topDualiesPlayers}
queryName="topDualiesPlayers"
scoreField="topDualiesScore"
weaponsField="topDualies"
setActiveItem={setActiveItem}
/>
)}
/>
<Route
exact
path="/xleaderboard/brellas"
render={() => (
<WeaponLeaderboard
query={topBrellaPlayers}
queryName="topBrellaPlayers"
scoreField="topBrellaScore"
weaponsField="topBrella"
setActiveItem={setActiveItem}
/>
)}
/>
</Segment>
)
})
export default PageXLeaderboard

View File

@@ -1,65 +1,82 @@
import React from 'react'
import { Table, Icon, Popup, Segment } from 'semantic-ui-react'
import { useQuery } from '@apollo/react-hooks'
import { Loader } from 'semantic-ui-react'
import { Link } from 'react-router-dom'
import React from "react"
import { Table, Icon, Popup, Segment } from "semantic-ui-react"
import { useQuery } from "@apollo/react-hooks"
import { useSelector } from "react-redux"
import { Loader } from "semantic-ui-react"
import { Link } from "react-router-dom"
import FourWeapons from './FourWeapons'
import FourWeapons from "./FourWeapons"
const WeaponLeaderboard = ({ query, queryName, scoreField, weaponsField, setActiveItem }) => {
const WeaponLeaderboard = ({
query,
queryName,
scoreField,
weaponsField,
setActiveItem
}) => {
const result = useQuery(query)
const localization = useSelector(state => state.localization)
setActiveItem(weaponsField)
if (result.loading) {
return <div style={{"paddingTop": "25px", "paddingBottom": "20000px"}} ><Loader active inline='centered' /></div>
return (
<div style={{ paddingTop: "25px", paddingBottom: "20000px" }}>
<Loader active inline="centered" />
</div>
)
}
if (result.error) {
return <div style={{"color": "red"}}>{result.error.message}</div>
return <div style={{ color: "red" }}>{result.error.message}</div>
}
document.title = `${weaponsField.substring(3)} Leaderboard - sendou.ink`
const leaderboard = result.data[queryName]
return (
<Segment>
<div style={{"padding": "5px"}}>
<Table basic='very'>
<Table.Header>
<Table.Row>
<Table.HeaderCell></Table.HeaderCell>
<Table.HeaderCell>Name</Table.HeaderCell>
<Table.HeaderCell>
{weaponsField.substring(3)} Power
<Popup
trigger={<Icon name='question circle'/>}
content='Power is the average of the top 4 best X powers. Hover over the weapon to receive information about that placement.'
position='bottom center'
/>
</Table.HeaderCell>
<Table.HeaderCell>Weapons</Table.HeaderCell>
<div style={{ margin: "1.5em" }}>
<Table basic="very">
<Table.Header>
<Table.Row>
<Table.HeaderCell />
<Table.HeaderCell>{localization["Name"]}</Table.HeaderCell>
<Table.HeaderCell>
{localization["Power"]}
<Popup
trigger={<Icon name="question circle" />}
content={localization["Leaderboard explanation"]}
position="bottom center"
/>
</Table.HeaderCell>
<Table.HeaderCell>{localization["Weapons"]}</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{leaderboard.map((player, index) => (
<Table.Row key={player.id}>
<Table.Cell>{index + 1}</Table.Cell>
<Table.Cell>
<Link
to={`/xsearch/p/${player.unique_id}`}
style={{ color: "black" }}
>
<u>{player.alias ? player.alias : player.name}</u>
</Link>
{player.twitter ? (
<a href={`https://twitter.com/${player.twitter}`}>
<Icon style={{ paddingLeft: "5px" }} name="twitter" />
</a>
) : null}
</Table.Cell>
<Table.Cell>{player[scoreField]}</Table.Cell>
<Table.Cell>
<FourWeapons weapons={player[weaponsField]} />
</Table.Cell>
</Table.Row>
</Table.Header>
<Table.Body>
{leaderboard.map((player, index) =>
<Table.Row key={player.id}>
<Table.Cell>{index + 1}</Table.Cell>
<Table.Cell><Link to={`/xsearch/p/${player.unique_id}`} style={{"color": "black"}}><u>{player.alias ? player.alias : player.name}</u></Link>
{player.twitter ?
<a href={`https://twitter.com/${player.twitter}`}><Icon style={{"paddingLeft": "5px"}} name="twitter"/></a>
: null}
</Table.Cell>
<Table.Cell>{player[scoreField]}</Table.Cell>
<Table.Cell>
<FourWeapons weapons={player[weaponsField]} />
</Table.Cell>
</Table.Row>
)}
</Table.Body>
</Table>
</div>
</Segment>
))}
</Table.Body>
</Table>
</div>
)
}
export default WeaponLeaderboard
export default WeaponLeaderboard

View File

@@ -1,304 +0,0 @@
import React, { useState } from 'react'
import { Menu, Responsive } from 'semantic-ui-react'
import { Route, withRouter } from 'react-router-dom'
import WeaponLeaderboard from './WeaponLeaderboard'
import { topTotalPlayers } from '../../graphql/queries/topPlayers'
import { topShooterPlayers } from '../../graphql/queries/topShooters'
import { topBlasterPlayers } from '../../graphql/queries/topBlasters'
import { topBrellaPlayers } from '../../graphql/queries/topBrellas'
import { topChargerPlayers } from '../../graphql/queries/topChargers'
import { topDualiesPlayers } from '../../graphql/queries/topDualies'
import { topRollerPlayers } from '../../graphql/queries/topRollers'
import { topSlosherPlayers } from '../../graphql/queries/topSloshers'
import { topSplatlingPlayers } from '../../graphql/queries/topSplatlings'
import allIcon from '../img/wpnIcons/all.png'
import blasterIcon from '../img/wpnIcons/blasters.png'
import brellaIcon from '../img/wpnIcons/brellas.png'
import chargerIcon from '../img/wpnIcons/chargers.png'
import dualieIcon from '../img/wpnIcons/dualies.png'
import rollerIcon from '../img/wpnIcons/rollers.png'
import shooterIcon from '../img/wpnIcons/shooters.png'
import slosherIcon from '../img/wpnIcons/sloshers.png'
import splatlingIcon from '../img/wpnIcons/splatlings.png'
const WeaponLeaderboardSelector = withRouter(({ history, setMenuSelection }) => {
const [activeItem, setActiveItem] = useState('')
const wpnIcon = {
paddingBottom: "5px"
}
setMenuSelection('leaderboards')
return (
<div>
<div className="ui centered grid">
<div className="center aligned column">
<Responsive minWidth={800}>
<Menu compact icon='labeled'>
<Menu.Item
name='all'
active={activeItem === 'topTotal'}
onClick={() => { history.push('/xleaderboard')}}
>
<img style={wpnIcon} src={allIcon} alt="All Icon"/>
All
</Menu.Item>
<Menu.Item
name='shooters'
active={activeItem === 'topShooter'}
onClick={() => { history.push('/xleaderboard/shooters')}}
>
<img style={wpnIcon} src={shooterIcon} alt="Shooter Icon"/>
Shooters
</Menu.Item>
<Menu.Item
name='blasters'
active={activeItem === 'topBlaster'}
onClick={() => { history.push('/xleaderboard/blasters')}}
>
<img style={wpnIcon} src={blasterIcon} alt="Blaster Icon"/>
Blasters
</Menu.Item>
<Menu.Item
name='rollers'
active={activeItem === 'topRoller'}
onClick={() => { history.push('/xleaderboard/rollers')}}
>
<img style={wpnIcon} src={rollerIcon} alt="Roller Icon"/>
Rollers
</Menu.Item>
<Menu.Item
name='chargers'
active={activeItem === 'topCharger'}
onClick={() => { history.push('/xleaderboard/chargers')}}
>
<img style={wpnIcon} src={chargerIcon} alt="Charger Icon"/>
Chargers
</Menu.Item>
<Menu.Item
name='splatlings'
active={activeItem === 'topSplatling'}
onClick={() => { history.push('/xleaderboard/splatlings')}}
>
<img style={wpnIcon} src={splatlingIcon} alt="Splatling Icon"/>
Splatlings
</Menu.Item>
<Menu.Item
name='sloshers'
active={activeItem === 'topSlosher'}
onClick={() => { history.push('/xleaderboard/sloshers')}}
>
<img style={wpnIcon} src={slosherIcon} alt="Slosher Icon"/>
Sloshers
</Menu.Item>
<Menu.Item
name='dualies'
active={activeItem === 'topDualies'}
onClick={() => { history.push('/xleaderboard/dualies')}}
>
<img style={wpnIcon} src={dualieIcon} alt="Dualie Icon"/>
Dualies
</Menu.Item>
<Menu.Item
name='brella'
active={activeItem === 'topBrella'}
onClick={() => { history.push('/xleaderboard/brellas')}}
>
<img style={wpnIcon} src={brellaIcon} alt="Brella Icon"/>
Brellas
</Menu.Item>
</Menu>
</Responsive>
<Responsive maxWidth={799}>
<Menu compact icon='labeled'>
<Menu.Item
name='all'
active={activeItem === 'topTotal'}
onClick={() => { history.push('/xleaderboard')}}
>
<img style={wpnIcon} src={allIcon} alt="All Icon"/>
All
</Menu.Item>
</Menu>
<Menu compact icon='labeled'>
<Menu.Item
name='shooters'
active={activeItem === 'topShooter'}
onClick={() => { history.push('/xleaderboard/shooters')}}
>
<img style={wpnIcon} src={shooterIcon} alt="Shooter Icon"/>
Shooters
</Menu.Item>
<Menu.Item
name='blasters'
active={activeItem === 'topBlaster'}
onClick={() => { history.push('/xleaderboard/blasters')}}
>
<img style={wpnIcon} src={blasterIcon} alt="Blaster Icon"/>
Blasters
</Menu.Item>
<Menu.Item
name='rollers'
active={activeItem === 'topRoller'}
onClick={() => { history.push('/xleaderboard/rollers')}}
>
<img style={wpnIcon} src={rollerIcon} alt="Roller Icon"/>
Rollers
</Menu.Item>
<Menu.Item
name='chargers'
active={activeItem === 'topCharger'}
onClick={() => { history.push('/xleaderboard/chargers')}}
>
<img style={wpnIcon} src={chargerIcon} alt="Charger Icon"/>
Chargers
</Menu.Item>
</Menu>
<Menu compact icon='labeled'>
<Menu.Item
name='splatlings'
active={activeItem === 'topSplatling'}
onClick={() => { history.push('/xleaderboard/splatlings')}}
>
<img style={wpnIcon} src={splatlingIcon} alt="Splatling Icon"/>
Splatlings
</Menu.Item>
<Menu.Item
name='sloshers'
active={activeItem === 'topSlosher'}
onClick={() => { history.push('/xleaderboard/sloshers')}}
>
<img style={wpnIcon} src={slosherIcon} alt="Slosher Icon"/>
Sloshers
</Menu.Item>
<Menu.Item
name='dualies'
active={activeItem === 'topDualies'}
onClick={() => { history.push('/xleaderboard/dualies')}}
>
<img style={wpnIcon} src={dualieIcon} alt="Dualie Icon"/>
Dualies
</Menu.Item>
<Menu.Item
name='brella'
active={activeItem === 'topBrella'}
onClick={() => { history.push('/xleaderboard/brellas')}}
>
<img style={wpnIcon} src={brellaIcon} alt="Brella Icon"/>
Brellas
</Menu.Item>
</Menu>
</Responsive>
</div>
</div>
<Route exact path="/xleaderboard" render={() =>
<WeaponLeaderboard
query={topTotalPlayers}
queryName="topTotalPlayers"
scoreField="topTotalScore"
weaponsField="topTotal"
setActiveItem={setActiveItem}
/>
}
/>
<Route exact path="/xleaderboard/shooters" render={() =>
<WeaponLeaderboard
query={topShooterPlayers}
queryName="topShooterPlayers"
scoreField="topShooterScore"
weaponsField="topShooter"
setActiveItem={setActiveItem}
/>
}
/>
<Route exact path="/xleaderboard/blasters" render={() =>
<WeaponLeaderboard
query={topBlasterPlayers}
queryName="topBlasterPlayers"
scoreField="topBlasterScore"
weaponsField="topBlaster"
setActiveItem={setActiveItem}
/>
}
/>
<Route exact path="/xleaderboard/rollers" render={() =>
<WeaponLeaderboard
query={topRollerPlayers}
queryName="topRollerPlayers"
scoreField="topRollerScore"
weaponsField="topRoller"
setActiveItem={setActiveItem}
/>
}
/>
<Route exact path="/xleaderboard/chargers" render={() =>
<WeaponLeaderboard
query={topChargerPlayers}
queryName="topChargerPlayers"
scoreField="topChargerScore"
weaponsField="topCharger"
setActiveItem={setActiveItem}
/>
}
/>
<Route exact path="/xleaderboard/splatlings" render={() =>
<WeaponLeaderboard
query={topSplatlingPlayers}
queryName="topSplatlingPlayers"
scoreField="topSplatlingScore"
weaponsField="topSplatling"
setActiveItem={setActiveItem}
/>
}
/>
<Route exact path="/xleaderboard/sloshers" render={() =>
<WeaponLeaderboard
query={topSlosherPlayers}
queryName="topSlosherPlayers"
scoreField="topSlosherScore"
weaponsField="topSlosher"
setActiveItem={setActiveItem}
/>
}
/>
<Route exact path="/xleaderboard/dualies" render={() =>
<WeaponLeaderboard
query={topDualiesPlayers}
queryName="topDualiesPlayers"
scoreField="topDualiesScore"
weaponsField="topDualies"
setActiveItem={setActiveItem}
/>
}
/>
<Route exact path="/xleaderboard/brellas" render={() =>
<WeaponLeaderboard
query={topBrellaPlayers}
queryName="topBrellaPlayers"
scoreField="topBrellaScore"
weaponsField="topBrella"
setActiveItem={setActiveItem}
/>
}
/>
</div>
)
})
export default WeaponLeaderboardSelector

View File

@@ -0,0 +1,12 @@
import React from 'react'
import { Segment } from 'semantic-ui-react'
const PageXBrowser = () => {
return (
<Segment>
moro
</Segment>
)
}
export default PageXBrowser

View File

@@ -1,133 +0,0 @@
import React, { useState, useEffect } from 'react'
import { useQuery } from '@apollo/react-hooks'
import { topPlayersOfWeapon } from '../../graphql/queries/topPlayersOfWeapon'
import weaponDictReversed from '../../utils/internal_english.json'
import { Loader, Header, Table, Checkbox, Segment } from 'semantic-ui-react'
import { withRouter, Link } from 'react-router-dom'
import szIcon from '../img/modeIcons/sz.png'
import tcIcon from '../img/modeIcons/tc.png'
import rmIcon from '../img/modeIcons/rm.png'
import cbIcon from '../img/modeIcons/cb.png'
import { months, modes } from '../../utils/lists'
const modeIcons = ["", szIcon, tcIcon, rmIcon, cbIcon]
const InfoWeapon = withRouter(({ history, wpn }) => {
const { data, error, loading } = useQuery(topPlayersOfWeapon, {variables: {weapon: weaponDictReversed[wpn] }})
const [uniqueId, setUniqueId] = useState('')
const [allPlayers, setAllPlayers] = useState(true)
const [fullLeaderboard, setFullLeaderboard] = useState([])
const [filteredLeaderboard, setFilteredLeaderboard] = useState([])
const [modeCount, setModeCount] = useState([])
useEffect(() => {
document.title = `${weaponDictReversed[wpn]} Leaderboard - sendou.ink`
if (loading) {
return
}
if (data['topPlayers']) {
setFullLeaderboard(data['topPlayers']['placements'])
setFilteredLeaderboard(data['topPlayers']['placements'].reduce((acc, cur) => {
if(acc.uids.includes(cur.unique_id)) { //if player is already in the array
return acc
}
acc.uids.push(cur.unique_id) //add uid so that same player isn't counted twice
acc.array.push(cur) //add new player to the array
return acc
}, {array: [], uids: []}).array)
setModeCount(data['topPlayers']['modeCount'])
}
}, [data, loading, wpn])
if (!(wpn in weaponDictReversed)) {
history.push('/404')
}
if (loading) {
return <div style={{"paddingTop": "25px", "paddingBottom": "20000px"}} ><Loader active inline='centered' /></div>
}
if (error) {
return <div style={{"color": "red"}}>{error.message}</div>
}
let leaderboard = fullLeaderboard
if (!allPlayers) {
leaderboard = filteredLeaderboard
}
return (
<div>
<Segment compact>
<div style={{"padding": "5px"}}>
<Header size='large'>
<img
src={`https://raw.githubusercontent.com/Leanny/leanny.github.io/master/splat2/weapons/Wst_${wpn}.png`}
alt={weaponDictReversed[wpn]}
/> {weaponDictReversed[wpn]} Leaderboard
</Header>
<Header size='tiny'>
<b>Times in Top 500:</b>
<img src={modeIcons[1]} style={{"paddingLeft": "10px"}} alt="Splat Zones logo" /> {modeCount[1]}
<img src={modeIcons[2]} style={{"paddingLeft": "10px"}} alt="Tower Control logo" /> {modeCount[2]}
<img src={modeIcons[3]} style={{"paddingLeft": "10px"}} alt="Rainmaker logo" /> {modeCount[3]}
<img src={modeIcons[4]} style={{"paddingLeft": "10px"}} alt="Clam Blitz logo" /> {modeCount[4]}<br/>
Total {modeCount[0]}
</Header>
</div>
</Segment>
<div>
<Checkbox
radio
label='All'
name='checkboxRadioGroup'
checked={allPlayers}
onChange={() => setAllPlayers(!allPlayers)}
/>
<Checkbox
style={{"paddingLeft": "5px"}}
radio
label='Highest only'
name='checkboxRadioGroup'
checked={!allPlayers}
onChange={() => setAllPlayers(!allPlayers)}
/>
<Table selectable compact>
<Table.Header>
<Table.Row>
<Table.HeaderCell></Table.HeaderCell>
<Table.HeaderCell>Name</Table.HeaderCell>
<Table.HeaderCell>X Power</Table.HeaderCell>
<Table.HeaderCell>Month</Table.HeaderCell>
<Table.HeaderCell>Year</Table.HeaderCell>
<Table.HeaderCell>Rank</Table.HeaderCell>
<Table.HeaderCell>Mode</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{leaderboard.map((p, i) =>
<Table.Row key={p.id} active={p.unique_id === uniqueId} onClick={() => setUniqueId(p.unique_id)}>
<Table.Cell>{i + 1}</Table.Cell>
<Table.Cell><Link to={`/xsearch/p/${p.unique_id}`} style={{"color": "black"}}><u>{p.alias ? p.alias : p.name}</u></Link></Table.Cell>
<Table.Cell>{p.x_power}</Table.Cell>
<Table.Cell>{months[p.month]}</Table.Cell>
<Table.Cell>{p.year}</Table.Cell>
<Table.Cell>{p.rank}</Table.Cell>
<Table.Cell>
<img
style={{"height": "25px", "width": "25px"}}
src={modeIcons[p.mode]}
alt={`Mode icon for ${modes[p.mode]}`}
/>
</Table.Cell>
</Table.Row>
)}
</Table.Body>
</Table>
</div>
</div>
)
})
export default InfoWeapon

View File

@@ -1,10 +1,10 @@
import React from 'react'
import { Table, Header, Image } from 'semantic-ui-react'
import szIcon from '../img/modeIcons/sz.png'
import tcIcon from '../img/modeIcons/tc.png'
import rmIcon from '../img/modeIcons/rm.png'
import cbIcon from '../img/modeIcons/cb.png'
import szIcon from '../../img/modeIcons/sz.png'
import tcIcon from '../../img/modeIcons/tc.png'
import rmIcon from '../../img/modeIcons/rm.png'
import cbIcon from '../../img/modeIcons/cb.png'
import { months } from '../../utils/lists'
import weaponDict from '../../utils/english_internal.json'

View File

@@ -2,10 +2,10 @@ import React from 'react'
import { Header, Image, Table } from 'semantic-ui-react'
import weaponDict from '../../utils/english_internal.json'
import szIcon from '../img/modeIcons/sz.png'
import tcIcon from '../img/modeIcons/tc.png'
import rmIcon from '../img/modeIcons/rm.png'
import cbIcon from '../img/modeIcons/cb.png'
import szIcon from '../../img/modeIcons/sz.png'
import tcIcon from '../../img/modeIcons/tc.png'
import rmIcon from '../../img/modeIcons/rm.png'
import cbIcon from '../../img/modeIcons/cb.png'
import { months } from '../../utils/lists'
const TopPlacementTable = ({ top }) => {

View File

@@ -122,7 +122,6 @@ const XTrends = ({ setMenuSelection }) => {
return (
<div>
<Segment>
<div style={{ padding: "5px" }}>
<Header as="h2">
Compare weapons based on their X Rank Top 500 appearances
@@ -367,7 +366,6 @@ const XTrends = ({ setMenuSelection }) => {
</Message.Item>
</Message.List>
</Message>
</Segment>
</div>
)
}

View File

@@ -0,0 +1,74 @@
import React from "react"
import { Card, Badge } from "antd"
import { Link } from 'react-router-dom'
import { abilities, top500crown } from '../../img/imports'
const mainAbilityStyle = {
//https://github.com/loadout-ink/splat2-calc
zIndex: "2",
borderRadius: "50%",
width: "40px",
height: "40px",
background: "#000",
border: "2px solid #888",
borderRight: "0px",
borderBottom: "0px",
backgroundSize: "100%",
boxShadow: "0 0 0 1px #000"
}
const subAbilityStyle = {
//https://github.com/loadout-ink/splat2-calc
zIndex: "2",
borderRadius: "50%",
width: "30px",
height: "30px",
background: "#000",
border: "2px solid #888",
borderRight: "0px",
borderBottom: "0px",
backgroundSize: "100%",
boxShadow: "0 0 0 1px #000"
}
const parseIntoAbilityIcons = (element, index) => {
if (index === 0) {
return <span key={index}><img src={abilities[element].image} style={mainAbilityStyle} alt={element}/>{' '}</span>
} else {
return <img key={index} src={abilities[element].image} style={subAbilityStyle} alt={element} />
}
}
const BuildCard = ({ build }) => {
// Arrays of 4
const headAbilities = build.headgear
const clothingAbilities = build.clothing
const shoesAbilities = build.shoes
const userName = `${build.discord_user.username}#${build.discord_user.discriminator}` //TODO: Truncuate long nicknames to avoid the rows breaking
const playerProfileLink = `/u/${build.discord_id}`
const lastUpdated = new Date(parseInt(build.updatedAt)).toLocaleString("en-GB")
const card =
<Card style={{ width: 200, background: "WhiteSmoke" }}>
<p>{headAbilities.map(parseIntoAbilityIcons)}</p>
<p>{clothingAbilities.map(parseIntoAbilityIcons)}</p>
<p>{shoesAbilities.map(parseIntoAbilityIcons)}</p>
<Link to={playerProfileLink}>{userName}</Link><br/>
<i>{lastUpdated}</i>
</Card>
if (build.top) {
return (
<Badge count={<img src={top500crown} alt="top 500 indicator" style={{height: "25px", width: "auto"}}/>}>
{card}
</Badge>
)
} else {
return (
<>
{card}
</>
)
}
}
export default BuildCard

View File

@@ -1,13 +1,14 @@
import React from 'react'
import { useSelector } from 'react-redux'
import { Select } from 'antd';
import { Select } from 'antd'
import language_dict from '../../utils/english_internal.json'
const { Option, OptGroup } = Select;
const mainWeapons = [
{
categoryName: "Shooters",
weapons: ["Sploosh-o-matic", "Neo Sploosh-o-matic", "Sploosh-o-matic 7",
values: ["Sploosh-o-matic", "Neo Sploosh-o-matic", "Sploosh-o-matic 7",
"Splattershot Jr.", "Custom Splattershot Jr.", "Kensa Splattershot Jr.",
"Splash-o-matic", "Neo Splash-o-matic", "Aerospray MG", "Aerospray RG",
"Aerospray PG", "Splattershot", "Tentatek Splattershot", "Kensa Splattershot",
@@ -19,25 +20,25 @@ const mainWeapons = [
},
{
categoryName: "Blasters",
weapons: ["Luna Blaster", "Luna Blaster Neo", "Kensa Luna Blaster",
values: ["Luna Blaster", "Luna Blaster Neo", "Kensa Luna Blaster",
"Blaster", "Custom Blaster", "Range Blaster", "Custom Range Blaster",
"Grim Range Blaster", "Rapid Blaster", "Rapid Blaster Deco", "Kensa Rapid Blaster",
"Rapid Blaster Pro", "Rapid Blaster Pro Deco", "Clash Blaster", "Clash Blaster Neo"]
},
{
categoryName: "Rollers",
weapons: ["Carbon Roller", "Carbon Roller Deco", "Splat Roller", "Krak-On Splat Roller",
values: ["Carbon Roller", "Carbon Roller Deco", "Splat Roller", "Krak-On Splat Roller",
"Kensa Splat Roller", "Dynamo Roller", "Gold Dynamo Roller", "Kensa Dynamo Roller",
"Flingza Roller", "Foil Flingza Roller"]
},
{
categoryName: "Brushes",
weapons: ["Inkbrush", "Inkbrush Nouveau",
values: ["Inkbrush", "Inkbrush Nouveau",
"Permanent Inkbrush", "Octobrush", "Octobrush Nouveau", "Kensa Octobrush"]
},
{
categoryName: "Chargers",
weapons: ["Classic Squiffer", "New Squiffer", "Fresh Squiffer", "Splat Charger",
values: ["Classic Squiffer", "New Squiffer", "Fresh Squiffer", "Splat Charger",
"Firefin Splat Charger", "Kensa Charger", "Splatterscope", "Firefin Splatterscope",
"Kensa Splatterscope", "E-liter 4K", "Custom E-liter 4K", "E-liter 4K Scope",
"Custom E-liter 4K Scope", "Bamboozler 14 Mk I", "Bamboozler 14 Mk II",
@@ -45,28 +46,28 @@ const mainWeapons = [
},
{
categoryName: "Splatlings",
weapons: ["Mini Splatling", "Zink Mini Splatling", "Kensa Mini Splatling",
values: ["Mini Splatling", "Zink Mini Splatling", "Kensa Mini Splatling",
"Heavy Splatling", "Heavy Splatling Deco", "Heavy Splatling Remix",
"Hydra Splatling", "Custom Hydra Splatling", "Ballpoint Splatling",
"Ballpoint Splatling Nouveau", "Nautilus 47", "Nautilus 79"]
},
{
categoryName: "Sloshers",
weapons: ["Slosher", "Slosher Deco", "Soda Slosher", "Tri-Slosher",
values: ["Slosher", "Slosher Deco", "Soda Slosher", "Tri-Slosher",
"Tri-Slosher Nouveau", "Sloshing Machine", "Sloshing Machine Neo",
"Kensa Sloshing Machine", "Bloblobber", "Bloblobber Deco", "Explosher",
"Custom Explosher"]
},
{
categoryName: "Dualies",
weapons: ["Dapple Dualies", "Dapple Dualies Nouveau", "Clear Dapple Dualies",
values: ["Dapple Dualies", "Dapple Dualies Nouveau", "Clear Dapple Dualies",
"Splat Dualies", "Enperry Splat Dualies", "Kensa Splat Dualies", "Glooga Dualies",
"Glooga Dualies Deco", "Kensa Glooga Dualies", "Dualie Squelchers",
"Custom Dualie Squelchers", "Dark Tetra Dualies", "Light Tetra Dualies"]
},
{
categoryName: "Brellas",
weapons: ["Splat Brella", "Sorella Brella", "Tenta Brella", "Tenta Sorella Brella",
values: ["Splat Brella", "Sorella Brella", "Tenta Brella", "Tenta Sorella Brella",
"Tenta Camo Brella", "Undercover Brella", "Undercover Sorella Brella", "Kensa Undercover Brella"]
}
]
@@ -74,7 +75,7 @@ const mainWeapons = [
const allWeapons = [
{
categoryName: "Shooters",
weapons: ["Sploosh-o-matic", "Neo Sploosh-o-matic", "Sploosh-o-matic 7",
values: ["Sploosh-o-matic", "Neo Sploosh-o-matic", "Sploosh-o-matic 7",
"Splattershot Jr.", "Custom Splattershot Jr.", "Kensa Splattershot Jr.",
"Splash-o-matic", "Neo Splash-o-matic", "Aerospray MG", "Aerospray RG",
"Aerospray PG", "Splattershot", "Tentatek Splattershot", "Kensa Splattershot",
@@ -86,25 +87,25 @@ const allWeapons = [
},
{
categoryName: "Blasters",
weapons: ["Luna Blaster", "Luna Blaster Neo", "Kensa Luna Blaster",
values: ["Luna Blaster", "Luna Blaster Neo", "Kensa Luna Blaster",
"Blaster", "Custom Blaster", "Range Blaster", "Custom Range Blaster",
"Grim Range Blaster", "Rapid Blaster", "Rapid Blaster Deco", "Kensa Rapid Blaster",
"Rapid Blaster Pro", "Rapid Blaster Pro Deco", "Clash Blaster", "Clash Blaster Neo"]
},
{
categoryName: "Rollers",
weapons: ["Carbon Roller", "Carbon Roller Deco", "Splat Roller", "Krak-On Splat Roller",
values: ["Carbon Roller", "Carbon Roller Deco", "Splat Roller", "Krak-On Splat Roller",
"Kensa Splat Roller", "Dynamo Roller", "Gold Dynamo Roller", "Kensa Dynamo Roller",
"Flingza Roller", "Foil Flingza Roller"]
},
{
categoryName: "Brushes",
weapons: ["Inkbrush", "Inkbrush Nouveau",
values: ["Inkbrush", "Inkbrush Nouveau",
"Permanent Inkbrush", "Octobrush", "Octobrush Nouveau", "Kensa Octobrush"]
},
{
categoryName: "Chargers",
weapons: ["Classic Squiffer", "New Squiffer", "Fresh Squiffer", "Splat Charger",
values: ["Classic Squiffer", "New Squiffer", "Fresh Squiffer", "Splat Charger",
"Firefin Splat Charger", "Kensa Charger", "Splatterscope", "Firefin Splatterscope",
"Kensa Splatterscope", "E-liter 4K", "Custom E-liter 4K", "E-liter 4K Scope",
"Custom E-liter 4K Scope", "Bamboozler 14 Mk I", "Bamboozler 14 Mk II",
@@ -112,59 +113,62 @@ const allWeapons = [
},
{
categoryName: "Splatlings",
weapons: ["Mini Splatling", "Zink Mini Splatling", "Kensa Mini Splatling",
values: ["Mini Splatling", "Zink Mini Splatling", "Kensa Mini Splatling",
"Heavy Splatling", "Heavy Splatling Deco", "Heavy Splatling Remix",
"Hydra Splatling", "Custom Hydra Splatling", "Ballpoint Splatling",
"Ballpoint Splatling Nouveau", "Nautilus 47", "Nautilus 79"]
},
{
categoryName: "Sloshers",
weapons: ["Slosher", "Slosher Deco", "Soda Slosher", "Tri-Slosher",
values: ["Slosher", "Slosher Deco", "Soda Slosher", "Tri-Slosher",
"Tri-Slosher Nouveau", "Sloshing Machine", "Sloshing Machine Neo",
"Kensa Sloshing Machine", "Bloblobber", "Bloblobber Deco", "Explosher",
"Custom Explosher"]
},
{
categoryName: "Dualies",
weapons: ["Dapple Dualies", "Dapple Dualies Nouveau", "Clear Dapple Dualies",
values: ["Dapple Dualies", "Dapple Dualies Nouveau", "Clear Dapple Dualies",
"Splat Dualies", "Enperry Splat Dualies", "Kensa Splat Dualies", "Glooga Dualies",
"Glooga Dualies Deco", "Kensa Glooga Dualies", "Dualie Squelchers",
"Custom Dualie Squelchers", "Dark Tetra Dualies", "Light Tetra Dualies"]
},
{
categoryName: "Brellas",
weapons: ["Splat Brella", "Sorella Brella", "Tenta Brella", "Tenta Sorella Brella",
values: ["Splat Brella", "Sorella Brella", "Tenta Brella", "Tenta Sorella Brella",
"Tenta Camo Brella", "Undercover Brella", "Undercover Sorella Brella", "Kensa Undercover Brella"]
},
{
categoryName: "Sub weapons",
weapons: ["Splat Bomb", "Suction Bomb", "Burst Bomb", "Curling Bomb", "Autobomb", "Ink Mine", "Toxic Mist", "Point Sensor", "Splash Wall", "Sprinkler", "Squid Beakon", "Fizzy Bomb", "Torpedo"]
values: ["Splat Bomb", "Suction Bomb", "Burst Bomb", "Curling Bomb", "Autobomb", "Ink Mine", "Toxic Mist", "Point Sensor", "Splash Wall", "Sprinkler", "Squid Beakon", "Fizzy Bomb", "Torpedo"]
},
{
categoryName: "Special weapons",
weapons: ["Tenta Missiles", "Sting Ray", "Inkjet", "Splashdown", "Ink Armor", "Ink Storm", "Baller", "Bubble Blower", "Booyah Bomb", "Ultra Stamp", "Splat-Bomb Launcher", "Suction-Bomb Launcher", "Curling-Bomb Launcher", "Burst-Bomb Launcher", "Autobomb Launcher"]
values: ["Tenta Missiles", "Sting Ray", "Inkjet", "Splashdown", "Ink Armor", "Ink Storm", "Baller", "Bubble Blower", "Booyah Bomb", "Ultra Stamp", "Splat-Bomb Launcher", "Suction-Bomb Launcher", "Curling-Bomb Launcher", "Burst-Bomb Launcher", "Autobomb Launcher"]
},
]
const SelectElement = ({ onChange, content }) => {
const SelectElement = ({ value, onChange, content }) => {
const localization = useSelector(state => state.localization)
let contentArr = null
if (content === "MAINWEAPONS") contentArr = mainWeapons
else if (content === "ALLWEAPONS") contentArr = allWeapons
return (
<Select style={{ width: 200 }} onChange={onChange} showSearch>
{contentArr.map(c => {
return (
<OptGroup key={c.categoryName} label={localization[c.categoryName]}>
{c.weapons.map(w => {
return (
<Option key={w} value={w}>{localization[w]}</Option>
)
})}
</OptGroup>
)
})}
</Select>
<>
<Select style={{ width: 200 }} value={value} onChange={onChange} showSearch placeholder={localization["Select a weapon"]}>
{contentArr.map(c => {
return (
<OptGroup key={c.categoryName} label={localization[c.categoryName]}>
{c.values.map(w => {
return (
<Option key={w} value={w}>{localization[w]}</Option>
)
})}
</OptGroup>
)
})}
</Select>
{' '}{value && <img src={process.env.PUBLIC_URL + `/wpnSmall/Wst_${language_dict[value]}.png`} alt={value} />}
</>
)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 846 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 679 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 710 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 691 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1000 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 684 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 610 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 828 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 825 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 795 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 816 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 822 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 686 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 643 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 607 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 883 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 818 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 955 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 859 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 938 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 741 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 656 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 698 KiB

View File

@@ -10,6 +10,8 @@ query searchForBuildsByWeapon($weapon: String!, $page: Int) {
headgear
clothing
shoes
title
updatedAt
discord_user {
username
discriminator

View File

@@ -0,0 +1,39 @@
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
player {
twitter
}
}
pageCount
}
}
`

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 289 B

After

Width:  |  Height:  |  Size: 289 B

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

56
react-ui/src/img/imports.js vendored Normal file
View File

@@ -0,0 +1,56 @@
import top500 from './misc/top500.png'
import BDU from './abilityIcons/BDU.png'
import BRU from './abilityIcons/BRU.png'
import CB from './abilityIcons/CB.png'
import DR from './abilityIcons/DR.png'
import H from './abilityIcons/H.png'
import ISM from './abilityIcons/ISM.png'
import ISS from './abilityIcons/ISS.png'
import LDE from './abilityIcons/LDE.png'
import MPU from './abilityIcons/MPU.png'
import NS from './abilityIcons/NS.png'
import OG from './abilityIcons/OG.png'
import QR from './abilityIcons/QR.png'
import QSJ from './abilityIcons/QSJ.png'
import REC from './abilityIcons/REC.png'
import RES from './abilityIcons/RES.png'
import RP from './abilityIcons/RP.png'
import RSU from './abilityIcons/RSU.png'
import SCU from './abilityIcons/SCU.png'
import SJ from './abilityIcons/SJ.png'
import SPU from './abilityIcons/SPU.png'
import SS from './abilityIcons/SS.png'
import SSU from './abilityIcons/SSU.png'
import T from './abilityIcons/T.png'
import TI from './abilityIcons/TI.png'
import OS from './abilityIcons/OS.png'
export const abilities = {
"BDU": {image: BDU, fullName: "Bomb Defense Up DX"},
"BRU": {image: BRU, fullName: "Sub Power Up"},
"CB": {image: CB, fullName: "Comeback", mainOnly: true},
"DR": {image: DR, fullName: "Drop Roller", mainOnly: true},
"H": {image: H, fullName: "Haunt", mainOnly: true},
"ISM": {image: ISM, fullName: "Ink Saver (Main)"},
"ISS": {image: ISS, fullName: "Ink Saver (Sub)"},
"LDE": {image: LDE, fullName: "Last-Ditch Effort", mainOnly: true},
"MPU": {image: MPU, fullName: "Main Power Up"},
"NS": {image: NS, fullName: "Ninja Squid", mainOnly: true},
"OG": {image: OG, fullName: "Opening Gambit", mainOnly: true},
"QR": {image: QR, fullName: "Quick Respawn"},
"QSJ": {image: QSJ, fullName: "Quick Super Jump"},
"REC": {image: REC, fullName: "Ink Recovery Up"},
"RES": {image: RES, fullName: "Ink Resistance Up"},
"RP": {image: RP, fullName: "Respawn Punisher", mainOnly: true},
"RSU": {image: RSU, fullName: "Run Speed Up"},
"SCU": {image: SCU, fullName: "Special Charge Up"},
"SJ": {image: SJ, fullName: "Stealth Jump", mainOnly: true},
"SPU": {image: SPU, fullName: "Special Power Up"},
"SS": {image: SS, fullName: "Special Saver"},
"SSU": {image: SSU, fullName: "Swim Speed Up"},
"T": {image: T, fullName: "Tenacity", mainOnly: true},
"TI": {image: TI, fullName: "Thermal Ink", mainOnly: true},
"OS": {image: OS, fullName: "Object Shredder", mainOnly: true}
}
export const top500crown = top500

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Some files were not shown because too many files have changed in this diff Show More