mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-28 06:10:01 -05:00
started implementing player search
This commit is contained in:
41
index.js
41
index.js
@@ -96,6 +96,7 @@ const typeDefs = gql`
|
||||
topPlayers (weapon: String!): topPlayer!
|
||||
weaponPlacementStats(weapon: String!): [Int!]!
|
||||
playerInfo(uid: String!): PlayerWithPlacements!
|
||||
searchForPlayers(name: String! exact: Boolean): [Placement]!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
@@ -322,6 +323,46 @@ const resolvers = {
|
||||
})
|
||||
|
||||
return { player, placements }
|
||||
},
|
||||
searchForPlayers: async (root, args) => {
|
||||
let placements = []
|
||||
if (args.exact) {
|
||||
placements = await Placement
|
||||
.find({ name: args.name })
|
||||
.sort({ "x_power": "desc" })
|
||||
.limit(100)
|
||||
.select({ name: 1, weapon: 1, x_power: 1, unique_id: 1})
|
||||
.catch(e => {
|
||||
throw new UserInputError(e.message, {
|
||||
invalidArgs: args,
|
||||
})
|
||||
})
|
||||
} else {
|
||||
placements = await Placement
|
||||
.find({ name: { "$regex": args.name, "$options": "i" }})
|
||||
.sort({ "x_power": "desc" })
|
||||
.limit(100)
|
||||
.select({ name: 1, weapon: 1, x_power: 1, unique_id: 1})
|
||||
.catch(e => {
|
||||
throw new UserInputError(e.message, {
|
||||
invalidArgs: args,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
let uids = []
|
||||
|
||||
return placements.filter(p => {
|
||||
if (uids.length === 21) {
|
||||
return false
|
||||
}
|
||||
const bool = uids.includes(p.unique_id)
|
||||
if (bool) {
|
||||
return false
|
||||
}
|
||||
uids.push(p.unique_id)
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9
react-ui/src/components/InfoPlayer.js
vendored
9
react-ui/src/components/InfoPlayer.js
vendored
@@ -60,6 +60,15 @@ const InfoPlayer = ({ uid }) => {
|
||||
{playerData.twitter ? <Image circular src={`https://avatars.io/twitter/${playerData.twitter}`} /> : null} {playerData.alias ? playerData.alias : playerData.name}
|
||||
{playerData.twitter ? <a href={`https://twitter.com/${playerData.twitter}`}><Icon style={{"paddingLeft": "5px"}} size='small' name="twitter"/></a> : null}
|
||||
</Header>
|
||||
{playerData.topTotalScore ? <><i>Total Power: {playerData.topTotalScore}</i><br /></> : null}
|
||||
{playerData.topShooterScore ? <><i>Shooter Power: {playerData.topShooterScore}</i><br /></> : null}
|
||||
{playerData.topBlasterScore ? <><i>Blaster Power: {playerData.topBlasterScore}</i><br /></> : null}
|
||||
{playerData.topRollerScore ? <><i>Roller Power: {playerData.topRollerScore}</i><br /></> : null}
|
||||
{playerData.topChargerScore ? <><i>Charger Power: {playerData.topChargerScore}</i><br /></> : null}
|
||||
{playerData.topSlosherScore ? <><i>Slosher Power: {playerData.topSlosherScore}</i><br /></> : null}
|
||||
{playerData.topSplatlingScore ? <><i>Splatling Power: {playerData.topSplatlingScore}</i><br /></> : null}
|
||||
{playerData.topDualiesScore ? <><i>Dualies Power: {playerData.topDualiesScore}</i><br /></> : null}
|
||||
{playerData.topBrellaScore ? <><i>Brella Power: {playerData.topBrellaScore}</i><br /></> : null}
|
||||
<TopPlacementTable top={top} />
|
||||
<Header dividing style={{"paddingTop": "5px"}}>All Top 500 placements</Header>
|
||||
<MonthsTable placements={data.playerInfo.placements} />
|
||||
|
||||
2
react-ui/src/components/NotFound.js
vendored
2
react-ui/src/components/NotFound.js
vendored
@@ -50,7 +50,7 @@ const NotFound = () => {
|
||||
<Header size='small'>404 - Page not found</Header>
|
||||
</div>
|
||||
<div style={{display: 'flex', justifyContent:'center', alignItems:'center'}}>
|
||||
<i>...not unlike {mapObject.name} can't be found in Splatoon 2</i>
|
||||
<i>...not unlike how {mapObject.name} can't be found in Splatoon 2</i>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
12
react-ui/src/components/XSearch.js
vendored
12
react-ui/src/components/XSearch.js
vendored
@@ -4,11 +4,13 @@ import { Route, withRouter } from 'react-router-dom'
|
||||
import WeaponForm from '../components/WeaponForm'
|
||||
import InfoWeapon from '../components/InfoWeapon'
|
||||
import InfoPlayer from '../components/InfoPlayer'
|
||||
import XSearchResults from '../components/XSearchResults'
|
||||
import weaponDict from '../utils/english_internal.json'
|
||||
|
||||
const XSearch = withRouter(({ history, setMenuSelection }) => {
|
||||
const [weaponForm, setWeaponForm] = useState('')
|
||||
const [playerForm, setPlayerForm] = useState('')
|
||||
const [exact, setExact] = useState(false)
|
||||
useEffect(() => {
|
||||
setMenuSelection('search')
|
||||
document.title = "X Rank Top 500 Search - sendou.ink"
|
||||
@@ -22,13 +24,17 @@ const XSearch = withRouter(({ history, setMenuSelection }) => {
|
||||
<Button disabled={weaponForm === ''} onClick={() => history.push(`/xsearch/w/${weaponDict[weaponForm].replace(/_/g, '-')}`)}>Search for a weapon</Button>
|
||||
<div style={{"paddingTop": "5px", "paddingBottom": "5px"}}><b>or</b></div>
|
||||
<Form>
|
||||
<Form.Input placeholder='Enter a player name (not implemented yet)' />
|
||||
<Form.Input
|
||||
placeholder='Search for a player'
|
||||
value={playerForm}
|
||||
onChange={(event) => setPlayerForm(event.target.value)} />
|
||||
<Message
|
||||
error
|
||||
content='No players matching this name could be found.'
|
||||
/>
|
||||
</Form>
|
||||
<Button disabled>Search for a player</Button>
|
||||
<Button disabled={playerForm.length === 0}>Search for a player</Button>
|
||||
{playerForm.length !== 999 ? null : <XSearchResults name={playerForm} exact={exact} setPlayerForm={setPlayerForm} />}
|
||||
</div>
|
||||
<Route exact path="/xsearch/w/:wpn" render={({ match }) =>
|
||||
<InfoWeapon wpn={match.params.wpn.replace(/-/g, '_')} setWeaponForm={setWeaponForm} />
|
||||
@@ -38,6 +44,6 @@ const XSearch = withRouter(({ history, setMenuSelection }) => {
|
||||
} />
|
||||
</div>
|
||||
)
|
||||
}) //alemmalle buttonille onChange uncontrolled?
|
||||
}) //weapon forming renderöinti liian raskas
|
||||
|
||||
export default XSearch
|
||||
54
react-ui/src/components/XSearchResults.js
vendored
Normal file
54
react-ui/src/components/XSearchResults.js
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import React from 'react'
|
||||
import { withRouter } from 'react-router-dom'
|
||||
import { useQuery } from 'react-apollo-hooks'
|
||||
import { Loader, Message, Grid, Button, Header } from 'semantic-ui-react'
|
||||
import { searchForPlayers } from '../graphql/queries/searchForPlayers'
|
||||
|
||||
const XSearchResults = withRouter(({ history, name, exact }) => {
|
||||
const result = useQuery(searchForPlayers, {variables: { name, exact }})
|
||||
|
||||
if (result.loading) {
|
||||
return <div style={{"paddingTop": "25px", "paddingBottom": "20000px"}} ><Loader active inline='centered' /></div>
|
||||
}
|
||||
if (result.error) {
|
||||
return <div style={{"color": "red"}}>{result.error.message}</div>
|
||||
}
|
||||
const searchResult = result.data['searchForPlayers']
|
||||
if (searchResult.length === 0) {
|
||||
return <Message
|
||||
error
|
||||
header='Your search matches 0 players who reached Top 500'
|
||||
list={[
|
||||
'You can\'t search for a player that has never finished in the Top 500',
|
||||
'Be careful about special characters: ρ is not the same as p for example',
|
||||
]}
|
||||
/>
|
||||
}
|
||||
return (
|
||||
<div style={{"paddingTop": "10px"}}>
|
||||
<Header>Search results</Header>
|
||||
{searchResult.length > 20 ? <Message info header='Your search returned over 20 players' content="Below are the twenty players with the highest power that match your criteria" /> : null}
|
||||
<Grid columns={3}>
|
||||
{searchResult.map(r => {
|
||||
return (
|
||||
<Grid.Row key={r.unique_id}>
|
||||
<Grid.Column>
|
||||
{r.name} ({r.x_power} with {r.weapon})
|
||||
</Grid.Column>
|
||||
<Grid.Column>
|
||||
<Button
|
||||
positive
|
||||
onClick={() => history.push(`/xsearch/p/${r.unique_id}`)}
|
||||
>Go!</Button>
|
||||
</Grid.Column>
|
||||
<Grid.Column></Grid.Column>
|
||||
</Grid.Row>
|
||||
)
|
||||
})}
|
||||
</Grid>
|
||||
</div>
|
||||
)
|
||||
|
||||
})
|
||||
|
||||
export default XSearchResults
|
||||
12
react-ui/src/graphql/queries/searchForPlayers.js
vendored
Normal file
12
react-ui/src/graphql/queries/searchForPlayers.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { gql } from 'apollo-boost'
|
||||
|
||||
export const searchForPlayers = gql`
|
||||
query searchForPlayers($name: String!, $exact: Boolean) {
|
||||
searchForPlayers(name: $name, exact: $exact) {
|
||||
name
|
||||
x_power
|
||||
weapon
|
||||
unique_id
|
||||
}
|
||||
}
|
||||
`
|
||||
Reference in New Issue
Block a user