working BuildForm component
161
index.js
@@ -14,6 +14,7 @@ const Link = require('./models/link')
|
||||
const User = require('./models/user')
|
||||
const Build = require('./models/build')
|
||||
const path = require('path')
|
||||
const weapons = require('./utils/weapons')
|
||||
|
||||
mongoose.set('useFindAndModify', false)
|
||||
mongoose.set('useCreateIndex', true)
|
||||
@@ -183,141 +184,9 @@ const typeDefs = gql`
|
||||
BRU
|
||||
}
|
||||
|
||||
enum Weapon {
|
||||
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
|
||||
.52 Gal
|
||||
.52 Gal Deco
|
||||
Kensa .52 Gal
|
||||
N-ZAP '85
|
||||
N-ZAP '89
|
||||
N-ZAP '83
|
||||
Splattershot Pro
|
||||
Forge Splattershot Pro
|
||||
Kensa Splattershot Pro
|
||||
.96 Gal
|
||||
.96 Gal Deco
|
||||
Jet Squelcher
|
||||
Custom Jet Squelcher
|
||||
L-3 Nozzlenose
|
||||
L-3 Nozzlenose D
|
||||
Kensa L-3 Nozzlenose
|
||||
H-3 Nozzlenose
|
||||
H-3 Nozzlenose D
|
||||
Cherry H-3 Nozzlenose
|
||||
Squeezer
|
||||
Foil Squeezer
|
||||
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
|
||||
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
|
||||
Inkbrush
|
||||
Inkbrush Nouveau
|
||||
Permanent Inkbrush
|
||||
Octobrush
|
||||
Octobrush Nouveau
|
||||
Kensa Octobrush
|
||||
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
|
||||
Bamboozler 14 Mk III
|
||||
Goo Tuber
|
||||
Custom Goo Tuber
|
||||
Slosher
|
||||
Slosher Deco
|
||||
Soda Slosher
|
||||
Tri-Slosher
|
||||
Tri-Slosher Nouveau
|
||||
Sloshing Machine
|
||||
Sloshing Machine Neo
|
||||
Kensa Sloshing Machine
|
||||
Bloblobber
|
||||
Bloblobber Deco
|
||||
Explosher
|
||||
Custom Explosher
|
||||
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
|
||||
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
|
||||
Splat Brella
|
||||
Sorella Brella
|
||||
Tenta Brella
|
||||
Tenta Sorella Brella
|
||||
Tenta Camo Brella
|
||||
Undercover Brella
|
||||
Undercover Sorella Brella
|
||||
Kensa Undercover Brella
|
||||
}
|
||||
|
||||
type Build {
|
||||
discord_id: String!
|
||||
weapon: Weapon!
|
||||
weapon: String!
|
||||
title: String
|
||||
headgear: [Ability!]!
|
||||
clothing: [Ability!]!
|
||||
@@ -358,7 +227,7 @@ const typeDefs = gql`
|
||||
password: String!
|
||||
): Token
|
||||
addBuild(
|
||||
weapon: Weapon!
|
||||
weapon: String!
|
||||
title: String
|
||||
headgear: [Ability!]!
|
||||
clothing: [Ability!]!
|
||||
@@ -670,6 +539,15 @@ const resolvers = {
|
||||
invalidArgs: args,
|
||||
})
|
||||
})
|
||||
},
|
||||
searchForBuilds: (root, args) => {
|
||||
return Build
|
||||
.find( {discord_id: args.discord_id })
|
||||
.catch(e => {
|
||||
throw new UserInputError(e.message, {
|
||||
invalidArgs, args,
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
Mutation: {
|
||||
@@ -677,8 +555,11 @@ const resolvers = {
|
||||
if (!ctx.user) throw new AuthenticationError('User not logged in.')
|
||||
if (ctx.title.length > 100) throw new UserInputError('Title too long.', {
|
||||
invalidArgs: args,
|
||||
}) //100 good limit or more?
|
||||
// need to validate that haunt not a sub etc.
|
||||
})
|
||||
if (!weapons.includes(args.weapon)) throw new UserInputError('Invalid weapon.', {
|
||||
invalidArgs: args,
|
||||
})
|
||||
|
||||
const existingBuilds = await Build
|
||||
.find({ discord_id: ctx.user.discord_id})
|
||||
.catch(e => {
|
||||
@@ -690,7 +571,13 @@ const resolvers = {
|
||||
invalidArgs: args,
|
||||
})
|
||||
const build = new Build({ ...args, discord_id: ctx.user.discord_id })
|
||||
return await Build.create(build) //?
|
||||
return await Build
|
||||
.create(build)
|
||||
.catch(e => {
|
||||
throw new UserInputError(e.message, {
|
||||
invalidArgs: args,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,4 +9,4 @@ const buildSchema = new mongoose.Schema({
|
||||
shoes: {type: [String], required: true}
|
||||
}, { timestamps: true })
|
||||
|
||||
module.exports = mongoose.model('Build', maplistSchema)
|
||||
module.exports = mongoose.model('Build', buildSchema)
|
||||
101
react-ui/src/components/SoloLadder/AbilityButtons.js
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
/* eslint-disable jsx-a11y/alt-text */
|
||||
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'
|
||||
|
||||
const headOnly = ["CB", "LDE", "OG", "T"]
|
||||
const clothingOnly = ["H", "NS", "TI", "RP"]
|
||||
const shoesOnly = ["DR", "SJ", "OS"]
|
||||
|
||||
const AbilityButton = ({ abilities, setAbilities }) => {
|
||||
function handleClick(abilityName) {
|
||||
let copyOfArray = [...abilities]
|
||||
if (headOnly.includes(abilityName)) {
|
||||
if (abilities[0][0] === "") {
|
||||
copyOfArray[0][0] = abilityName
|
||||
}
|
||||
} else if (clothingOnly.includes(abilityName)) {
|
||||
if (abilities[1][0] === "") {
|
||||
copyOfArray[1][0] = abilityName
|
||||
}
|
||||
} else if (shoesOnly.includes(abilityName)) {
|
||||
if (abilities[2][0] === "") {
|
||||
copyOfArray[2][0] = abilityName
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < abilities.length; i++) {
|
||||
for (let j = 0; j < abilities[i].length; j++) {
|
||||
const element = abilities[i][j]
|
||||
if (element === "") {
|
||||
copyOfArray[i][j] = abilityName
|
||||
setAbilities(copyOfArray)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setAbilities(copyOfArray)
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{/*main only*/}
|
||||
<div>
|
||||
<Button circular color='black' onClick={() => handleClick('CB')} style={{"padding": "2px"}}><img src={CB} style={{ "maxWidth": "40px", "height": "auto" }} /></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('LDE')} style={{"padding": "2px"}}><img src={LDE} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('OG')} style={{"padding": "2px"}}><img src={OG} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('T')} style={{"padding": "2px"}}><img src={T} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('H')} style={{"padding": "2px"}}><img src={H} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('NS')} style={{"padding": "2px"}}><img src={NS} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('TI')} style={{"padding": "2px"}}><img src={TI} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('RP')} style={{"padding": "2px"}}><img src={RP} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('DR')} style={{"padding": "2px"}}><img src={DR} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('SJ')} style={{"padding": "2px"}}><img src={SJ} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('OS')} style={{"padding": "2px"}}><img src={OS} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
</div>
|
||||
{/*stackables*/}
|
||||
<div style={{"paddingTop": "3px"}}>
|
||||
<Button circular color='black' onClick={() => handleClick('BDU')} style={{"padding": "2px"}}><img src={BDU} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('ISM')} style={{"padding": "2px"}}><img src={ISM} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('ISS')} style={{"padding": "2px"}}><img src={ISS} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('REC')} style={{"padding": "2px"}}><img src={REC} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('MPU')} style={{"padding": "2px"}}><img src={MPU} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('SPU')} style={{"padding": "2px"}}><img src={SPU} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('BRU')} style={{"padding": "2px"}}><img src={BRU} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('QR')} style={{"padding": "2px"}}><img src={QR} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('QSJ')} style={{"padding": "2px"}}><img src={QSJ} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('SS')} style={{"padding": "2px"}}><img src={SS} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('SCU')} style={{"padding": "2px"}}><img src={SCU} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('SSU')} style={{"padding": "2px"}}><img src={SSU} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('RSU')} style={{"padding": "2px"}}><img src={RSU} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
<Button circular color='black' onClick={() => handleClick('RES')} style={{"padding": "2px"}}><img src={RES} style={{ "maxWidth": "40px", "height": "auto" }}/></Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AbilityButton
|
||||
156
react-ui/src/components/SoloLadder/Build.js
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
/* eslint-disable jsx-a11y/alt-text */
|
||||
import React from 'react'
|
||||
import { Header, Segment, List, Grid } from 'semantic-ui-react'
|
||||
import weaponDict from '../../utils/english_internal.json'
|
||||
|
||||
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 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},
|
||||
"": {ap: 0, mainOnly: true}
|
||||
}
|
||||
|
||||
let apsCalculated = false //i'm sure there is a better way to do this but...
|
||||
|
||||
const lineStyle = {
|
||||
"display": "inline-block",
|
||||
"width": "2px",
|
||||
"backgroundColor": "white",
|
||||
"margin": "0 10px",
|
||||
"height": "4em"
|
||||
}
|
||||
const arrayOfSortedAbilityPoints = () => {
|
||||
var sortable = []
|
||||
for (var abilityObj in abilities) {
|
||||
if (abilities[abilityObj].hasOwnProperty("ap") && !abilities[abilityObj].mainOnly) {
|
||||
sortable.push(abilities[abilityObj])
|
||||
}
|
||||
}
|
||||
sortable.sort((a, b) => {
|
||||
return b.ap - a.ap
|
||||
})
|
||||
return sortable
|
||||
}
|
||||
|
||||
const Build = ({ build, existingAbilities, setAbilities }) => {
|
||||
const imageSource = build.weapon === '' ? EMPTY : `https://raw.githubusercontent.com/Leanny/leanny.github.io/master/splat2/weapons/Wst_${weaponDict[build.weapon]}.png`
|
||||
|
||||
function removeAbility(gearIndex, slotIndex) {
|
||||
let copyOfArray = [...existingAbilities]
|
||||
copyOfArray[gearIndex][slotIndex] = ""
|
||||
setAbilities(copyOfArray)
|
||||
}
|
||||
|
||||
function abilityMap(a, i) {
|
||||
const ap = abilities[a].ap ? abilities[a].ap : 0
|
||||
const imageSrc = a === "" ? EMPTY : abilities[a].image
|
||||
if (i === 0) {
|
||||
if (!apsCalculated && a !== "") abilities[a].ap = ap + 10
|
||||
return (
|
||||
<span key={i}>
|
||||
<img src={imageSrc} alt={a} onClick={() => !setAbilities ? null : removeAbility(this.gearIndex, i)}/> {/* If setAbilities exists it means clicking ability should remove it. */}
|
||||
<span style={lineStyle} />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
if (!apsCalculated && a !== "") abilities[a].ap = ap + 3
|
||||
return (
|
||||
<span key={i} style={{"padding": "1px"}}>
|
||||
<img
|
||||
src={imageSrc}
|
||||
alt={a}
|
||||
style={{ "maxWidth": "40px", "height": "auto" }}
|
||||
onClick={() => !setAbilities ? null : removeAbility(this.gearIndex, i)}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Segment inverted>
|
||||
<div>
|
||||
<Header size='huge' inverted>
|
||||
<img
|
||||
src={imageSource}
|
||||
/> {!build.title || build.title === "" ? `${build.weapon} Build` : build.title}
|
||||
</Header>
|
||||
</div>
|
||||
<div style={{"paddingLeft": "13px"}}>
|
||||
<Grid stackable columns={4}>
|
||||
<Grid.Column>
|
||||
<div>
|
||||
{build.headgear.map(abilityMap, {gearIndex: 0})}
|
||||
</div>
|
||||
<div>
|
||||
{build.clothing.map(abilityMap, {gearIndex: 1})}
|
||||
</div>
|
||||
<div>
|
||||
{build.shoes.map(abilityMap, {gearIndex: 2})}
|
||||
{apsCalculated = true} {/*This implementation makes it so that AP's aren't shown when new build is made but it might be sick if they did.*/}
|
||||
</div>
|
||||
</Grid.Column>
|
||||
<Grid.Column>
|
||||
<List>
|
||||
{arrayOfSortedAbilityPoints().map(a => <List.Item key={a.fullName}>{a.ap} {a.fullName}</List.Item>)}
|
||||
</List>
|
||||
</Grid.Column>
|
||||
<Grid.Column></Grid.Column>
|
||||
<Grid.Column></Grid.Column>
|
||||
</Grid>
|
||||
</div>
|
||||
</Segment>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Build
|
||||
61
react-ui/src/components/SoloLadder/BuildForm.js
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Form, Message, Button } from 'semantic-ui-react'
|
||||
import WeaponForm from '../XSearch/WeaponForm'
|
||||
import Build from './Build'
|
||||
import AbilityButtons from './AbilityButtons'
|
||||
|
||||
const BuildForm = () => {
|
||||
const [weaponForm, setWeaponForm] = useState('')
|
||||
const [title, setTitle] = useState('')
|
||||
const [abilities, setAbilities] = useState([["", "", "", ""], ["", "", "", ""], ["", "", "", ""]])
|
||||
const build = {
|
||||
weapon: weaponForm,
|
||||
title,
|
||||
headgear: abilities[0],
|
||||
clothing: abilities[1],
|
||||
shoes: abilities[2]
|
||||
}
|
||||
function isBuildComplete() {
|
||||
if (title.length > 100) return false
|
||||
if (weaponForm === '') return false
|
||||
for (let i = 0; i < abilities.length; i++) {
|
||||
for (let j = 0; j < abilities[i].length; j++) {
|
||||
const element = abilities[i][j]
|
||||
if (element === "") {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<Build build={build} existingAbilities={abilities} setAbilities={setAbilities}/>
|
||||
</div>
|
||||
<div style={{"paddingTop": "15px"}}>
|
||||
<WeaponForm weaponForm={weaponForm} setWeaponForm={setWeaponForm} showImages={false} />
|
||||
</div>
|
||||
<div style={{"paddingTop": "15px"}}>
|
||||
<Form error={title.length > 100}>
|
||||
<Form.Field>
|
||||
<label>Choose title (optional)</label>
|
||||
<input placeholder='Choose title (optional)' value={title} onChange={(e) => setTitle(e.target.value) }/>
|
||||
<Message
|
||||
error
|
||||
content="Title can't be longer than 100 characters."
|
||||
/>
|
||||
</Form.Field>
|
||||
</Form>
|
||||
</div>
|
||||
<div style={{"paddingTop": "10px"}}>
|
||||
<AbilityButtons abilities={abilities} setAbilities={setAbilities} />
|
||||
</div>
|
||||
<div style={{"paddingTop": "10px"}}>
|
||||
<Button disabled={!isBuildComplete()}>Add build</Button> {/*OnClick gotta remember that weapon or title can be empty */}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default BuildForm
|
||||
18
react-ui/src/components/SoloLadder/BuildTab.js
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from 'react'
|
||||
import { Icon } from 'semantic-ui-react'
|
||||
import { useQuery, useMutation } from 'react-apollo-hooks'
|
||||
|
||||
import { addBuild } from '../../graphql/mutations/addBuilds'
|
||||
|
||||
const BuildTab = () => {
|
||||
return (
|
||||
<div style={{"fontSize": "small", "paddingTop": "25px"}} >
|
||||
<hr />
|
||||
Website by <a href="https://twitter.com/sendouc">Sendou</a>. Data for the X Rank Leaderboards provided by <a href="https://twitter.com/LeanYoshi">Lean</a>.
|
||||
Data for the rotations provided by <a href="https://splatoon2.ink/">splatoon2.ink</a>.<br />
|
||||
<Icon name='github' /> Source code for this site is available on <a href="https://github.com/Sendouc/sendou-ink">GitHub</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default BuildTab
|
||||
12
react-ui/src/components/SoloLadder/UserPage.js
vendored
@@ -3,9 +3,19 @@ import { Tab, Image, Loader, List, Grid } from 'semantic-ui-react'
|
||||
import { useQuery } from 'react-apollo-hooks'
|
||||
import { searchForUser } from '../../graphql/queries/searchForUser'
|
||||
import InfoPlayer from '../../components/XSearch/InfoPlayer'
|
||||
import Build from './Build'
|
||||
import BuildForm from './BuildForm'
|
||||
|
||||
const UserPage = ({ userIdOrName }) => {
|
||||
const { data, error, loading } = useQuery(searchForUser, {variables: { discord_id: userIdOrName }})
|
||||
const dummyBuild = {
|
||||
discord_id: "79237403620945920",
|
||||
weapon: "Tenta Camo Brella",
|
||||
title: "Standard Camo Tenta build for aggressive playstyle",
|
||||
headgear: ["", "SSU", "RSU", "RSU"],
|
||||
clothing: ["QR", "RSU", "", "SS"],
|
||||
shoes: ["QR", "SS", "RES", ""]
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return <div style={{"paddingTop": "25px", "paddingBottom": "20000px"}} ><Loader active inline='centered' /></div>
|
||||
@@ -50,7 +60,7 @@ const UserPage = ({ userIdOrName }) => {
|
||||
}
|
||||
|
||||
const panes = [ //Solo Ladder to be added
|
||||
{ menuItem: 'Builds', render: () => <Tab.Pane>No builds to show.</Tab.Pane> },
|
||||
{ menuItem: 'Builds', render: () => <Tab.Pane><BuildForm /></Tab.Pane> },
|
||||
{ menuItem: 'X Rank', render: () => <Tab.Pane><InfoPlayer twitter={userData.twitter_name} /></Tab.Pane> },
|
||||
]
|
||||
|
||||
|
||||
10
react-ui/src/components/XSearch/WeaponForm.js
vendored
@@ -4,7 +4,7 @@ import { withRouter } from 'react-router-dom'
|
||||
import { weapons } from '../../utils/lists'
|
||||
import weaponDict from '../../utils/english_internal.json'
|
||||
|
||||
const WeaponForm = (props) => {
|
||||
const WeaponForm = ({ weaponForm, setWeaponForm, showImages=true }) => {
|
||||
return (
|
||||
<div>
|
||||
<Dropdown
|
||||
@@ -17,11 +17,13 @@ const WeaponForm = (props) => {
|
||||
{key: w,
|
||||
text: w,
|
||||
value: w,
|
||||
image: {src: process.env.PUBLIC_URL + `/wpnSmall/Wst_${weaponDict[w]}.png`}})
|
||||
image: showImages ? {src: process.env.PUBLIC_URL + `/wpnSmall/Wst_${weaponDict[w]}.png`} : null
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
onChange={(event, { value }) => props.setWeaponForm(value)}
|
||||
value={props.weaponForm}
|
||||
onChange={(event, { value }) => setWeaponForm(value)}
|
||||
value={weaponForm}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
BIN
react-ui/src/components/img/abilityIcons/BDU.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
react-ui/src/components/img/abilityIcons/BRU.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
react-ui/src/components/img/abilityIcons/CB.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
react-ui/src/components/img/abilityIcons/DR.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
react-ui/src/components/img/abilityIcons/EMPTY.png
Normal file
|
After Width: | Height: | Size: 289 B |
BIN
react-ui/src/components/img/abilityIcons/H.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
react-ui/src/components/img/abilityIcons/ISM.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
react-ui/src/components/img/abilityIcons/ISS.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
react-ui/src/components/img/abilityIcons/LDE.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
react-ui/src/components/img/abilityIcons/MPU.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
react-ui/src/components/img/abilityIcons/NS.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
react-ui/src/components/img/abilityIcons/OG.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
react-ui/src/components/img/abilityIcons/OS.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
react-ui/src/components/img/abilityIcons/QR.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
react-ui/src/components/img/abilityIcons/QSJ.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
react-ui/src/components/img/abilityIcons/REC.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
react-ui/src/components/img/abilityIcons/RES.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
react-ui/src/components/img/abilityIcons/RP.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
react-ui/src/components/img/abilityIcons/RSU.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
react-ui/src/components/img/abilityIcons/SCU.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
react-ui/src/components/img/abilityIcons/SJ.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
react-ui/src/components/img/abilityIcons/SPU.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
react-ui/src/components/img/abilityIcons/SS.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
react-ui/src/components/img/abilityIcons/SSU.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
react-ui/src/components/img/abilityIcons/T.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
react-ui/src/components/img/abilityIcons/TI.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
20
react-ui/src/graphql/mutations/addBuild.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const addBuild = gql`
|
||||
mutation addBuild ($weapon: String!, $title: String, $headgear: [Ability!]!, $clothing: [Ability!]!, $shoes: [Ability!]!) {
|
||||
addBuild(
|
||||
weapon: $weapon,
|
||||
title: $title,
|
||||
headgear: $headgear,
|
||||
clothing: $clothing,
|
||||
shoes: $shoes
|
||||
) {
|
||||
weapon
|
||||
title
|
||||
headgear
|
||||
clothing
|
||||
shoes
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
`
|
||||
37
utils/weapons.js
Normal file
@@ -0,0 +1,37 @@
|
||||
const weapons = ["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",
|
||||
".52 Gal", ".52 Gal Deco", "Kensa .52 Gal", "N-ZAP '85", "N-ZAP '89",
|
||||
"N-ZAP '83", "Splattershot Pro", "Forge Splattershot Pro", "Kensa Splattershot Pro",
|
||||
".96 Gal", ".96 Gal Deco", "Jet Squelcher", "Custom Jet Squelcher",
|
||||
"L-3 Nozzlenose", "L-3 Nozzlenose D", "Kensa L-3 Nozzlenose",
|
||||
"H-3 Nozzlenose", "H-3 Nozzlenose D", "Cherry H-3 Nozzlenose", "Squeezer",
|
||||
"Foil Squeezer",
|
||||
"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",
|
||||
"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", "Inkbrush", "Inkbrush Nouveau",
|
||||
"Permanent Inkbrush", "Octobrush", "Octobrush Nouveau", "Kensa Octobrush",
|
||||
"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",
|
||||
"Bamboozler 14 Mk III", "Goo Tuber", "Custom Goo Tuber", "Slosher", "Slosher Deco", "Soda Slosher", "Tri-Slosher",
|
||||
"Tri-Slosher Nouveau", "Sloshing Machine", "Sloshing Machine Neo",
|
||||
"Kensa Sloshing Machine", "Bloblobber", "Bloblobber Deco", "Explosher",
|
||||
"Custom Explosher", "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",
|
||||
"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",
|
||||
"Splat Brella", "Sorella Brella", "Tenta Brella", "Tenta Sorella Brella",
|
||||
"Tenta Camo Brella", "Undercover Brella", "Undercover Sorella Brella", "Kensa Undercover Brella"]
|
||||
|
||||
module.exports = weapons
|
||||