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

Commit

Permalink
feat(imaging): link image with visit (#2309)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexTan331 authored Aug 26, 2020
1 parent 0954a4e commit c0ee742
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 31 deletions.
3 changes: 2 additions & 1 deletion src/__tests__/imagings/ViewImagings.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ describe('View Imagings', () => {
id: '1234',
type: 'imaging type',
patient: 'patient',
fullName: 'full name',
status: 'requested',
requestedOn: expectedDate.toISOString(),
requestedBy: 'some user',
Expand Down Expand Up @@ -110,7 +111,7 @@ describe('View Imagings', () => {
expect.objectContaining({ label: 'imagings.imaging.requestedOn', key: 'requestedOn' }),
)
expect(columns[3]).toEqual(
expect.objectContaining({ label: 'imagings.imaging.patient', key: 'patient' }),
expect.objectContaining({ label: 'imagings.imaging.patient', key: 'fullName' }),
)
expect(columns[4]).toEqual(
expect.objectContaining({ label: 'imagings.imaging.requestedBy', key: 'requestedBy' }),
Expand Down
19 changes: 17 additions & 2 deletions src/__tests__/imagings/requests/NewImagingRequest.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ describe('New Imaging Request', () => {
expect(typeahead.prop('searchAccessor')).toEqual('fullName')
})

it('should render a dropdown list of visits', async () => {
const wrapper = await setup('loading', {})
const visitsTypeSelect = wrapper.find('.visits').find(SelectWithLabelFormGroup)
expect(visitsTypeSelect).toBeDefined()
expect(visitsTypeSelect.prop('label')).toEqual('patient.visits.label')
expect(visitsTypeSelect.prop('isRequired')).toBeTruthy()
})

it('should render a type input box', async () => {
const wrapper = await setup('loading', {})
const typeInputBox = wrapper.find(TextInputWithLabelFormGroup)
Expand All @@ -98,7 +106,7 @@ describe('New Imaging Request', () => {

it('should render a status types select', async () => {
const wrapper = await setup('loading', {})
const statusTypesSelect = wrapper.find(SelectWithLabelFormGroup)
const statusTypesSelect = wrapper.find('.imaging-status').find(SelectWithLabelFormGroup)

expect(statusTypesSelect).toBeDefined()
expect(statusTypesSelect.prop('label')).toEqual('imagings.imaging.status')
Expand Down Expand Up @@ -184,6 +192,7 @@ describe('New Imaging Request', () => {
patient: 'patient',
type: 'expected type',
status: 'requested',
visitId: 'expected visitId',
notes: 'expected notes',
id: '1234',
requestedOn: expectedDate.toISOString(),
Expand All @@ -204,12 +213,18 @@ describe('New Imaging Request', () => {
onChange({ currentTarget: { value: expectedImaging.type } })
})

const statusSelect = wrapper.find(SelectWithLabelFormGroup)
const statusSelect = wrapper.find('.imaging-status').find(SelectWithLabelFormGroup)
act(() => {
const onChange = statusSelect.prop('onChange') as any
onChange({ currentTarget: { value: expectedImaging.status } })
})

const visitsSelect = wrapper.find('.visits').find(SelectWithLabelFormGroup)
act(() => {
const onChange = visitsSelect.prop('onChange') as any
onChange({ currentTarget: { value: expectedImaging.visitId } })
})

const notesTextField = wrapper.find(TextFieldWithLabelFormGroup)
act(() => {
const onChange = notesTextField.prop('onChange') as any
Expand Down
2 changes: 1 addition & 1 deletion src/imagings/ViewImagings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const ViewImagings = () => {
formatter: (row) =>
row.requestedOn ? format(new Date(row.requestedOn), 'yyyy-MM-dd hh:mm a') : '',
},
{ label: t('imagings.imaging.patient'), key: 'patient' },
{ label: t('imagings.imaging.patient'), key: 'fullName' },
{
label: t('imagings.imaging.requestedBy'),
key: 'requestedBy',
Expand Down
1 change: 1 addition & 0 deletions src/imagings/imaging-slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface Error {
type?: string
status?: string
message?: string
visitId?: string
}

interface ImagingState {
Expand Down
116 changes: 89 additions & 27 deletions src/imagings/requests/NewImagingRequest.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Typeahead, Label, Button, Alert } from '@hospitalrun/components'
import { Typeahead, Label, Button, Alert, Column, Row } from '@hospitalrun/components'
import format from 'date-fns/format'
import React, { useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { useHistory } from 'react-router-dom'
Expand All @@ -23,6 +24,7 @@ const NewImagingRequest = () => {
const history = useHistory()
useTitle(t('imagings.requests.new'))
const { status, error } = useSelector((state: RootState) => state.imaging)
const [visitOption, setVisitOption] = useState([] as Option[])

const statusOptions: Option[] = [
{ label: t('imagings.status.requested'), value: 'requested' },
Expand All @@ -32,9 +34,11 @@ const NewImagingRequest = () => {

const [newImagingRequest, setNewImagingRequest] = useState({
patient: '',
fullName: '',
type: '',
notes: '',
status: '',
visitId: '',
})

const breadcrumbs = [
Expand All @@ -46,10 +50,28 @@ const NewImagingRequest = () => {
useAddBreadcrumbs(breadcrumbs)

const onPatientChange = (patient: Patient) => {
setNewImagingRequest((previousNewImagingRequest) => ({
...previousNewImagingRequest,
patient: patient.fullName as string,
}))
if (patient) {
setNewImagingRequest((previousNewImagingRequest) => ({
...previousNewImagingRequest,
patient: patient.id,
fullName: patient.fullName as string,
}))

const visits = patient.visits?.map((v) => ({
label: `${v.type} at ${format(new Date(v.startDateTime), 'yyyy-MM-dd hh:mm a')}`,
value: v.id,
})) as Option[]

setVisitOption(visits)
} else {
setNewImagingRequest((previousNewImagingRequest) => ({
...previousNewImagingRequest,
patient: '',
fullName: '',
visitId: '',
}))
setVisitOption([])
}
}

const onImagingTypeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
Expand All @@ -67,6 +89,13 @@ const NewImagingRequest = () => {
}))
}

const onVisitChange = (value: string) => {
setNewImagingRequest((previousNewImagingRequest) => ({
...previousNewImagingRequest,
visitId: value,
}))
}

const onNoteChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
const notes = event.currentTarget.value
setNewImagingRequest((previousNewImagingRequest) => ({
Expand All @@ -88,25 +117,54 @@ const NewImagingRequest = () => {
history.push('/imaging')
}

const defaultSelectedVisitsOption = () => {
if (visitOption !== undefined) {
return visitOption.filter(({ value }) => value === newImagingRequest.visitId)
}
return []
}

return (
<>
{status === 'error' && (
<Alert color="danger" title={t('states.error')} message={t(error.message || '')} />
)}
<form>
<div className="form-group patient-typeahead">
<Label htmlFor="patientTypeahead" isRequired text={t('imagings.imaging.patient')} />
<Typeahead
id="patientTypeahead"
placeholder={t('imagings.imaging.patient')}
onChange={(p: Patient[]) => onPatientChange(p[0])}
onSearch={async (query: string) => PatientRepository.search(query)}
searchAccessor="fullName"
renderMenuItemChildren={(p: Patient) => <div>{`${p.fullName} (${p.code})`}</div>}
isInvalid={!!error.patient}
feedback={t(error.patient as string)}
/>
</div>
<Row>
<Column>
<div className="form-group patient-typeahead">
<Label htmlFor="patientTypeahead" isRequired text={t('imagings.imaging.patient')} />
<Typeahead
id="patientTypeahead"
placeholder={t('imagings.imaging.patient')}
onChange={(p: Patient[]) => {
onPatientChange(p[0])
}}
onSearch={async (query: string) => PatientRepository.search(query)}
searchAccessor="fullName"
renderMenuItemChildren={(p: Patient) => <div>{`${p.fullName} (${p.code})`}</div>}
isInvalid={!!error.patient}
feedback={t(error.patient as string)}
/>
</div>
</Column>
<Column>
<div className="visits">
<SelectWithLabelFormGroup
name="visit"
label={t('patient.visits.label')}
isRequired
isEditable={newImagingRequest.patient !== undefined}
options={visitOption || []}
defaultSelected={defaultSelectedVisitsOption()}
onChange={(values) => {
onVisitChange(values[0])
}}
/>
</div>
</Column>
</Row>

<TextInputWithLabelFormGroup
name="imagingType"
label={t('imagings.imaging.type')}
Expand All @@ -117,15 +175,19 @@ const NewImagingRequest = () => {
value={newImagingRequest.type}
onChange={onImagingTypeChange}
/>
<SelectWithLabelFormGroup
name="status"
label={t('imagings.imaging.status')}
options={statusOptions}
isRequired
isEditable
defaultSelected={statusOptions.filter(({ value }) => value === newImagingRequest.status)}
onChange={(values) => onStatusChange(values[0])}
/>
<div className="imaging-status">
<SelectWithLabelFormGroup
name="status"
label={t('imagings.imaging.status')}
options={statusOptions}
isRequired
isEditable
defaultSelected={statusOptions.filter(
({ value }) => value === newImagingRequest.status,
)}
onChange={(values) => onStatusChange(values[0])}
/>
</div>
<div className="form-group">
<TextFieldWithLabelFormGroup
name="ImagingNotes"
Expand Down
2 changes: 2 additions & 0 deletions src/shared/model/Imaging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import AbstractDBModel from './AbstractDBModel'
export default interface Imaging extends AbstractDBModel {
code: string
patient: string
fullName: string
type: string
status: 'requested' | 'completed' | 'canceled'
visitId: string
requestedOn: string
requestedBy: string // will be the currently logged in user's id
completedOn?: string
Expand Down

0 comments on commit c0ee742

Please sign in to comment.