diff --git a/index.js b/index.js
index fef3a66ec..7576289cb 100644
--- a/index.js
+++ b/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,
+ })
+ })
}
}
}
diff --git a/models/build.js b/models/build.js
index c027be577..a881449c7 100644
--- a/models/build.js
+++ b/models/build.js
@@ -9,4 +9,4 @@ const buildSchema = new mongoose.Schema({
shoes: {type: [String], required: true}
}, { timestamps: true })
-module.exports = mongoose.model('Build', maplistSchema)
\ No newline at end of file
+module.exports = mongoose.model('Build', buildSchema)
\ No newline at end of file
diff --git a/react-ui/src/components/SoloLadder/AbilityButtons.js b/react-ui/src/components/SoloLadder/AbilityButtons.js
new file mode 100644
index 000000000..e5d7e67f0
--- /dev/null
+++ b/react-ui/src/components/SoloLadder/AbilityButtons.js
@@ -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 (
+
+ {/*main only*/}
+
+
handleClick('CB')} style={{"padding": "2px"}}>
+
handleClick('LDE')} style={{"padding": "2px"}}>
+
handleClick('OG')} style={{"padding": "2px"}}>
+
handleClick('T')} style={{"padding": "2px"}}>
+
handleClick('H')} style={{"padding": "2px"}}>
+
handleClick('NS')} style={{"padding": "2px"}}>
+
handleClick('TI')} style={{"padding": "2px"}}>
+
handleClick('RP')} style={{"padding": "2px"}}>
+
handleClick('DR')} style={{"padding": "2px"}}>
+
handleClick('SJ')} style={{"padding": "2px"}}>
+
handleClick('OS')} style={{"padding": "2px"}}>
+
+ {/*stackables*/}
+
+
handleClick('BDU')} style={{"padding": "2px"}}>
+
handleClick('ISM')} style={{"padding": "2px"}}>
+
handleClick('ISS')} style={{"padding": "2px"}}>
+
handleClick('REC')} style={{"padding": "2px"}}>
+
handleClick('MPU')} style={{"padding": "2px"}}>
+
handleClick('SPU')} style={{"padding": "2px"}}>
+
handleClick('BRU')} style={{"padding": "2px"}}>
+
handleClick('QR')} style={{"padding": "2px"}}>
+
handleClick('QSJ')} style={{"padding": "2px"}}>
+
handleClick('SS')} style={{"padding": "2px"}}>
+
handleClick('SCU')} style={{"padding": "2px"}}>
+
handleClick('SSU')} style={{"padding": "2px"}}>
+
handleClick('RSU')} style={{"padding": "2px"}}>
+
handleClick('RES')} style={{"padding": "2px"}}>
+
+
+ )
+}
+
+export default AbilityButton
\ No newline at end of file
diff --git a/react-ui/src/components/SoloLadder/Build.js b/react-ui/src/components/SoloLadder/Build.js
new file mode 100644
index 000000000..6303938de
--- /dev/null
+++ b/react-ui/src/components/SoloLadder/Build.js
@@ -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 (
+
+ !setAbilities ? null : removeAbility(this.gearIndex, i)}/> {/* If setAbilities exists it means clicking ability should remove it. */}
+
+
+ )
+ }
+ if (!apsCalculated && a !== "") abilities[a].ap = ap + 3
+ return (
+
+ !setAbilities ? null : removeAbility(this.gearIndex, i)}
+ />
+
+ )
+ }
+
+ return (
+
+
+
+
+ {!build.title || build.title === "" ? `${build.weapon} Build` : build.title}
+
+
+
+
+
+
+ {build.headgear.map(abilityMap, {gearIndex: 0})}
+
+
+ {build.clothing.map(abilityMap, {gearIndex: 1})}
+
+
+ {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.*/}
+
+
+
+
+ {arrayOfSortedAbilityPoints().map(a => {a.ap} {a.fullName} )}
+
+
+
+
+
+
+
+
+ )
+}
+
+export default Build
\ No newline at end of file
diff --git a/react-ui/src/components/SoloLadder/BuildForm.js b/react-ui/src/components/SoloLadder/BuildForm.js
new file mode 100644
index 000000000..7a075878e
--- /dev/null
+++ b/react-ui/src/components/SoloLadder/BuildForm.js
@@ -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 (
+
+
+
+
+
+
+
+
+
+ Choose title (optional)
+ setTitle(e.target.value) }/>
+
+
+
+
+
+
+ Add build {/*OnClick gotta remember that weapon or title can be empty */}
+
+
+ )
+}
+
+export default BuildForm
\ No newline at end of file
diff --git a/react-ui/src/components/SoloLadder/BuildTab.js b/react-ui/src/components/SoloLadder/BuildTab.js
new file mode 100644
index 000000000..9b46dc47d
--- /dev/null
+++ b/react-ui/src/components/SoloLadder/BuildTab.js
@@ -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 (
+
+
+ Website by
Sendou . Data for the X Rank Leaderboards provided by
Lean .
+ Data for the rotations provided by
splatoon2.ink .
+
Source code for this site is available on
GitHub
+
+ )
+}
+
+export default BuildTab
\ No newline at end of file
diff --git a/react-ui/src/components/SoloLadder/UserPage.js b/react-ui/src/components/SoloLadder/UserPage.js
index 64ce6d560..4c64e0ac2 100644
--- a/react-ui/src/components/SoloLadder/UserPage.js
+++ b/react-ui/src/components/SoloLadder/UserPage.js
@@ -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
@@ -50,7 +60,7 @@ const UserPage = ({ userIdOrName }) => {
}
const panes = [ //Solo Ladder to be added
- { menuItem: 'Builds', render: () => No builds to show. },
+ { menuItem: 'Builds', render: () => },
{ menuItem: 'X Rank', render: () => },
]
diff --git a/react-ui/src/components/XSearch/WeaponForm.js b/react-ui/src/components/XSearch/WeaponForm.js
index c2194bdce..390017bd0 100644
--- a/react-ui/src/components/XSearch/WeaponForm.js
+++ b/react-ui/src/components/XSearch/WeaponForm.js
@@ -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 (
{
{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}
/>
)
diff --git a/react-ui/src/components/img/abilityIcons/BDU.png b/react-ui/src/components/img/abilityIcons/BDU.png
new file mode 100644
index 000000000..dcfe727c7
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/BDU.png differ
diff --git a/react-ui/src/components/img/abilityIcons/BRU.png b/react-ui/src/components/img/abilityIcons/BRU.png
new file mode 100644
index 000000000..23e6cf030
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/BRU.png differ
diff --git a/react-ui/src/components/img/abilityIcons/CB.png b/react-ui/src/components/img/abilityIcons/CB.png
new file mode 100644
index 000000000..aef7bb0da
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/CB.png differ
diff --git a/react-ui/src/components/img/abilityIcons/DR.png b/react-ui/src/components/img/abilityIcons/DR.png
new file mode 100644
index 000000000..1ef13663e
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/DR.png differ
diff --git a/react-ui/src/components/img/abilityIcons/EMPTY.png b/react-ui/src/components/img/abilityIcons/EMPTY.png
new file mode 100644
index 000000000..71c37a8fb
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/EMPTY.png differ
diff --git a/react-ui/src/components/img/abilityIcons/H.png b/react-ui/src/components/img/abilityIcons/H.png
new file mode 100644
index 000000000..90f757d4e
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/H.png differ
diff --git a/react-ui/src/components/img/abilityIcons/ISM.png b/react-ui/src/components/img/abilityIcons/ISM.png
new file mode 100644
index 000000000..b3540bffd
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/ISM.png differ
diff --git a/react-ui/src/components/img/abilityIcons/ISS.png b/react-ui/src/components/img/abilityIcons/ISS.png
new file mode 100644
index 000000000..7d575a133
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/ISS.png differ
diff --git a/react-ui/src/components/img/abilityIcons/LDE.png b/react-ui/src/components/img/abilityIcons/LDE.png
new file mode 100644
index 000000000..4695b56b3
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/LDE.png differ
diff --git a/react-ui/src/components/img/abilityIcons/MPU.png b/react-ui/src/components/img/abilityIcons/MPU.png
new file mode 100644
index 000000000..0a1eac9d7
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/MPU.png differ
diff --git a/react-ui/src/components/img/abilityIcons/NS.png b/react-ui/src/components/img/abilityIcons/NS.png
new file mode 100644
index 000000000..a9c8d2c87
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/NS.png differ
diff --git a/react-ui/src/components/img/abilityIcons/OG.png b/react-ui/src/components/img/abilityIcons/OG.png
new file mode 100644
index 000000000..6a47d6806
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/OG.png differ
diff --git a/react-ui/src/components/img/abilityIcons/OS.png b/react-ui/src/components/img/abilityIcons/OS.png
new file mode 100644
index 000000000..15beb8453
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/OS.png differ
diff --git a/react-ui/src/components/img/abilityIcons/QR.png b/react-ui/src/components/img/abilityIcons/QR.png
new file mode 100644
index 000000000..1777171f6
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/QR.png differ
diff --git a/react-ui/src/components/img/abilityIcons/QSJ.png b/react-ui/src/components/img/abilityIcons/QSJ.png
new file mode 100644
index 000000000..2dcbaa32c
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/QSJ.png differ
diff --git a/react-ui/src/components/img/abilityIcons/REC.png b/react-ui/src/components/img/abilityIcons/REC.png
new file mode 100644
index 000000000..e5c4399ae
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/REC.png differ
diff --git a/react-ui/src/components/img/abilityIcons/RES.png b/react-ui/src/components/img/abilityIcons/RES.png
new file mode 100644
index 000000000..be3ea4738
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/RES.png differ
diff --git a/react-ui/src/components/img/abilityIcons/RP.png b/react-ui/src/components/img/abilityIcons/RP.png
new file mode 100644
index 000000000..533df1266
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/RP.png differ
diff --git a/react-ui/src/components/img/abilityIcons/RSU.png b/react-ui/src/components/img/abilityIcons/RSU.png
new file mode 100644
index 000000000..0ebde89f9
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/RSU.png differ
diff --git a/react-ui/src/components/img/abilityIcons/SCU.png b/react-ui/src/components/img/abilityIcons/SCU.png
new file mode 100644
index 000000000..56e232c91
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/SCU.png differ
diff --git a/react-ui/src/components/img/abilityIcons/SJ.png b/react-ui/src/components/img/abilityIcons/SJ.png
new file mode 100644
index 000000000..6bb4c3f21
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/SJ.png differ
diff --git a/react-ui/src/components/img/abilityIcons/SPU.png b/react-ui/src/components/img/abilityIcons/SPU.png
new file mode 100644
index 000000000..ad279c9e5
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/SPU.png differ
diff --git a/react-ui/src/components/img/abilityIcons/SS.png b/react-ui/src/components/img/abilityIcons/SS.png
new file mode 100644
index 000000000..e96c05a91
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/SS.png differ
diff --git a/react-ui/src/components/img/abilityIcons/SSU.png b/react-ui/src/components/img/abilityIcons/SSU.png
new file mode 100644
index 000000000..73e1dd548
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/SSU.png differ
diff --git a/react-ui/src/components/img/abilityIcons/T.png b/react-ui/src/components/img/abilityIcons/T.png
new file mode 100644
index 000000000..7121d7c4a
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/T.png differ
diff --git a/react-ui/src/components/img/abilityIcons/TI.png b/react-ui/src/components/img/abilityIcons/TI.png
new file mode 100644
index 000000000..33d8b15b0
Binary files /dev/null and b/react-ui/src/components/img/abilityIcons/TI.png differ
diff --git a/react-ui/src/graphql/mutations/addBuild.js b/react-ui/src/graphql/mutations/addBuild.js
new file mode 100644
index 000000000..51f44924d
--- /dev/null
+++ b/react-ui/src/graphql/mutations/addBuild.js
@@ -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
+ }
+}
+`
\ No newline at end of file
diff --git a/utils/weapons.js b/utils/weapons.js
new file mode 100644
index 000000000..9094e5f44
--- /dev/null
+++ b/utils/weapons.js
@@ -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
\ No newline at end of file