import { useRef , useState , useEffect , useContext , ReactElement , forwardRef , useImperativeHandle , } from 'react' ; import Router from 'next/router' ; import styled from 'styled-components' ; import TextInput from '../TextInput/TextInput' ; import ButtonSolid from '../ButtonSolid/ButtonSolid' ; import { classNames } from '../../../utils/classnames' ; import { trackEvent } from '../../../utils/ga' ; import SearchFilters from '../SearchFilters/SearchFilters' ; import Select from '../Select/Select' ; import Space from '../styled/Space' ; import SelectUncontrolled from '../SelectUncontrolled/SelectUncontrolled' ; import SearchFormSortByPortal from './SearchFormSortByPortal' ; import ClearSearch from '../ClearSearch/ClearSearch' ; import { AppContext } from '../AppContext/AppContext' ; import { searchFormInputCatalogue , searchFormInputImage , } from '../../../text/aria-labels' ; import { ParsedUrlQuery } from 'querystring' ; import { LinkProps } from '../../../model/link-props' ; import { Filter } from '../../../services/catalogue/filters' ; import { formDataAsUrlQuery } from '../../../utils/forms' ; const SearchInputWrapper = styled . div `
  font-size: 20px;

  .search-query {
    height: ${ props => 10 * props . theme . spacingUnit }px;
  }
` ; const SearchButtonWrapper = styled . div . attrs ( { className : classNames ( { absolute : true , } ) , } ) `
  top: ${ props => props . theme . spacingUnits [ '3' ] + 6 }px;
  right: ${ props => props . theme . spacingUnits [ '5' ] + 6 }px;

  ${ props => props . theme . media . medium `
    top: ${ props . theme . spacingUnits [ '4' ] + 6 }px;
    right: ${ props . theme . spacingUnits [ '6' ] + 6 }px;
  ` }

  ${ props => props . theme . media . large `
    top: ${ props . theme . spacingUnits [ '5' ] + 6 }px;
    right: ${ props . theme . spacingUnits [ '8' ] + 6 }px;
  ` }
` ; const SearchSortOrderWrapper = styled . div `
  color: ${ props => props . theme . color ( 'black' ) };
` ; type Props = { query : string ; sort ? : string ; sortOrder ? : string ; linkResolver : ( params : ParsedUrlQuery ) => LinkProps ; ariaDescribedBy : string ; isImageSearch : boolean ; shouldShowFilters : boolean ; showSortBy : boolean ; filters : Filter [ ] ; } ; const SearchForm = forwardRef ( ( { query , sort , sortOrder , linkResolver , ariaDescribedBy , isImageSearch , shouldShowFilters , showSortBy , filters , } , ref ) : ReactElement < Props > => { const { isEnhanced } = useContext ( AppContext ) ; const searchForm = useRef < HTMLFormElement > ( null ) ; const [ inputQuery , setInputQuery ] = useState ( query ) ; const searchInput = useRef < HTMLInputElement > ( null ) ; const [ forceState , setForceState ] = useState ( false ) ; const [ portalSortOrder , setPortalSortOrder ] = useState ( sortOrder ) ; function submit ( ) { searchForm . current && searchForm . current . dispatchEvent ( new window . Event ( 'submit' , { cancelable : true , bubbles : true } ) ) ; } useImperativeHandle ( ref , ( ) => ( { submit , } ) ) ; useEffect ( ( ) => { const delayTimer = setTimeout ( ( ) => { ! forceState && setForceState ( true ) ; } , 0 ) ; return ( ) => { clearTimeout ( delayTimer ) ; } ; } , [ ] ) ; useEffect ( ( ) => { if ( query !== inputQuery ) { setInputQuery ( query ) ; } } , [ query ] ) ; useEffect ( ( ) => { if ( portalSortOrder !== sortOrder ) { submit ( ) ; } } , [ portalSortOrder ] ) ; function updateUrl ( form ) { const urlQuery = formDataAsUrlQuery ( form ) ; const sort = portalSortOrder === 'asc' || portalSortOrder === 'desc' ? 'production.dates' : undefined ; const link = linkResolver ( { ... urlQuery , sortOrder : portalSortOrder , sort , } ) ; return Router . push ( link . href , link . as ) ; } return ( < form role = "search" ref = { searchForm } className = "relative" action = { isImageSearch ? '/images' : '/works' } aria - describedby = { ariaDescribedBy } onSubmit = { event => { event . preventDefault ( ) ; trackEvent ( { category : 'SearchForm' , action : 'submit search' , label : query , } ) ; updateUrl ( event . currentTarget ) ; return false ; } } > < Space h = { { size : 'l' , properties : [ 'padding-left' , 'padding-right' ] } } v = { { size : 'm' , properties : [ 'padding-top' , 'padding-bottom' ] } } > < SearchInputWrapper className = "relative" > < TextInput id = { `${ isImageSearch ? 'images' : 'works' }-search-input` } label = { isImageSearch ? 'Search for images' : 'Search the catalogue' } name = "query" value = { inputQuery } setValue = { setInputQuery } ref = { searchInput } required = { true } big = { true } placeholder = { '' } ariaLabel = { isImageSearch ? searchFormInputImage : searchFormInputCatalogue } / > { inputQuery && ( < ClearSearch inputRef = { searchInput } setValue = { setInputQuery } gaEvent = { { category : 'SearchForm' , action : 'clear search' , label : 'works-search' , } } right = { 102 } / > ) } < /SearchInputWrapper> < /Space> { shouldShowFilters && ( < SearchFilters query = { query } linkResolver = { linkResolver } searchForm = { searchForm } changeHandler = { submit } filters = { filters } / > ) } { ! isImageSearch && isEnhanced && ( < SearchFormSortByPortal id = "sort-select-portal" > < SearchSortOrderWrapper > < Select name = "portalSortOrder" label = "Sort by:" value = { portalSortOrder || '' } options = { [ { value : '' , text : 'Relevance' , } , { value : 'asc' , text : 'Oldest to newest' , } , { value : 'desc' , text : 'Newest to oldest' , } , ] } onChange = { event => { setPortalSortOrder ( event . currentTarget . value ) ; } } /> < /SearchSortOrderWrapper> < /SearchFormSortByPortal>)} < noscript > { ! isImageSearch && showSortBy && ( < > < Space v = { { size : 's' , properties : [ 'margin-bottom' ] } } > < SelectUncontrolled name = "sort" label = "Sort by" defaultValue = { sort || '' } options = { [ { value : '' , text : 'Relevance' , } , { value : 'production.dates' , text : 'Production dates' , } , ] } / > < /Space> < SelectUncontrolled name = "sortOrder" label = "Sort order" defaultValue = { sortOrder || '' } options = { [ { value : 'asc' , text : 'Ascending' , } , { value : 'desc' , text : 'Descending' , } , ] } / > < />)} < /noscript> < SearchButtonWrapper > < ButtonSolid text = "Search" isTextHidden = { false } isBig = { true } / > < /SearchButtonWrapper> < /form>); } ) ; export default SearchForm ;