Fix SearchModal and add WeaponResult

This commit is contained in:
Justin Edmund 2020-09-15 01:24:36 -07:00
parent 94cb909700
commit a8672c8b72
5 changed files with 265 additions and 41 deletions

View file

@ -1,10 +1,9 @@
import React from 'react'
import { v1 as uuidv1 } from 'uuid'
import Portal from '../../Portal'
import Modal from '../Modal/Modal'
import Overlay from '../Overlay/Overlay'
import WeaponResult from '../WeaponResult/WeaponResult'
import './SearchModal.css'
@ -16,8 +15,9 @@ interface Props {
interface State {
query: string,
results: { [key: string]: any }
isLoaded: boolean
loading: boolean
message: string
totalResults: number
}
class SearchModal extends React.Component<Props, State> {
@ -28,62 +28,78 @@ class SearchModal extends React.Component<Props, State> {
this.state = {
query: '',
results: {},
isLoaded: false,
message: ''
}
loading: false,
message: '',
totalResults: 0
}
}
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((result) => {
// console.log("hello world!")
console.log(result)
// this.setState({
// isLoaded: true,
// results: result
// })
const totalResults = result.length
this.setState({
results: result,
totalResults: totalResults,
loading: false
})
}, (error) => {
// this.setState({
// isLoaded: true,
// message: error
// })
this.setState({
loading: false,
message: error
})
})
}
inputChanged = (event) => {
const query = this.searchQuery.value
if (query.length > 2) {
console.log(query)
this.fetchResults(query)
const query = event.target.value
if (query.length) {
this.setState({ query, loading: true, message: '' }, () => {
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() {
const { query, isLoaded, message } = this.state
const { query, loading } = this.state
return (
<Portal key="search_portal">
<Modal styleName="SearchModal" key="search_modal">
<input
className="Input"
defaultValue={query}
id="SearchInput"
name="query"
key="search_input_key"
type="text"
ref={el => this.searchQuery = el}
onChange={this.inputChanged}
placeholder={this.props.placeholderText}
/>
<div id="input_container">
<label className="search_label" htmlFor="search_input">
<input
autoComplete="off"
type="text"
name="query"
className="Input"
id="search_input"
value={query}
placeholder={this.props.placeholderText}
onChange={this.inputChanged}
/>
</label>
</div>
{ this.renderSearchResults() }
</Modal>
<Overlay onClick={this.props.close} />
</Portal>

View 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')
}

View 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

View 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;
}

View 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