-
Notifications
You must be signed in to change notification settings - Fork 81
/
index.tsx
85 lines (77 loc) · 2.99 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import debounce from 'lodash-es/debounce';
import { StaticFilterDefinitions } from 'types/filters';
import {
SearchAutosuggestProps,
SearchSuggestion,
SearchSuggestionSection,
} from 'types/Suggestion';
import { handle } from 'utils/errors/handle';
import { HttpStatusCode } from 'utils/errors/HttpError';
import { getSuggestionsSection } from './getSuggestionsSection';
/**
* `react-autosuggest` callback to get a human string value from a Suggestion object.
* @param suggestion The relevant suggestion object.
*/
export const getSuggestionValue: SearchAutosuggestProps['getSuggestionValue'] = (suggestion) =>
suggestion.title;
/**
* `react-autosuggest` callback to render one suggestion.
* @param suggestion Either a resource suggestion with a model name & a machine name, or the default
* suggestion with some text to render.
*/
export const renderSuggestion: SearchAutosuggestProps['renderSuggestion'] = (suggestion) => (
<span>{suggestion.title}</span>
);
/**
* `react-autosuggest` callback to build up the list of suggestions and sections whenever user
* interaction requires us to create or update that list.
* @param filters The general filters object as returned by the API on a course search.
* @param setSuggestions The suggestion setter method for the component using our helper.
* @param incomingValue The current value of the search suggest form field.
*/
const onSuggestionsFetchRequested = async (
filters: StaticFilterDefinitions,
setSuggestions: (suggestions: SearchSuggestionSection[]) => void,
incomingValue: string,
) => {
if (incomingValue.length < 3) {
return setSuggestions([]);
}
// Fetch the suggestions for each resource-based section to build out the sections
let sections: SearchSuggestionSection[];
try {
sections = (await Promise.all(
Object.values(await filters)
.filter((filterdef) => filterdef.is_autocompletable)
.map((filterdef) =>
getSuggestionsSection(filterdef.name, filterdef.human_name, incomingValue),
),
// We can assert this because of the catch below
)) as SearchSuggestionSection[];
} catch (error) {
return handle(error);
}
setSuggestions(
// Drop sections with no results as there's no use displaying them
sections.filter((section) => !!section!.values.length),
);
};
export const onSuggestionsFetchRequestedDebounced = debounce(
onSuggestionsFetchRequested,
HttpStatusCode.OK,
{
maxWait: 1000,
},
);
/**
* Helper to pick out the relevant filter for a suggestion from the general filters object.
* @param filters The general filters object as returned by the API on a course search.
* @param suggestion The suggestion with which we're doing some work (eg. the suggestion the user selected).
*/
export const getRelevantFilter = (
filters: StaticFilterDefinitions,
suggestion: SearchSuggestion,
) => {
// Use the `kind` field on the suggestion to pick the relevant filter to update.
return Object.values(filters).find((fltr) => fltr.name === suggestion.kind)!;
};