redoc/src/components/SearchBox/SearchBox.tsx

121 lines
2.6 KiB
TypeScript
Raw Normal View History

2018-02-08 19:41:02 +03:00
import * as React from 'react';
import { IMenuItem } from '../../services/MenuStore';
import { SearchStore } from '../../services/SearchStore';
import { MenuItem } from '../SideMenu/MenuItem';
2018-02-22 12:36:03 +03:00
2018-02-22 12:26:53 +03:00
import { MarkerService } from '../../services/MarkerService';
import { SearchDocument } from '../../services/SearchWorker.worker';
2018-02-08 19:41:02 +03:00
import { ClearIcon, SearchIcon, SearchInput, SearchResultsBox, SearchWrap } from './elements';
2018-02-08 19:41:02 +03:00
export interface SearchBoxProps {
search: SearchStore;
2018-02-22 12:26:53 +03:00
marker: MarkerService;
2018-02-08 19:41:02 +03:00
getItemById: (id: string) => IMenuItem | undefined;
onActivate: (item: IMenuItem) => void;
2018-02-22 19:48:50 +03:00
className?: string;
2018-02-08 19:41:02 +03:00
}
export interface SearchBoxState {
results: any;
term: string;
}
2018-02-22 19:48:50 +03:00
interface SearchResult {
item: IMenuItem;
score: number;
}
2018-02-08 19:41:02 +03:00
export class SearchBox extends React.PureComponent<SearchBoxProps, SearchBoxState> {
constructor(props) {
super(props);
this.state = {
results: [],
term: '',
};
}
2018-02-22 12:26:53 +03:00
clearResults(term: string) {
this.setState({
results: [],
term,
});
this.props.marker.unmark();
}
2018-02-22 12:36:03 +03:00
clear = () => {
2018-02-22 12:26:53 +03:00
this.setState({
results: [],
term: '',
});
this.props.marker.unmark();
2018-02-22 12:36:03 +03:00
};
2018-02-22 12:26:53 +03:00
clearIfEsq = event => {
if (event && event.keyCode === 27) {
this.clear();
}
};
setResults(results: SearchDocument[], term: string) {
this.setState({
results,
term,
});
this.props.marker.mark(term);
}
2018-02-08 19:41:02 +03:00
search = (event: React.ChangeEvent<HTMLInputElement>) => {
const q = event.target.value;
if (q.length < 3) {
2018-02-22 12:26:53 +03:00
this.clearResults(q);
2018-02-08 19:41:02 +03:00
return;
}
2018-02-22 12:26:53 +03:00
2018-02-08 19:41:02 +03:00
this.setState({
term: q,
});
this.props.search.search(event.target.value).then(res => {
2018-02-22 12:26:53 +03:00
this.setResults(res, q);
2018-02-08 19:41:02 +03:00
});
};
render() {
2018-02-22 19:48:50 +03:00
const results: SearchResult[] = this.state.results.map(res => ({
item: this.props.getItemById(res.id),
score: res.score,
}));
results.sort((a, b) => b.score - a.score);
2018-02-08 19:41:02 +03:00
return (
<SearchWrap>
2018-02-22 12:36:03 +03:00
{this.state.term && <ClearIcon onClick={this.clear}>×</ClearIcon>}
2018-02-08 19:41:02 +03:00
<SearchIcon />
<SearchInput
value={this.state.term}
onKeyDown={this.clearIfEsq}
placeholder="Search..."
type="text"
onChange={this.search}
/>
2018-02-22 19:48:50 +03:00
{results.length > 0 && (
2018-02-08 19:41:02 +03:00
<SearchResultsBox>
2018-02-22 19:48:50 +03:00
{results.map(res => (
2018-02-08 19:41:02 +03:00
<MenuItem
2018-02-22 19:48:50 +03:00
item={res.item}
2018-02-08 19:41:02 +03:00
onActivate={this.props.onActivate}
withoutChildren={true}
2018-02-22 19:48:50 +03:00
key={res.item.id}
2018-02-08 19:41:02 +03:00
/>
))}
</SearchResultsBox>
)}
</SearchWrap>
2018-02-08 19:41:02 +03:00
);
}
}