Fix SearchModal and add WeaponResult
This commit is contained in:
parent
94cb909700
commit
a8672c8b72
5 changed files with 265 additions and 41 deletions
|
|
@ -1,10 +1,9 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { v1 as uuidv1 } from 'uuid'
|
|
||||||
|
|
||||||
import Portal from '../../Portal'
|
import Portal from '../../Portal'
|
||||||
|
|
||||||
import Modal from '../Modal/Modal'
|
import Modal from '../Modal/Modal'
|
||||||
import Overlay from '../Overlay/Overlay'
|
import Overlay from '../Overlay/Overlay'
|
||||||
|
import WeaponResult from '../WeaponResult/WeaponResult'
|
||||||
|
|
||||||
import './SearchModal.css'
|
import './SearchModal.css'
|
||||||
|
|
||||||
|
|
@ -16,8 +15,9 @@ interface Props {
|
||||||
interface State {
|
interface State {
|
||||||
query: string,
|
query: string,
|
||||||
results: { [key: string]: any }
|
results: { [key: string]: any }
|
||||||
isLoaded: boolean
|
loading: boolean
|
||||||
message: string
|
message: string
|
||||||
|
totalResults: number
|
||||||
}
|
}
|
||||||
|
|
||||||
class SearchModal extends React.Component<Props, State> {
|
class SearchModal extends React.Component<Props, State> {
|
||||||
|
|
@ -28,62 +28,78 @@ class SearchModal extends React.Component<Props, State> {
|
||||||
this.state = {
|
this.state = {
|
||||||
query: '',
|
query: '',
|
||||||
results: {},
|
results: {},
|
||||||
isLoaded: false,
|
loading: false,
|
||||||
message: ''
|
message: '',
|
||||||
}
|
totalResults: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchResults = (query) => {
|
fetchResults = (query) => {
|
||||||
fetch(`http://127.0.0.1:3000/api/v1/search?query=${query}`)
|
fetch(`http://grid-api.ngrok.io/api/v1/search?query=${query}`)
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
// console.log("hello world!")
|
const totalResults = result.length
|
||||||
console.log(result)
|
this.setState({
|
||||||
// this.setState({
|
results: result,
|
||||||
// isLoaded: true,
|
totalResults: totalResults,
|
||||||
// results: result
|
loading: false
|
||||||
// })
|
})
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
// this.setState({
|
this.setState({
|
||||||
// isLoaded: true,
|
loading: false,
|
||||||
// message: error
|
message: error
|
||||||
// })
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
inputChanged = (event) => {
|
inputChanged = (event) => {
|
||||||
const query = this.searchQuery.value
|
const query = event.target.value
|
||||||
if (query.length > 2) {
|
if (query.length) {
|
||||||
console.log(query)
|
this.setState({ query, loading: true, message: '' }, () => {
|
||||||
this.fetchResults(query)
|
this.fetchResults(query)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setState({ query, results: {}, message: '' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSearchResults = () => {
|
||||||
|
const { results } = this.state
|
||||||
|
|
||||||
|
if (results.length) {
|
||||||
|
return (
|
||||||
|
<div id="results_container">
|
||||||
|
{ results.map( result => {
|
||||||
|
return <WeaponResult key={result.id} data={result} />
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (query) {
|
|
||||||
// this.setState({ query, isLoaded: true, message: '' }, () => {
|
|
||||||
// // this.fetchResults(query)
|
|
||||||
// })
|
|
||||||
// } else {
|
|
||||||
// this.setState({ query, results: {}, message: '' })
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { query, isLoaded, message } = this.state
|
const { query, loading } = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Portal key="search_portal">
|
<Portal key="search_portal">
|
||||||
<Modal styleName="SearchModal" key="search_modal">
|
<Modal styleName="SearchModal" key="search_modal">
|
||||||
<input
|
<div id="input_container">
|
||||||
className="Input"
|
<label className="search_label" htmlFor="search_input">
|
||||||
defaultValue={query}
|
<input
|
||||||
id="SearchInput"
|
autoComplete="off"
|
||||||
name="query"
|
type="text"
|
||||||
key="search_input_key"
|
name="query"
|
||||||
type="text"
|
className="Input"
|
||||||
ref={el => this.searchQuery = el}
|
id="search_input"
|
||||||
onChange={this.inputChanged}
|
value={query}
|
||||||
placeholder={this.props.placeholderText}
|
placeholder={this.props.placeholderText}
|
||||||
/>
|
onChange={this.inputChanged}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{ this.renderSearchResults() }
|
||||||
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<Overlay onClick={this.props.close} />
|
<Overlay onClick={this.props.close} />
|
||||||
</Portal>
|
</Portal>
|
||||||
|
|
|
||||||
79
src/components/WeaponLabelIcon/WeaponLabelIcon.css
Normal file
79
src/components/WeaponLabelIcon/WeaponLabelIcon.css
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
.WeaponLabelIcon {
|
||||||
|
display: inline-block;
|
||||||
|
background-size: 60px 25px;
|
||||||
|
height: 25px;
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Elements */
|
||||||
|
|
||||||
|
.fire {
|
||||||
|
background-image: url('../../images/labels/element/Label_Element_Fire.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.water {
|
||||||
|
background-image: url('../../images/labels/element/Label_Element_Water.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.earth {
|
||||||
|
background-image: url('../../images/labels/element/Label_Element_Earth.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.wind {
|
||||||
|
background-image: url('../../images/labels/element/Label_Element_Wind.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
background-image: url('../../images/labels/element/Label_Element_Dark.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.light {
|
||||||
|
background-image: url('../../images/labels/element/Label_Element_Light.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.null {
|
||||||
|
background-image: url('../../images/labels/element/Label_Element_Any.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Proficiencies */
|
||||||
|
|
||||||
|
.sword {
|
||||||
|
background-image: url('../../images/labels/proficiency/Label_Weapon_Sabre.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.dagger {
|
||||||
|
background-image: url('../../images/labels/proficiency/Label_Weapon_Dagger.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.axe {
|
||||||
|
background-image: url('../../images/labels/proficiency/Label_Weapon_Axe.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.spear {
|
||||||
|
background-image: url('../../images/labels/proficiency/Label_Weapon_Spear.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.staff {
|
||||||
|
background-image: url('../../images/labels/proficiency/Label_Weapon_Staff.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.fist {
|
||||||
|
background-image: url('../../images/labels/proficiency/Label_Weapon_Melee.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.harp {
|
||||||
|
background-image: url('../../images/labels/proficiency/Label_Weapon_Harp.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.gun {
|
||||||
|
background-image: url('../../images/labels/proficiency/Label_Weapon_Gun.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.bow {
|
||||||
|
background-image: url('../../images/labels/proficiency/Label_Weapon_Bow.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
.katana {
|
||||||
|
background-image: url('../../images/labels/proficiency/Label_Weapon_Katana.png')
|
||||||
|
}
|
||||||
|
|
||||||
16
src/components/WeaponLabelIcon/WeaponLabelIcon.tsx
Normal file
16
src/components/WeaponLabelIcon/WeaponLabelIcon.tsx
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
import React from 'react'
|
||||||
|
import './WeaponLabelIcon.css'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
labelType: string
|
||||||
|
}
|
||||||
|
|
||||||
|
class WeaponLabelIcon extends React.Component<Props> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<i className={`WeaponLabelIcon ${this.props.labelType}`} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WeaponLabelIcon
|
||||||
48
src/components/WeaponResult/WeaponResult.css
Normal file
48
src/components/WeaponResult/WeaponResult.css
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
.WeaponResult {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
|
||||||
|
border-radius: 6px;
|
||||||
|
display: flex;
|
||||||
|
font-family: -apple-system, "Helvetica Neue", "Lucida Grande";
|
||||||
|
gap: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WeaponResult img {
|
||||||
|
background: #e9e9e9;
|
||||||
|
border-radius: 6px;
|
||||||
|
display: inline-block;
|
||||||
|
height: 72px;
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WeaponResult h5 {
|
||||||
|
color: #555;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin: 2px 4px 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WeaponResult .WeaponLabelIcon {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WeaponResult .stars {
|
||||||
|
display: inline-block;
|
||||||
|
color: #FFA15E;
|
||||||
|
font-size: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WeaponResult .stars > span {
|
||||||
|
color: #65DAFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WeaponResult:hover {
|
||||||
|
background: #e9e9e9;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.WeaponResult:hover .image_placeholder {
|
||||||
|
background: #dadada;
|
||||||
|
}
|
||||||
65
src/components/WeaponResult/WeaponResult.tsx
Normal file
65
src/components/WeaponResult/WeaponResult.tsx
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
import React from 'react'
|
||||||
|
import './WeaponResult.css'
|
||||||
|
|
||||||
|
import '../WeaponLabelIcon/WeaponLabelIcon'
|
||||||
|
import WeaponLabelIcon from '../WeaponLabelIcon/WeaponLabelIcon'
|
||||||
|
|
||||||
|
import gridImages from '../../images/grid/*.jpg'
|
||||||
|
|
||||||
|
interface Weapon {
|
||||||
|
id: string
|
||||||
|
granblue_id: number
|
||||||
|
element: number
|
||||||
|
proficiency: number
|
||||||
|
max_level: number
|
||||||
|
max_skill_level: number
|
||||||
|
name: {
|
||||||
|
en: string
|
||||||
|
jp: string
|
||||||
|
}
|
||||||
|
hp: {
|
||||||
|
min_hp: number
|
||||||
|
max_hp: number
|
||||||
|
max_hp_flb: number
|
||||||
|
max_hp_ulb: number
|
||||||
|
}
|
||||||
|
atk: {
|
||||||
|
min_atk: number
|
||||||
|
max_atk: number
|
||||||
|
max_atk_flb: number
|
||||||
|
max_atk_ulb: number
|
||||||
|
}
|
||||||
|
uncap: {
|
||||||
|
flb: boolean
|
||||||
|
ulb: boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data: Weapon
|
||||||
|
}
|
||||||
|
|
||||||
|
const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||||
|
const Proficiency = ['none', 'sword', 'dagger', 'axe', 'spear', 'bow', 'staff', 'fist', 'harp', 'gun', 'katana']
|
||||||
|
|
||||||
|
|
||||||
|
class WeaponResult extends React.Component<Props> {
|
||||||
|
render() {
|
||||||
|
const weapon = this.props.data
|
||||||
|
return (
|
||||||
|
<div className="WeaponResult">
|
||||||
|
<img alt={weapon.name.en} src={gridImages[weapon.granblue_id]} />
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<h5>{weapon.name.en}</h5>
|
||||||
|
<div className="stars">⭑⭑⭑{(weapon.uncap.flb) ? <span>⭑</span> : ''}{(weapon.uncap.ulb) ? <span>⭑</span> : ''}</div>
|
||||||
|
</div>
|
||||||
|
<WeaponLabelIcon labelType={Element[weapon.element]} />
|
||||||
|
<WeaponLabelIcon labelType={Proficiency[weapon.proficiency]} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WeaponResult
|
||||||
Loading…
Reference in a new issue