charity-base-search
Version:
React component for CharityBase search input
225 lines (196 loc) • 6.96 kB
JavaScript
'use strict';
exports.__esModule = true;
exports.TextField = exports.Input = exports.HelperText = undefined;
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _lodash = require('lodash.debounce');
var _lodash2 = _interopRequireDefault(_lodash);
var _filterSuggest = require('filter-suggest');
var _filterSuggest2 = _interopRequireDefault(_filterSuggest);
var _search = require('./search.svg');
var _search2 = _interopRequireDefault(_search);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var DEBOUNCE_TIME = 100;
var applyDebounced = (0, _lodash2.default)(function (f, x) {
return f(x);
}, DEBOUNCE_TIME);
var QUERY = '\n query CBS_SEARCH_FILTERS(\n $search: String!\n $filterType: [String]\n ) {\n CHC {\n getFilters(\n search: $search\n filterType: $filterType\n ) {\n id\n value\n label\n filterType\n score\n }\n }\n }\n';
var getData = function getData(apiUrl, apiKey, variables) {
return fetch(apiUrl + '?query=' + QUERY + '&variables=' + JSON.stringify(variables), {
headers: {
Authorization: 'Apikey ' + apiKey
}
}).then(function (x) {
return x.json();
});
};
var getSearchItem = function getSearchItem(inputValue) {
return {
id: 'search-' + inputValue,
value: inputValue,
label: inputValue,
filterType: 'search'
};
};
var errorMessage = function errorMessage(_ref) {
var error = _ref.error,
empty = _ref.empty,
loading = _ref.loading,
searchTerm = _ref.searchTerm;
if (error) {
return 'Oops something went wrong, please try again';
}
if (empty && searchTerm.length > 1 && !loading) {
return 'Sorry we can\'t find anything matching \'' + searchTerm + '\'';
}
return null;
};
var CharityBaseSearch = function CharityBaseSearch(_ref2) {
var apiKey = _ref2.apiKey,
apiUrl = _ref2.apiUrl,
className = _ref2.className,
filterTypes = _ref2.filterTypes,
hideAcknowledgement = _ref2.hideAcknowledgement,
label = _ref2.label,
mapItem = _ref2.mapItem,
menuClassName = _ref2.menuClassName,
onBlur = _ref2.onBlur,
onFocus = _ref2.onFocus,
_onSelect = _ref2.onSelect,
outlined = _ref2.outlined,
style = _ref2.style,
textFieldClassName = _ref2.textFieldClassName;
var _useState = (0, _react.useState)(''),
inputValue = _useState[0],
setInputValue = _useState[1];
var _useState2 = (0, _react.useState)(''),
debouncedInputValue = _useState2[0],
setDebouncedInputValue = _useState2[1];
var _useState3 = (0, _react.useState)(null),
data = _useState3[0],
setData = _useState3[1];
var _useState4 = (0, _react.useState)(null),
error = _useState4[0],
setError = _useState4[1];
var _useState5 = (0, _react.useState)(false),
loading = _useState5[0],
setLoading = _useState5[1];
var onInputValueChange = function onInputValueChange(x) {
var value = x || '';
setInputValue(value);
applyDebounced(setDebouncedInputValue, value.trim());
};
(0, _react.useEffect)(function () {
var ignore = false;
if (debouncedInputValue) {
var variables = { search: debouncedInputValue, filterType: filterTypes };
setLoading(true);
getData(apiUrl, apiKey, variables).then(function (_ref3) {
var data = _ref3.data,
errors = _ref3.errors;
if (ignore) return;
if (errors) {
// setData(null)
return setError(errors[0].message); // graphql error
}
setError(null);
setData(data);
}).catch(function (error) {
if (ignore) return;
// setData(null)
setError(error && error.message || 'Unknown error'); // probably network error
}).then(function () {
if (ignore) return;
setLoading(false);
});
} else {
setError(null);
setData(null);
}
return function () {
ignore = true;
};
}, [apiUrl, apiKey, debouncedInputValue, JSON.stringify(filterTypes)]);
var syncItems = [getSearchItem(inputValue)].reduce(function (agg, x) {
return filterTypes && filterTypes.indexOf(x.filterType) === -1 ? agg : [].concat(agg, [x]);
}, []);
var filterItems = data && data.CHC ? [].concat(syncItems, data.CHC.getFilters) : [];
return _react2.default.createElement(
'div',
{ className: className, style: style },
hideAcknowledgement ? null : _react2.default.createElement(
'a',
{
className: 'cbs-acknowledgement',
href: 'https://charitybase.uk',
target: '_blank',
rel: 'noopener noreferrer'
},
'Powered by CharityBase'
),
_react2.default.createElement(_filterSuggest2.default, {
errorMessage: errorMessage({
error: error,
loading: loading,
empty: filterItems.length === 0,
searchTerm: debouncedInputValue
}),
inputValue: inputValue,
items: filterItems.map(mapItem),
label: label,
leadingIcon: _react2.default.createElement('img', { width: 24, height: 24, src: _search2.default }),
loading: loading,
menuClassName: menuClassName,
onBlur: onBlur,
onFocus: onFocus,
onInputValueChange: onInputValueChange,
onSelect: function onSelect(item) {
onInputValueChange('');
_onSelect(item);
},
outlined: outlined,
textFieldClassName: textFieldClassName
})
);
};
CharityBaseSearch.propTypes = process.env.NODE_ENV !== "production" ? {
apiKey: _propTypes2.default.string.isRequired,
apiUrl: _propTypes2.default.string,
className: _propTypes2.default.string,
filterTypes: _propTypes2.default.array,
hideAcknowledgement: _propTypes2.default.bool,
label: _propTypes2.default.string,
mapItem: _propTypes2.default.func,
menuClassName: _propTypes2.default.string,
onBlur: _propTypes2.default.func,
onFocus: _propTypes2.default.func,
onSelect: _propTypes2.default.func.isRequired,
outlined: _propTypes2.default.bool,
style: _propTypes2.default.object,
textFieldClassName: _propTypes2.default.string
} : {};
CharityBaseSearch.defaultProps = {
apiUrl: 'https://charitybase.uk/api/graphql',
label: 'Search charities',
mapItem: function mapItem(_ref4) {
var id = _ref4.id,
filterType = _ref4.filterType,
value = _ref4.value,
label = _ref4.label;
return { // __typename ?
id: id,
filterType: filterType,
value: value,
label: label,
icon: null,
primary: label,
secondary: 'Filter by ' + filterType
};
}
};
exports.default = CharityBaseSearch;
exports.HelperText = _filterSuggest.HelperText;
exports.Input = _filterSuggest.Input;
exports.TextField = _filterSuggest.TextField;