instantjob-recruiter-client
Version:
a set of tools for creating an instantjob recruiter react client
145 lines (130 loc) • 3.62 kB
JSX
import React, {Component} from 'react'
import classNames from 'classnames/bind'
import {MdSearch} from 'react-icons/lib/md'
import styled from 'styled-components'
import {tolerant_equal} from 'selectors/base'
import {cancelable_timeout} from 'common/cancelable'
import {color, input} from 'common/styles'
import auto_bind from 'common/auto_bind'
export default class SearchBar extends Component {
constructor(props) {
super(props)
this.state = {
query: "",
results: [],
}
auto_bind(this)
this.fuse = this.props.make_fuse()
}
static defaultProps = {
on_query_change: () => {},
simple: false,
extend: true,
placeholder: "Recherche",
make_fuse: () => null,
items: [],
default_results: [],
onFocus: () => null,
onBlur: () => null,
}
set_items(items) {
this.fuse.set(items)
}
set_query(query = "") {
if (this.mounted) {
this.set_should_verify_results()
this.setState((state) => ({...state, query}))
}
}
verify_results() {
const {query} = this.state
const {default_results, on_query_change} = this.props
const results = query == "" ? default_results : this.fuse.search(query)
const results_changed = !tolerant_equal(results, this.previous.results)
if (!tolerant_equal(query, this.previous.query) || results_changed) {
if (results_changed) {
this.setState({results})
}
on_query_change(query, results)
}
}
componentDidUpdate() {
if (this.should_verify_results) {
this.verify_results()
this.should_verify_results = false
}
}
componentDidMount() {
this.mounted = true
this.set_items(this.props.items)
this.previous = {query: ''}
this.verify_results()
}
set_should_verify_results() {
this.previous = {...this.state}
this.should_verify_results = true
}
componentWillReceiveProps(props) {
const {items, default_results} = this.props
if (!tolerant_equal(props.items, items)) {
this.set_items(props.items)
this.set_should_verify_results()
}
if (!tolerant_equal(props.default_results, default_results) && this.state.query == "") {
this.set_should_verify_results()
}
}
shouldComponentUpdate(props, state) {
return state !== this.state ||
!tolerant_equal(props.items, this.props.items) ||
!tolerant_equal(props.default_results, this.props.default_results) ||
props.className !== this.props.className ||
props.placeholder !== this.props.placeholder
}
componentWillUnmount() {
this.mounted = false
}
focus() {
this.input.focus()
}
render() {
const {className} = this.props
return (
<Container className={className}>
<Icon>
<MdSearch />
</Icon>
<Input
innerRef={(input) => this.input = input}
type="text"
placeholder={this.props.placeholder}
value={this.state.query}
onChange={({target: {value: query}}) => this.set_query(query)}
onFocus={(event) => {
if (this.state.query != "") {
let input = event.target
setTimeout(() => input.select(), 100)
}
this.props.onFocus()
}}
onBlur={this.props.onBlur}
/>
</Container>
)
}
}
const Container = styled.div`
display: flex;
align-items: center;
border-bottom: solid 2px ${color('black', 'pale')};
`
const Icon = styled.div`
color: ${color('black', 'bright')};
font-size: 20px;
padding: 5px;
flex-shrink: 0;
`
const Input = styled.input`
${input}
flex: 1;
`