From 886163aafe30de2c66d41e0491600f00749ca682 Mon Sep 17 00:00:00 2001 From: Fibii <38106876+Fibii@users.noreply.github.com> Date: Wed, 5 Aug 2020 04:45:09 +0200 Subject: [PATCH] feat(patients): add no patients exist (#2235) --- .../patients/list/ViewPatients.test.tsx | 38 +++++++++++++++++-- src/__tests__/patients/patients-slice.test.ts | 3 +- .../patients/view/NoPatientsExist.test.tsx | 33 ++++++++++++++++ src/patients/list/ViewPatients.tsx | 34 ++++++++++------- src/patients/patients-slice.ts | 11 +++++- src/patients/view/NoPatientsExist.tsx | 38 +++++++++++++++++++ src/shared/db/Repository.ts | 5 +++ .../locales/ar/translations/patients/index.ts | 1 + .../locales/de/translations/patients/index.ts | 1 + .../enUs/translations/patients/index.ts | 1 + .../locales/fr/translations/patients/index.ts | 1 + .../locales/ru/translations/patients/index.ts | 1 + 12 files changed, 147 insertions(+), 20 deletions(-) create mode 100644 src/__tests__/patients/view/NoPatientsExist.test.tsx create mode 100644 src/patients/view/NoPatientsExist.tsx diff --git a/src/__tests__/patients/list/ViewPatients.test.tsx b/src/__tests__/patients/list/ViewPatients.test.tsx index 35a8afdcae..ebdb3effde 100644 --- a/src/__tests__/patients/list/ViewPatients.test.tsx +++ b/src/__tests__/patients/list/ViewPatients.test.tsx @@ -11,6 +11,7 @@ import { mocked } from 'ts-jest/utils' import * as ButtonBarProvider from '../../../page-header/button-toolbar/ButtonBarProvider' import ViewPatients from '../../../patients/list/ViewPatients' import * as patientSlice from '../../../patients/patients-slice' +import NoPatientsExist from '../../../patients/view/NoPatientsExist' import { UnpagedRequest } from '../../../shared/db/PageRequest' import PatientRepository from '../../../shared/db/PatientRepository' @@ -35,12 +36,13 @@ describe('Patients', () => { }, ] - const setup = (isLoading?: boolean) => { + const setup = (isLoading?: boolean, currentPatients = patients, count = patients.length) => { const store = mockStore({ patients: { - patients, + patients: currentPatients, isLoading, pageRequest: UnpagedRequest, + count, }, }) return mount( @@ -80,6 +82,13 @@ describe('Patients', () => { expect(wrapper.find(Spinner)).toHaveLength(1) }) + it('should render no patients exists when no patients exist', () => { + const wrapper = setup(false, [], 0) + + const addNewPatient = wrapper.find(NoPatientsExist) + expect(addNewPatient).toHaveLength(1) + }) + it('should render a table of patients', () => { const wrapper = setup() @@ -121,7 +130,10 @@ describe('Patients', () => { describe('search functionality', () => { beforeEach(() => jest.useFakeTimers()) - afterEach(() => jest.useRealTimers()) + afterEach(() => { + jest.useRealTimers() + jest.restoreAllMocks() + }) it('should search for patients after the search text has not changed for 500 milliseconds', () => { const searchPatientsSpy = jest.spyOn(patientSlice, 'searchPatients') @@ -145,5 +157,25 @@ describe('Patients', () => { sorts: [{ field: 'index', direction: 'asc' }], }) }) + + it("shound't display NoPatientsFound if a search result has no results", () => { + const searchPatientsSpy = jest.spyOn(patientSlice, 'searchPatients') + const wrapper = setup() + searchPatientsSpy.mockClear() + const expectedSearchText = '$$$not a patient$$$' + + act(() => { + const onChange = wrapper.find(TextInput).prop('onChange') as any + onChange({ target: { value: expectedSearchText } }) + }) + + act(() => { + jest.advanceTimersByTime(500) + }) + + wrapper.update() + + expect(NoPatientsExist).toHaveLength(0) + }) }) }) diff --git a/src/__tests__/patients/patients-slice.test.ts b/src/__tests__/patients/patients-slice.test.ts index 84565aedd2..1fea4c6a66 100644 --- a/src/__tests__/patients/patients-slice.test.ts +++ b/src/__tests__/patients/patients-slice.test.ts @@ -81,7 +81,8 @@ describe('patients slice', () => { await searchPatients('')(dispatch, getState, null) - expect(PatientRepository.findAll).toHaveBeenCalledTimes(1) + // expecting 2 here because searchPatients uses PatientRepository.count() which calls #findAll + expect(PatientRepository.findAll).toHaveBeenCalledTimes(2) }) it('should dispatch the FETCH_PATIENTS_SUCCESS action', async () => { diff --git a/src/__tests__/patients/view/NoPatientsExist.test.tsx b/src/__tests__/patients/view/NoPatientsExist.test.tsx new file mode 100644 index 0000000000..398434c475 --- /dev/null +++ b/src/__tests__/patients/view/NoPatientsExist.test.tsx @@ -0,0 +1,33 @@ +import { Icon, Typography, Button } from '@hospitalrun/components' +import { mount } from 'enzyme' +import React from 'react' + +import NoPatientsExist from '../../../patients/view/NoPatientsExist' + +describe('NoPatientsExist', () => { + const setup = () => mount() + + it('should render an icon and a button with typography', () => { + const wrapper = setup() + + const addNewPatient = wrapper.find(NoPatientsExist) + expect(addNewPatient).toHaveLength(1) + + const icon = wrapper.find(Icon).first() + const typography = wrapper.find(Typography) + const button = wrapper.find(Button) + const iconType = icon.prop('icon') + const iconSize = icon.prop('size') + const typographyText = typography.prop('children') + const typographyVariant = typography.prop('variant') + const buttonIcon = button.prop('icon') + const buttonText = button.prop('children') + + expect(iconType).toEqual('patients') + expect(iconSize).toEqual('6x') + expect(typographyText).toEqual('patients.noPatients') + expect(typographyVariant).toEqual('h5') + expect(buttonIcon).toEqual('patient-add') + expect(buttonText).toEqual('patients.newPatient') + }) +}) diff --git a/src/patients/list/ViewPatients.tsx b/src/patients/list/ViewPatients.tsx index 4dafd5543d..ad985f488f 100644 --- a/src/patients/list/ViewPatients.tsx +++ b/src/patients/list/ViewPatients.tsx @@ -13,6 +13,7 @@ import useTranslator from '../../shared/hooks/useTranslator' import useUpdateEffect from '../../shared/hooks/useUpdateEffect' import { RootState } from '../../shared/store' import { searchPatients } from '../patients-slice' +import NoPatientsExist from '../view/NoPatientsExist' const breadcrumbs = [{ i18nKey: 'patients.label', location: '/patients' }] @@ -22,7 +23,7 @@ const ViewPatients = () => { useTitle(t('patients.label')) useAddBreadcrumbs(breadcrumbs, true) const dispatch = useDispatch() - const { patients, isLoading } = useSelector((state: RootState) => state.patients) + const { patients, isLoading, count } = useSelector((state: RootState) => state.patients) const setButtonToolBar = useButtonToolbarSetter() @@ -48,22 +49,23 @@ const ViewPatients = () => { }, [dispatch, debouncedSearchText]) useEffect(() => { - setButtonToolBar([ - , - ]) - + if (patients && patients.length > 0) { + setButtonToolBar([ + , + ]) + } return () => { setButtonToolBar([]) } - }, [dispatch, setButtonToolBar, t, history]) + }, [dispatch, setButtonToolBar, t, history, patients]) const loadingIndicator = const table = ( @@ -91,6 +93,10 @@ const ViewPatients = () => { setSearchText(event.target.value) } + if (count === 0) { + return + } + return (
diff --git a/src/patients/patients-slice.ts b/src/patients/patients-slice.ts index e3daa42d56..15c910b9f4 100644 --- a/src/patients/patients-slice.ts +++ b/src/patients/patients-slice.ts @@ -8,11 +8,13 @@ import { AppThunk } from '../shared/store' interface PatientsState { isLoading: boolean patients: Patient[] + count: number } const initialState: PatientsState = { isLoading: false, patients: [], + count: 0, } function startLoading(state: PatientsState) { @@ -28,9 +30,13 @@ const patientsSlice = createSlice({ state.isLoading = false state.patients = payload }, + fetchCountSuccess(state, { payload }: PayloadAction) { + state.count = payload + }, }, }) -export const { fetchPatientsStart, fetchPatientsSuccess } = patientsSlice.actions + +export const { fetchPatientsStart, fetchPatientsSuccess, fetchCountSuccess } = patientsSlice.actions export const fetchPatients = (sortRequest: SortRequest = Unsorted): AppThunk => async ( dispatch, @@ -53,7 +59,8 @@ export const searchPatients = ( } else { patients = await PatientRepository.search(searchString) } - + const count = await PatientRepository.count() + dispatch(fetchCountSuccess(count)) dispatch(fetchPatientsSuccess(patients)) } diff --git a/src/patients/view/NoPatientsExist.tsx b/src/patients/view/NoPatientsExist.tsx new file mode 100644 index 0000000000..f255e38805 --- /dev/null +++ b/src/patients/view/NoPatientsExist.tsx @@ -0,0 +1,38 @@ +import { Button, Icon, Typography } from '@hospitalrun/components' +import React from 'react' +import { useHistory } from 'react-router-dom' + +import useTranslator from '../../shared/hooks/useTranslator' + +const NoPatientsExist = () => { + const history = useHistory() + const { t } = useTranslator() + + return ( +
+
+
+ +
+
+
+ {t('patients.noPatients')} +
+
+
+ +
+
+
+ ) +} + +export default NoPatientsExist diff --git a/src/shared/db/Repository.ts b/src/shared/db/Repository.ts index a77ad08d72..ba3f287dc8 100644 --- a/src/shared/db/Repository.ts +++ b/src/shared/db/Repository.ts @@ -132,6 +132,11 @@ export default class Repository { // return pagedResult // } + async count(): Promise { + const result = await this.findAll() + return result.length + } + async search(criteria: any): Promise { const response = await this.db.find(criteria) const data = await this.db.rel.parseRelDocs(this.type, response.docs) diff --git a/src/shared/locales/ar/translations/patients/index.ts b/src/shared/locales/ar/translations/patients/index.ts index e2b9ef8c32..753a035674 100644 --- a/src/shared/locales/ar/translations/patients/index.ts +++ b/src/shared/locales/ar/translations/patients/index.ts @@ -2,6 +2,7 @@ export default { patients: { label: 'المرضى', viewPatients: 'عرض المرضى', + noPatients: 'لا يوجد مرضى حاليا, قم بانشاء اول مريض حالا !', viewPatient: 'عرض المريض', editPatient: 'تغيير المريض', newPatient: 'مريض جديد', diff --git a/src/shared/locales/de/translations/patients/index.ts b/src/shared/locales/de/translations/patients/index.ts index 47d71277f0..01dc40787a 100644 --- a/src/shared/locales/de/translations/patients/index.ts +++ b/src/shared/locales/de/translations/patients/index.ts @@ -2,6 +2,7 @@ export default { patients: { label: 'Patienten', viewPatients: 'Patienten anzeigen', + noPatients: 'Es sind noch keine Patienten vorhanden, fügen Sie den Ersten hinzu', viewPatient: 'Patient anzeigen', editPatient: 'Patient bearbeiten', newPatient: 'Neuer Patient', diff --git a/src/shared/locales/enUs/translations/patients/index.ts b/src/shared/locales/enUs/translations/patients/index.ts index 8f8703b423..e8d3a2c2ff 100644 --- a/src/shared/locales/enUs/translations/patients/index.ts +++ b/src/shared/locales/enUs/translations/patients/index.ts @@ -4,6 +4,7 @@ export default { warning: 'Warning!', patientsList: 'Patients List', viewPatients: 'View Patients', + noPatients: "There are no patients yet, let's add the first one!", viewPatient: 'View Patient', newPatient: 'New Patient', editPatient: 'Edit Patient', diff --git a/src/shared/locales/fr/translations/patients/index.ts b/src/shared/locales/fr/translations/patients/index.ts index 02cabc76a7..2462ae46f9 100644 --- a/src/shared/locales/fr/translations/patients/index.ts +++ b/src/shared/locales/fr/translations/patients/index.ts @@ -3,6 +3,7 @@ export default { label: 'Patients', patientsList: 'Liste des patients', viewPatients: 'Voir les patients', + noPatients: "Il n'y a aucun patient ici, voilà donc le premier", viewPatient: 'Voir le patient', editPatient: 'Modifier le patient', newPatient: 'Nouveau patient', diff --git a/src/shared/locales/ru/translations/patients/index.ts b/src/shared/locales/ru/translations/patients/index.ts index 43c675bad4..47a9701562 100644 --- a/src/shared/locales/ru/translations/patients/index.ts +++ b/src/shared/locales/ru/translations/patients/index.ts @@ -2,6 +2,7 @@ export default { patients: { label: 'Пациенты', viewPatients: 'Просмотр пациентов', + noPatients: 'Пациентов еще нет, давайте добавим первого!', viewPatient: 'Просмотр пациента', editPatient: 'Редактировать пациента', newPatient: 'Новый пациент',