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

feat(patients): adds ability to remove related person #1968

Merged
merged 3 commits into from
Apr 6, 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
73 changes: 57 additions & 16 deletions src/__tests__/patients/related-persons/RelatedPersons.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { Provider } from 'react-redux'
import Permissions from 'model/Permissions'
import { mocked } from 'ts-jest/utils'

import RelatedPerson from 'model/RelatedPerson'
import { Button } from '@hospitalrun/components'
import * as patientSlice from '../../../patients/patient-slice'

const mockStore = configureMockStore([thunk])
Expand Down Expand Up @@ -173,23 +175,29 @@ describe('Related Persons Tab', () => {
})
})

describe('List', () => {
describe('Table', () => {
const patient = {
id: '123',
rev: '123',
relatedPersons: [{ patientId: '123', type: 'type' }],
relatedPersons: [{ patientId: '123001', type: 'type' }],
} as Patient
const expectedRelatedPerson = {
givenName: 'test',
familyName: 'test',
fullName: 'test test',
id: '123001',
} as Patient

const user = {
permissions: [Permissions.WritePatients, Permissions.ReadPatients],
}

let patientSaveOrUpdateSpy: any

beforeEach(async () => {
patientSaveOrUpdateSpy = jest.spyOn(PatientRepository, 'saveOrUpdate')
jest.spyOn(PatientRepository, 'find')
mocked(PatientRepository.find).mockResolvedValue({
fullName: 'test test',
id: '123001',
} as Patient)
mocked(PatientRepository.find).mockResolvedValue(expectedRelatedPerson)

await act(async () => {
wrapper = await mount(
Expand All @@ -204,20 +212,53 @@ describe('Related Persons Tab', () => {
})

it('should render a list of related persons with their full name being displayed', () => {
const list = wrapper.find(components.List)
const listItems = wrapper.find(components.ListItem)
expect(list).toHaveLength(1)
expect(listItems).toHaveLength(1)
expect(listItems.at(0).text()).toEqual('test test')
const table = wrapper.find('table')
const tableHeader = wrapper.find('thead')
const tableHeaders = wrapper.find('th')
const tableBody = wrapper.find('tbody')
const tableData = wrapper.find('td')
const deleteButton = tableData.at(3).find(Button)
expect(table).toHaveLength(1)
expect(tableHeader).toHaveLength(1)
expect(tableBody).toHaveLength(1)
expect(tableHeaders.at(0).text()).toEqual('patient.givenName')
expect(tableHeaders.at(1).text()).toEqual('patient.familyName')
expect(tableHeaders.at(2).text()).toEqual('patient.relatedPersons.relationshipType')
expect(tableHeaders.at(3).text()).toEqual('actions.label')
expect(tableData.at(0).text()).toEqual(expectedRelatedPerson.givenName)
expect(tableData.at(1).text()).toEqual(expectedRelatedPerson.familyName)
expect(tableData.at(2).text()).toEqual((patient.relatedPersons as RelatedPerson[])[0].type)
expect(deleteButton).toHaveLength(1)
expect(deleteButton.text().trim()).toEqual('actions.delete')
expect(deleteButton.prop('color')).toEqual('danger')
})

it('should remove the related person when the delete button is clicked', async () => {
const eventPropagationSpy = jest.fn()

const table = wrapper.find('table')
const tableBody = table.find('tbody')
const tableData = tableBody.find('td')
const deleteButton = tableData.at(3).find(Button)

await act(async () => {
const onClick = deleteButton.prop('onClick')
onClick({ stopPropagation: eventPropagationSpy })
})

expect(eventPropagationSpy).toHaveBeenCalledTimes(1)
expect(patientSaveOrUpdateSpy).toHaveBeenLastCalledWith({ ...patient, relatedPersons: [] })
})

it('should navigate to related person patient profile on related person click', () => {
const list = wrapper.find(components.List)
const listItems = wrapper.find(components.ListItem)
const table = wrapper.find('table')
const tableBody = table.find('tbody')
const row = tableBody.find('tr')
act(() => {
;(listItems.at(0).prop('onClick') as any)()
const onClick = row.prop('onClick')
onClick()
})
expect(list).toHaveLength(1)
expect(listItems).toHaveLength(1)

expect(history.location.pathname).toEqual('/patients/123001')
})
})
Expand Down
1 change: 1 addition & 0 deletions src/locales/enUs/translations/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export default {
actions: {
label: 'Actions',
edit: 'Edit',
save: 'Save',
update: 'Update',
Expand Down
73 changes: 53 additions & 20 deletions src/patients/related-persons/RelatedPersonTab.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react'
import { Button, Panel, List, ListItem, Alert, Spinner, Toast } from '@hospitalrun/components'
import { Button, Alert, Spinner, Toast } from '@hospitalrun/components'
import AddRelatedPersonModal from 'patients/related-persons/AddRelatedPersonModal'
import RelatedPerson from 'model/RelatedPerson'
import { useTranslation } from 'react-i18next'
Expand Down Expand Up @@ -44,7 +44,7 @@ const RelatedPersonTab = (props: Props) => {
await Promise.all(
patient.relatedPersons.map(async (person) => {
const fetchedRelatedPerson = await PatientRepository.find(person.patientId)
fetchedRelatedPersons.push(fetchedRelatedPerson)
fetchedRelatedPersons.push({ ...fetchedRelatedPerson, type: person.type })
}),
)
}
Expand Down Expand Up @@ -88,6 +88,20 @@ const RelatedPersonTab = (props: Props) => {
closeNewRelatedPersonModal()
}

const onRelatedPersonDelete = (
event: React.MouseEvent<HTMLButtonElement>,
relatedPerson: Patient,
) => {
event.stopPropagation()
const patientToUpdate = { ...patient }
const newRelatedPersons = patientToUpdate.relatedPersons?.filter(
(r) => r.patientId !== relatedPerson.id,
)
patientToUpdate.relatedPersons = newRelatedPersons

dispatch(updatePatient(patientToUpdate))
}

return (
<div>
<div className="row">
Expand All @@ -108,27 +122,46 @@ const RelatedPersonTab = (props: Props) => {
<br />
<div className="row">
<div className="col-md-12">
<Panel title={t('patient.relatedPersons.label')} color="primary" collapsible>
{relatedPersons ? (
relatedPersons.length > 0 ? (
<List>
{relatedPersons ? (
relatedPersons.length > 0 ? (
<table className="table table-hover">
<thead className="thead-light">
<tr>
<th>{t('patient.givenName')}</th>
<th>{t('patient.familyName')}</th>
<th>{t('patient.relatedPersons.relationshipType')}</th>
<th>{t('actions.label')}</th>
</tr>
</thead>
<tbody>
{relatedPersons.map((r) => (
<ListItem action key={r.id} onClick={() => onRelatedPersonClick(r.id)}>
{r.fullName}
</ListItem>
<tr key={r.id} onClick={() => onRelatedPersonClick(r.id)}>
<td>{r.givenName}</td>
<td>{r.familyName}</td>
<td>{r.type}</td>
<td>
<Button
icon="remove"
color="danger"
onClick={(e) => onRelatedPersonDelete(e, r)}
>
{t('actions.delete')}
</Button>
</td>
</tr>
))}
</List>
) : (
<Alert
color="warning"
title={t('patient.relatedPersons.warning.noRelatedPersons')}
message={t('patient.relatedPersons.addRelatedPersonAbove')}
/>
)
</tbody>
</table>
) : (
<Spinner color="blue" loading size={[10, 25]} type="ScaleLoader" />
)}
</Panel>
<Alert
color="warning"
title={t('patient.relatedPersons.warning.noRelatedPersons')}
message={t('patient.relatedPersons.addRelatedPersonAbove')}
/>
)
) : (
<Spinner color="blue" loading size={[10, 25]} type="ScaleLoader" />
)}
</div>
</div>

Expand Down