@@ -6,9 +6,45 @@ import TextField from '@material-ui/core/TextField';
66import CloseIcon from '@material-ui/icons/Close' ;
77import SearchIcon from '@material-ui/icons/Search' ;
88import Downshift from 'downshift' ;
9- import React from 'react' ;
9+ import _isNil from 'ramda/src/isNil' ;
10+ import React , { useState } from 'react' ;
11+ import { useDispatch , useSelector } from 'react-redux' ;
12+ import { useHistory } from 'react-router-dom' ;
13+ import { autocompleteRequested } from '../../redux/autocomplete/actionCreators' ;
14+ import { State } from '../../redux/rootReducer' ;
15+ import Course from '../../types/items/Course' ;
16+ import User from '../../types/items/User' ;
1017import useStyles from './styles' ;
1118
19+ export interface GetFormattedResultsOptions {
20+ readonly courses : Course [ ] ;
21+ readonly users : User [ ] ;
22+ }
23+
24+ const getFormattedResults = ( {
25+ courses,
26+ users,
27+ } : GetFormattedResultsOptions ) => {
28+ const updatedCourses = courses
29+ . map ( ( course : Course ) => ( {
30+ ...course ,
31+ label : course . title ,
32+ type : 'course' ,
33+ } ) )
34+ . slice ( 0 , 4 ) ;
35+ const updatedUsers = users
36+ . map ( ( user : User ) => ( {
37+ ...user ,
38+ label : [ user . firstName , user . lastName ] . every ( Boolean )
39+ ? `${ user . firstName } ${ user . lastName } `
40+ : user . email ,
41+ type : 'user' ,
42+ } ) )
43+ . slice ( 0 , 2 ) ;
44+
45+ return [ ...updatedCourses , ...updatedUsers ] ;
46+ } ;
47+
1248function renderInput ( inputProps : any ) {
1349 const { InputProps, classes, ref, ...other } = inputProps ;
1450
@@ -56,12 +92,47 @@ function renderSuggestion(suggestionProps: any) {
5692
5793let popperNode : any ;
5894
59- const Autocomplete = ( { value , onChange , suggestions } : any ) => {
95+ const Autocomplete = ( ) => {
6096 const classes = useStyles ( ) ;
6197
98+ const [ value , setValue ] = useState ( '' ) ;
99+ const history = useHistory ( ) ;
100+ const { courses, users } = useSelector ( ( state : State ) => state . autocomplete ) ;
101+
102+ const dispatch = useDispatch ( ) ;
103+ const results = getFormattedResults ( { courses, users } ) ;
104+
105+ const handleChange = ( changes : any ) => {
106+ // TODO: abstract this operations
107+ if (
108+ changes . hasOwnProperty ( 'selectedItem' ) &&
109+ ! _isNil ( changes . selectedItem )
110+ ) {
111+ setValue ( changes . selectedItem ) ;
112+
113+ const item : any = results . filter (
114+ result => result . label === changes . selectedItem
115+ ) [ 0 ] ;
116+
117+ const link =
118+ item . type === 'course'
119+ ? `/courses/${ item . slug } `
120+ : `/instructors/${ item . email } ` ;
121+
122+ history . push ( link ) ;
123+ } else if ( changes . hasOwnProperty ( 'inputValue' ) ) {
124+ setValue ( changes . inputValue ) ;
125+ dispatch ( autocompleteRequested ( changes . inputValue ) ) ;
126+ }
127+ } ;
128+
62129 return (
63130 < div className = { classes . root } >
64- < Downshift id = "downshift-popper" selectedItem = { value } onStateChange = { onChange } >
131+ < Downshift
132+ id = "downshift-popper"
133+ selectedItem = { value }
134+ onStateChange = { handleChange }
135+ >
65136 { ( {
66137 clearSelection,
67138 getInputProps,
@@ -109,15 +180,14 @@ const Autocomplete = ({value, onChange, suggestions}: any) => {
109180 width : popperNode ? popperNode . clientWidth : undefined ,
110181 } }
111182 >
112- { suggestions . map (
113- ( suggestion : any , index : number ) =>
114- renderSuggestion ( {
115- highlightedIndex,
116- index,
117- itemProps : getItemProps ( { item : suggestion . label } ) ,
118- selectedItem,
119- suggestion,
120- } )
183+ { results . map ( ( suggestion : any , index : number ) =>
184+ renderSuggestion ( {
185+ highlightedIndex,
186+ index,
187+ itemProps : getItemProps ( { item : suggestion . label } ) ,
188+ selectedItem,
189+ suggestion,
190+ } )
121191 ) }
122192 </ Paper >
123193 </ div >
0 commit comments