From e97c3cac832111786c7515e3485c675ba499ac4c Mon Sep 17 00:00:00 2001 From: blestab Date: Thu, 9 Jul 2020 01:03:34 +0200 Subject: [PATCH 1/2] fix: add Relates Person search crash if matched person has no DoB fix #2195 --- src/patients/related-persons/AddRelatedPersonModal.tsx | 6 +++--- src/shared/hooks/useTranslator.ts | 7 +------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/patients/related-persons/AddRelatedPersonModal.tsx b/src/patients/related-persons/AddRelatedPersonModal.tsx index 7b57e6d3bb..c7a30bd8e0 100644 --- a/src/patients/related-persons/AddRelatedPersonModal.tsx +++ b/src/patients/related-persons/AddRelatedPersonModal.tsx @@ -48,6 +48,8 @@ const AddRelatedPersonModal = (props: Props) => { return patients.filter((p: Patient) => p.id !== patient.id) } + const formattedDate = (date: string) => (date ? format(new Date(date), 'yyyy-MM-dd') : '') + const body = (
{relatedPersonError?.message && ( @@ -65,9 +67,7 @@ const AddRelatedPersonModal = (props: Props) => { isInvalid={!!relatedPersonError?.relatedPerson} onSearch={onSearch} renderMenuItemChildren={(p: Patient) => ( -
- {`${p.fullName} - ${format(new Date(p.dateOfBirth), 'yyyy-MM-dd')} (${p.code})`} -
+
{`${p.fullName} - ${formattedDate(p.dateOfBirth)} (${p.code})`}
)} /> {relatedPersonError?.relatedPerson && ( diff --git a/src/shared/hooks/useTranslator.ts b/src/shared/hooks/useTranslator.ts index 7a55183aaf..353c81cf18 100644 --- a/src/shared/hooks/useTranslator.ts +++ b/src/shared/hooks/useTranslator.ts @@ -4,12 +4,7 @@ import { useTranslation } from 'react-i18next' export default function useTranslator() { const { t } = useTranslation() - const translate = useCallback( - (key: any): any => { - return key !== undefined ? t(key) : undefined - }, - [t], - ) + const translate = useCallback((key: any): any => (key !== undefined ? t(key) : undefined), [t]) return { t: translate, From 5a34b8f40e0cead8cb2a660e6ea6dc41faf71303 Mon Sep 17 00:00:00 2001 From: blestab Date: Fri, 10 Jul 2020 02:12:57 +0200 Subject: [PATCH 2/2] feat(incidents): add ability to resolve an incident re #2078 --- src/incidents/IncidentFilter.ts | 1 + src/incidents/incident-slice.ts | 22 +++++++ src/incidents/view/ViewIncident.tsx | 63 ++++++++++++++++++- .../enUs/translations/incidents/index.ts | 3 + src/shared/model/Incident.ts | 3 +- src/shared/model/Permissions.ts | 1 + src/user/user-slice.ts | 1 + 7 files changed, 90 insertions(+), 4 deletions(-) diff --git a/src/incidents/IncidentFilter.ts b/src/incidents/IncidentFilter.ts index d141730d05..492e28545e 100644 --- a/src/incidents/IncidentFilter.ts +++ b/src/incidents/IncidentFilter.ts @@ -1,5 +1,6 @@ enum IncidentFilter { reported = 'reported', + completed = 'completed', all = 'all', } diff --git a/src/incidents/incident-slice.ts b/src/incidents/incident-slice.ts index 11a319ebe9..9390815b91 100644 --- a/src/incidents/incident-slice.ts +++ b/src/incidents/incident-slice.ts @@ -51,6 +51,8 @@ const incidentSlice = createSlice({ reportIncidentStart: start, reportIncidentSuccess: finish, reportIncidentError: error, + completeIncidentStart: start, + completeIncidentSuccess: finish, }, }) @@ -60,6 +62,8 @@ export const { reportIncidentStart, reportIncidentSuccess, reportIncidentError, + completeIncidentStart, + completeIncidentSuccess, } = incidentSlice.actions export const fetchIncident = (id: string): AppThunk => async (dispatch) => { @@ -120,4 +124,22 @@ export const reportIncident = ( } } +export const completeIncident = ( + incidentToComplete: Incident, + onSuccess?: (incidentToComplete: Incident) => void, +): AppThunk => async (dispatch) => { + dispatch(completeIncidentStart()) + + incidentToComplete.completedOn = new Date(Date.now().valueOf()).toISOString() + const completedIncident = await IncidentRepository.saveOrUpdate({ + ...incidentToComplete, + status: 'completed', + }) + dispatch(completeIncidentSuccess(completedIncident)) + + if (onSuccess) { + onSuccess(completedIncident) + } +} + export default incidentSlice.reducer diff --git a/src/incidents/view/ViewIncident.tsx b/src/incidents/view/ViewIncident.tsx index 17b6fc620d..ed6bdbd9cf 100644 --- a/src/incidents/view/ViewIncident.tsx +++ b/src/incidents/view/ViewIncident.tsx @@ -1,22 +1,26 @@ -import { Column, Row, Spinner } from '@hospitalrun/components' +import { Button, Column, Row, Spinner } from '@hospitalrun/components' import format from 'date-fns/format' import React, { useEffect } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { useParams } from 'react-router-dom' +import { useParams, useHistory } from 'react-router-dom' import useAddBreadcrumbs from '../../page-header/breadcrumbs/useAddBreadcrumbs' import useTitle from '../../page-header/title/useTitle' import TextFieldWithLabelFormGroup from '../../shared/components/input/TextFieldWithLabelFormGroup' import TextInputWithLabelFormGroup from '../../shared/components/input/TextInputWithLabelFormGroup' import useTranslator from '../../shared/hooks/useTranslator' +import Permissions from '../../shared/model/Permissions' import { RootState } from '../../shared/store' -import { fetchIncident } from '../incident-slice' +import { fetchIncident, completeIncident } from '../incident-slice' const ViewIncident = () => { const dispatch = useDispatch() const { t } = useTranslator() + const history = useHistory() const { id } = useParams() const { incident } = useSelector((state: RootState) => state.incident) + const { permissions } = useSelector((state: RootState) => state.user) + const isIncomplete = incident?.status !== 'completed' useTitle(incident ? incident.code : '') const breadcrumbs = [ { @@ -31,7 +35,54 @@ const ViewIncident = () => { dispatch(fetchIncident(id)) } }, [dispatch, id]) + + const onComplete = async () => { + const onSuccess = () => { + history.push('/incidents') + } + + if (incident) { + dispatch(completeIncident(incident, onSuccess)) + } + } + + const getButtons = () => { + const buttons: React.ReactNode[] = [] + if (incident?.status === 'completed') { + return buttons + } + + if (permissions.includes(Permissions.CompleteIncident)) { + buttons.push( + , + ) + } + + return buttons + } + if (incident) { + const getCompletedOnDate = () => { + if (incident.status === 'completed' && incident.completedOn) { + return ( + +
+

{t('incidents.reports.completedOn')}

+
{format(new Date(incident.completedOn), 'yyyy-MM-dd hh:mm a')}
+
+
+ ) + } + return <> + } + return ( <> @@ -59,6 +110,7 @@ const ViewIncident = () => {
{format(new Date(incident.reportedOn || ''), 'yyyy-MM-dd hh:mm a')}
+ {getCompletedOnDate()}
@@ -95,6 +147,11 @@ const ViewIncident = () => { /> + {isIncomplete && ( +
+
{getButtons()}
+
+ )} ) } diff --git a/src/shared/locales/enUs/translations/incidents/index.ts b/src/shared/locales/enUs/translations/incidents/index.ts index 8b71520a52..dc9aa43df3 100644 --- a/src/shared/locales/enUs/translations/incidents/index.ts +++ b/src/shared/locales/enUs/translations/incidents/index.ts @@ -7,12 +7,14 @@ export default { }, status: { reported: 'reported', + completed: 'completed', all: 'all', }, reports: { label: 'Reported Incidents', new: 'Report Incident', view: 'View Incident', + complete: 'Complete Incident', dateOfIncident: 'Date of Incident', department: 'Department', category: 'Category', @@ -21,6 +23,7 @@ export default { code: 'Code', reportedBy: 'Reported By', reportedOn: 'Reported On', + completedOn: 'Completed On', status: 'Status', error: { dateRequired: 'Date is required.', diff --git a/src/shared/model/Incident.ts b/src/shared/model/Incident.ts index ecc8f66cdc..c36ae8d5db 100644 --- a/src/shared/model/Incident.ts +++ b/src/shared/model/Incident.ts @@ -9,5 +9,6 @@ export default interface Incident extends AbstractDBModel { category: string categoryItem: string description: string - status: 'reported' + status: 'reported' | 'completed' + completedOn: string } diff --git a/src/shared/model/Permissions.ts b/src/shared/model/Permissions.ts index 2adda626ac..b4b2f5f2d5 100644 --- a/src/shared/model/Permissions.ts +++ b/src/shared/model/Permissions.ts @@ -14,6 +14,7 @@ enum Permissions { ViewIncidents = 'read:incidents', ViewIncident = 'read:incident', ReportIncident = 'write:incident', + CompleteIncident = 'complete:incident', AddCarePlan = 'write:care_plan', ReadCarePlan = 'read:care_plan', } diff --git a/src/user/user-slice.ts b/src/user/user-slice.ts index c18fff557c..755d07ed6a 100644 --- a/src/user/user-slice.ts +++ b/src/user/user-slice.ts @@ -35,6 +35,7 @@ const initialState: UserState = { Permissions.ViewIncident, Permissions.ViewIncidents, Permissions.ReportIncident, + Permissions.CompleteIncident, Permissions.AddCarePlan, Permissions.ReadCarePlan, ],