import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { Highlight, connectAutoComplete } from 'react-instantsearch-dom'; import AutoSuggest from 'react-autosuggest'; import './AutoComplete.css' class Autocomplete extends Component { static propTypes = { hits: PropTypes.arrayOf(PropTypes.object).isRequired, currentRefinement: PropTypes.string.isRequired, refine: PropTypes.func.isRequired, onSuggestionSelected: PropTypes.func.isRequired, onSuggestionCleared: PropTypes.func.isRequired, }; state = { value: this.props.currentRefinement, }; isSuggestionHasCategories(suggestion) { return ( suggestion.instant_search && suggestion.instant_search.facets && suggestion.instant_search.facets.exact_matches && suggestion.instant_search.facets.exact_matches.categories && suggestion.instant_search.facets.exact_matches.categories.length ); } normalizeSuggestionCategories(suggestions) { return suggestions.map(suggestion => { const context = suggestion.instant_search || {}; const facets = context.facets || {}; const matches = facets.exact_matches || {}; const categories = matches.categories || []; return { ...suggestion, // eslint-disable-next-line instant_search: { ...context, facets: { ...facets, // eslint-disable-next-line exact_matches: { ...matches, categories, }, }, }, }; }); } createMostRelevantSuggestionForAllCategories(suggestion) { return { ...suggestion, // eslint-disable-next-line instant_search: { ...suggestion.instant_search, facets: { ...suggestion.instant_search.facets, // eslint-disable-next-line exact_matches: { ...suggestion.instant_search.facets.exact_matches, categories: [{ value: 'ALL_CATEGORIES' }], }, }, }, }; } onChange = (_, { newValue }) => { if (!newValue) { this.props.onSuggestionCleared(); } this.setState({ value: newValue, }); }; onSuggestionsFetchRequested = ({ value }) => { this.props.refine(value); }; onSuggestionsClearRequested = () => { this.props.refine(); }; getSuggestionValue(hit) { return hit.query; } renderSuggestion(hit) { const [category] = hit.instant_search.facets.exact_matches.categories; return ( <span> <Highlight attribute="query" hit={hit} tagName="mark" /> {category && ( <i> {' '} in{' '} {category.value === 'ALL_CATEGORIES' ? 'All categories' : category.value} </i> )} </span> ); } render() { const { hits, onSuggestionSelected } = this.props; const { value } = this.state; const inputProps = { placeholder: 'Search here...', onChange: this.onChange, class: 'ais-SearchBox-input', value, }; const suggestions = this.normalizeSuggestionCategories(hits); const suggestionsWithAllCategories = suggestions[0] && this.isSuggestionHasCategories(suggestions[0]) ? [this.createMostRelevantSuggestionForAllCategories(suggestions[0])] : []; return ( <AutoSuggest suggestions={[...suggestionsWithAllCategories, ...suggestions]} onSuggestionsFetchRequested={this.onSuggestionsFetchRequested} onSuggestionsClearRequested={this.onSuggestionsClearRequested} onSuggestionSelected={onSuggestionSelected} getSuggestionValue={this.getSuggestionValue} renderSuggestion={this.renderSuggestion} inputProps={inputProps} /> ); } } export default connectAutoComplete(Autocomplete);