import * as React from 'react' ; import { connect } from 'react-redux' ; import { RootState , SearchOptions , SortingOption } from '../../types' ; import { FormUpdate , updateForm } from '../../actions/form' ; import { TextField , Select } from '@shopify/polaris' ; import { Dispatch } from 'redux' ; interface Props { readonly value : string ; } interface Handlers { readonly onChange : ( value : string | number ) => void ; } interface State { readonly value : string ; readonly error ? : string ; } const createMapDispatchFn = ( field ) => ( dispatch ) : Handlers => ( { onChange : ( value ) => { dispatch ( updateForm < SearchOptions > ( 'searchOptions' , field , value ) ) ; } } ) ; const createMapStateFn = ( field ) => ( state ) => ( { value : state . searchOptions [ field ] } ) ; class SearchDelayField extends React . PureComponent < Props & Handlers , State > { constructor ( props ) { super ( props ) ; this . state = { value : props . value . toString ( ) } ; } private handleChange = ( value ) => { this . setState ( { value , error : undefined } ) ; this . setErrorIfAny ( value ) ; const parsedValue = + value ; if ( ! Number . isNaN ( parsedValue ) ) { this . props . onChange ( parsedValue ) ; } } ; private setErrorIfAny = ( value ) => { if ( + value < 0 ) { this . setState ( { error : `Time between searches can't be negative.` } ) ; } } ; public render ( ) { return ( < TextField label = "Time Between Searches" type = "number" suffix = "seconds" min = { 0 } autoComplete = { false } spellCheck = { false } value = { this . state . value } onChange = { this . handleChange } error = { this . state . error } / > ) ; } } class MinimumRewardField extends React . PureComponent < Props & Handlers , State > { constructor ( props ) { super ( props ) ; this . state = { value : props . value . toString ( ) } ; } private handleChange = ( value ) => { this . setState ( { value , error : undefined } ) ; const parsedValue = + value ; if ( ! Number . isNaN ( parsedValue ) ) { this . props . onChange ( parsedValue ) ; } } ; public render ( ) { return ( < TextField label = "Minimum Reward" type = "number" step = { 0.1 } prefix = "$" autoComplete = { false } spellCheck = { false } value = { this . state . value } onChange = { this . handleChange } / > ) ; } } interface SortDropdownOptions { readonly label : SortingOption ; readonly value : SortingOption ; } class SortTypeField extends React . PureComponent < Props & Handlers , never > { private static options : SortDropdownOptions [ ] = [ { label : 'Latest' , value : 'Latest' } , { label : 'Batch Size' , value : 'Batch Size' } , { label : 'Reward' , value : 'Reward' } ] ; public render ( ) { return ( < Select label = "Search By" options = { SortTypeField . options } value = { this . props . value } onChange = { this . props . onChange } / > ) ; } } interface CustomSearchOwnProps { readonly connectedLeft ? : React . ReactNode ; readonly helpText ? : React . ReactNode ; } class CustomSearch extends React . PureComponent < Props & CustomSearchOwnProps & Handlers , never > { public render ( ) { return ( < TextField labelHidden type = "search" connectedLeft = { this . props . connectedLeft } label = "Search Term" name = "search-term" id = "search-term" placeholder = "Title, requester name, keywords, etc." value = { this . props . value } onChange = { this . props . onChange } helpText = { this . props . helpText } / > ) ; } } const ConnectedSearchDelayField = connect ( createMapStateFn ( 'delay' ) , createMapDispatchFn ( 'delay' ) ) ( SearchDelayField ) ; const ConnectedMinRewardField = connect ( createMapStateFn ( 'minReward' ) , createMapDispatchFn ( 'minReward' ) ) ( MinimumRewardField ) ; const ConnectedSortTypeField = connect ( createMapStateFn ( 'sortType' ) , createMapDispatchFn ( 'sortType' ) ) ( SortTypeField ) ; const ConnectedCustomSearchField = connect ( createMapStateFn ( 'searchTerm' ) , createMapDispatchFn ( 'searchTerm' ) ) ( CustomSearch ) ; export { ConnectedSearchDelayField , ConnectedMinRewardField , ConnectedSortTypeField , ConnectedCustomSearchField } ;