Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

feat(patients): added live search to the patients search #1970

Merged
merged 6 commits into from
Apr 7, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 9 additions & 19 deletions src/__tests__/patients/list/Patients.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import '../../../__mocks__/matchMediaMock'
import React from 'react'
import { mount } from 'enzyme'
import { TextInput, Button, Spinner, ListItem } from '@hospitalrun/components'
import { TextInput, Spinner, ListItem } from '@hospitalrun/components'
import { MemoryRouter } from 'react-router-dom'
import { Provider } from 'react-redux'
import thunk from 'redux-thunk'
Expand Down Expand Up @@ -47,15 +47,6 @@ describe('Patients', () => {
jest.restoreAllMocks()
})

it('should render a search input with button', () => {
const wrapper = setup()
const searchInput = wrapper.find(TextInput)
const searchButton = wrapper.find(Button)
expect(searchInput).toHaveLength(1)
expect(searchInput.prop('placeholder')).toEqual('actions.search')
expect(searchButton.text().trim()).toEqual('actions.search')
})

it('should render a loading bar if it is loading', () => {
const wrapper = setup(true)

Expand Down Expand Up @@ -83,10 +74,15 @@ describe('Patients', () => {
})

describe('search functionality', () => {
it('should call the searchPatients() action with the correct data', () => {
beforeEach(() => jest.useFakeTimers())

afterEach(() => jest.useRealTimers())

it('should search for patients after the search text has not changed for 500 milliseconds', () => {
const searchPatientsSpy = jest.spyOn(patientSlice, 'searchPatients')
const expectedSearchText = 'search text'
const wrapper = setup()
searchPatientsSpy.mockClear()
const expectedSearchText = 'search text'

act(() => {
;(wrapper.find(TextInput).prop('onChange') as any)({
Expand All @@ -99,14 +95,8 @@ describe('Patients', () => {
} as React.ChangeEvent<HTMLInputElement>)
})

wrapper.update()

act(() => {
;(wrapper.find(Button).prop('onClick') as any)({
preventDefault(): void {
// noop
},
} as React.MouseEvent<HTMLButtonElement>)
jest.advanceTimersByTime(500)
})

wrapper.update()
Expand Down
58 changes: 31 additions & 27 deletions src/patients/list/Patients.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ import useAddBreadcrumbs from '../../breadcrumbs/useAddBreadcrumbs'

const breadcrumbs = [{ i18nKey: 'patients.label', location: '/patients' }]

function useDebounce(value: any, delayInMilliseconds: number) {
hd-genius marked this conversation as resolved.
Show resolved Hide resolved
const [debouncedValue, setDebouncedValue] = useState(value)

useEffect(() => {
const debounceHandler = setTimeout(() => setDebouncedValue(value), delayInMilliseconds)

return () => clearTimeout(debounceHandler)
}, [value, delayInMilliseconds])

return debouncedValue
}

const Patients = () => {
const { t } = useTranslation()
const history = useHistory()
Expand All @@ -43,6 +55,12 @@ const Patients = () => {

const [searchText, setSearchText] = useState<string>('')

const debouncedSearchText = useDebounce(searchText, 500)

useEffect(() => {
dispatch(searchPatients(debouncedSearchText))
}, [dispatch, debouncedSearchText])

useEffect(() => {
dispatch(fetchPatients())

Expand All @@ -51,9 +69,7 @@ const Patients = () => {
}
}, [dispatch, setButtonToolBar])

if (isLoading) {
return <Spinner color="blue" loading size={[10, 25]} type="ScaleLoader" />
}
const loadingIndicator = <Spinner color="blue" loading size={[10, 25]} type="ScaleLoader" />

const list = (
<ul>
Expand All @@ -69,35 +85,23 @@ const Patients = () => {
setSearchText(event.target.value)
}

const onSearchFormSubmit = (event: React.FormEvent | React.MouseEvent) => {
event.preventDefault()
dispatch(searchPatients(searchText))
}

return (
<Container>
<form className="form" onSubmit={onSearchFormSubmit}>
<Row>
<Column md={10}>
<TextInput
size="lg"
type="text"
onChange={onSearchBoxChange}
value={searchText}
placeholder={t('actions.search')}
/>
</Column>
<Column md={2}>
<Button size="large" onClick={onSearchFormSubmit}>
{t('actions.search')}
</Button>
</Column>
</Row>
</form>
<Row>
<Column md={12}>
<TextInput
size="lg"
type="text"
onChange={onSearchBoxChange}
value={searchText}
placeholder={t('actions.search')}
/>
</Column>
</Row>

<Row>
<List layout="flush" style={{ width: '100%', marginTop: '10px', marginLeft: '-25px' }}>
{list}
{isLoading ? loadingIndicator : list}
</List>
</Row>
</Container>
Expand Down