Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@emotion/jest": "^11.2.1",
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"@orfium/ictinus": "^3.9.1",
"@orfium/ictinus": "^3.14.1",
"@testing-library/jest-dom": "^5.11.9",
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.1.3",
Expand All @@ -23,11 +23,13 @@
"axios": "^0.21.1",
"customize-cra": "^1.0.0",
"final-form": "^4.20.2",
"final-form-arrays": "^3.0.2",
"history": "^4.10.1",
"lodash": "^4.17.21",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-final-form": "^6.5.3",
"react-final-form-arrays": "^3.1.3",
"react-final-form-listeners": "^1.0.3",
"react-query": "^3.16.0",
"react-router-dom": "^5.2.0",
Expand Down
15 changes: 12 additions & 3 deletions src/api/patientsAPI/patientsAPI.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { RegisterPatientPayload, PatientsPayload, PaginationParams } from '../../models/apiTypes';
import {
RegisterPatientPayload,
PatientsPayload,
PaginationParams,
RegisterEpisodePayload,
} from '../../models/apiTypes';
import { METHODS, request } from '../axiosInstances';

export default {
getHospitals: (params?: PaginationParams) => request(METHODS.GET, '/hospitals/', { params }),
getHospital: (id: string) => request(METHODS.GET, `/hospitals/${id}`, {}),
getHospital: (id: string) => request(METHODS.GET, `/hospitals/${id}/`, {}),
getPatients: (params?: PatientsPayload) => request(METHODS.GET, '/patients/', { params }),
getPatient: (id: string) => request(METHODS.GET, `/patients/${id}`, {}),
getSurgeons: (params?: PaginationParams) =>
request(METHODS.GET, '/medical-personnel/', { params }),
getPatient: (id: string) => request(METHODS.GET, `/patients/${id}/`, {}),
registerPatient: (params: RegisterPatientPayload) =>
request(METHODS.POST, '/patients/', { params }),
registerEpisode: (params: RegisterEpisodePayload) =>
request(METHODS.POST, '/episodes/', { params }),
};
9 changes: 9 additions & 0 deletions src/common.style.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ export const PageTitle = styled.div`
padding: 16px;
`;

export const PageSubtitle = styled.div`
color: ${(props) => props.theme.utils.getColor('darkGray', 400)};
display: flex;
font-size: 18px;
font-weight: 400;
gap: 16px;
padding: 16px;
`;

export const SectionTitle = styled.div`
color: ${(props) => props.theme.utils.getColor('blue', 500)};
font-size: 18px;
Expand Down
60 changes: 60 additions & 0 deletions src/hooks/api/patientHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ import {
PatientAPI,
PatientsPayload,
PatientsResponse,
RegisterEpisodePayload,
RegisterPatientPayload,
SurgeonsResponse,
} from '../../models/apiTypes';
import { RegisterEpisodeFormType } from '../../pages/RegisterEpisode/types';
import { RegisterPatientFormType } from '../../pages/RegisterPatient/types';
import urls from '../../routing/urls';

Expand Down Expand Up @@ -77,6 +80,22 @@ export const useGetPatients = (params?: PatientsPayload) => {
);
};

export const useGetSurgeons = (params?: PaginationParams) => {
return useQuery<SurgeonsResponse, AxiosError, SurgeonsResponse>(
[ReactQueryKeys.SurgeonsQuery, params?.limit, params?.offset, params?.ordering],
async () => {
const { request } = patientsAPI.single.getSurgeons(params);
return await request();
},
{
onError: (errors) => {
console.log(errors);
},
retry: false,
}
);
};

export const useGetPatient = (id: string) => {
return useQuery<PatientAPI, AxiosError, PatientAPI>(
[ReactQueryKeys.PatientsQuery, id],
Expand Down Expand Up @@ -122,3 +141,44 @@ export const useRegisterPatient = () => {
}
);
};

export const useRegisterEpisode = (
hospitalID?: string,
patientID?: string,
episodeType = 'Inguinal Mesh Hernia Repair'
) => {
const history = useHistory();

return useMutation<RegisterEpisodePayload, AxiosError, RegisterEpisodeFormType>(
(params) => {
const payload = {
hospital_id: params?.hospital?.value,
patient_id: parseInt(patientID ?? '0'),
anaesthetic_type: params?.anaestheticType?.label,
diathermy_used: params?.diathermyUsed?.label === 'True',
surgeon_ids: params?.surgeons?.map((surgeon) => surgeon?.value) ?? ['1'],
comments: params?.comments,
mesh_type: params?.meshType?.label,
episode_type: episodeType,
type: params.type?.label,
cepod: params.cepod?.label,
complexity: params?.complexity?.label,
occurence: params?.occurence?.label,
side: params?.side?.label,
surgery_date: params?.surgeryDate,
};

const { request } = patientsAPI.single.registerEpisode(payload);

return request();
},
{
onSuccess: () => {
history.replace(`${urls.patients()}/${hospitalID}/${patientID}`);
},
onError: (errors) => {
console.log(errors);
},
}
);
};
1 change: 1 addition & 0 deletions src/hooks/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const ReactQueryKeys = {
PatientsQuery: 'patientsQuery',
HospitalsQuery: 'hospitalsQuery',
SurgeonsQuery: 'surgeonsQuery',
};
44 changes: 42 additions & 2 deletions src/models/apiTypes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,36 @@ export type HospitalsAPI = {
patient_hospital_id?: number;
};

// export type EpisodesAPI = {};
export type EpisodesAPI = {
episode_type: string;
cepod: string;
side: string;
occurence: string;
type: string;
complexity: string;
mesh_type: string;
diathermy_used: boolean;
comments?: string;
anaesthetic_type: string;
surgeons: SurgeonsAPI[];
};

export type RegisterEpisodePayload = {
hospital_id: number;
patient_id: number;
surgery_date: string;
episode_type: string;
cepod: string;
side: string;
occurence: string;
type: string;
complexity: string;
mesh_type: string;
diathermy_used: boolean;
comments?: string;
anaesthetic_type: string;
surgeon_ids: number[];
};

export interface HospitalsResponse extends PaginationResponse, PaginationParams {
results: HospitalsAPI[];
Expand Down Expand Up @@ -73,9 +102,20 @@ export type PatientAPI = {
phone_2: string;
address: string;
hospital_mappings: HospitalsAPI[];
// episodes: EpisodesAPI[];
episodes: EpisodesAPI[];
};

export interface PatientsResponse extends PaginationResponse, PaginationParams {
results: PatientAPI[];
}

export type SurgeonsAPI = {
id: number;
user: {
email: string;
};
level: string;
};
export interface SurgeonsResponse extends PaginationResponse, PaginationParams {
results: SurgeonsAPI[];
}
9 changes: 8 additions & 1 deletion src/pages/PatientDetails/PatientDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,14 @@ const PatientDetails: React.FC = () => {
)}
</ComponentWrapper>
<ButtonContainer>
<Button color={'blue-500'} buttonType="button" disabled={isLoading} block size="md">
<Button
color={'blue-500'}
buttonType="button"
disabled={isLoading}
block
size="md"
onClick={() => history.push(`${history.location.pathname}/add-episode`)}
>
Register new episode
</Button>
</ButtonContainer>
Expand Down
8 changes: 8 additions & 0 deletions src/pages/RegisterEpisode/RegisterEpisode.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import styled from '@emotion/styled';

export const FormHeading = styled.span`
font-size: 14px;
font-weight: 700;
margin-bottom: 12px;
padding: 18px;
`;
149 changes: 149 additions & 0 deletions src/pages/RegisterEpisode/RegisterEpisode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/** @jsxImportSource @emotion/react */
import React, { useState } from 'react';

import { Button, Icon } from '@orfium/ictinus';
import { ButtonContainer, PageSubtitle, PageTitle, PageWrapper } from 'common.style';
import ConfirmationModal from 'components/ConfirmationModal';
import arrayMutators from 'final-form-arrays';
import { Form } from 'react-final-form';
import { useHistory } from 'react-router';
import { useRouteMatch } from 'react-router-dom';
import urls from 'routing/urls';

import {
useGetHospital,
useGetHospitals,
useGetPatient,
useGetSurgeons,
useRegisterEpisode,
} from '../../hooks/api/patientHooks';
import RegisterEpisodeForm from './components/RegisterEpisodeForm';
import { RegisterEpisodeFormType } from './types';
import { formValidation } from './utils';

const RegisterEpisode: React.FC = () => {
const match = useRouteMatch<{ hospitalID?: string; patientID?: string }>();
const { hospitalID, patientID } = match.params;

const { data: hospitals, isLoading: isHospitalsLoading } = useGetHospitals({
offset: 0,
limit: 100,
});
const { data: patient, isLoading: isPatientLoading } = useGetPatient(patientID ?? '');
const { data: hospital, isLoading: isHospitalLoading } = useGetHospital(hospitalID ?? '');
const { data: surgeons, isLoading: isSurgeonsLoading } = useGetSurgeons({
offset: 0,
limit: 100,
});

const hospitalPatientID = patient?.hospital_mappings.find(
(value) => value.hospital_id === hospital?.id
)?.patient_hospital_id;

const isLoading =
isHospitalLoading || isHospitalsLoading || isSurgeonsLoading || isPatientLoading;

const { mutate, isLoading: isSubmitLoading } = useRegisterEpisode(hospitalID, patientID);

const handleSubmit = (form: RegisterEpisodeFormType) => {
mutate(form);
};

const [isFormDirty, setIsFormDirty] = useState(false);
const [showWarningModal, setShowWarningModal] = useState(false);

const history = useHistory();

return (
<>
<PageWrapper>
<PageTitle>
<Icon
name="fatArrowLeft"
size={24}
color={'lightGray-700'}
onClick={() => {
if (isFormDirty) {
setShowWarningModal(true);
} else {
history.push(urls.patients());
}
}}
/>
Register an Episode
</PageTitle>
<PageSubtitle>
Please verify that the hospital of the surgery is correct. If you wish, you can choose
another hospital.
</PageSubtitle>
<Form
initialValues={{
hospital: { value: hospital?.id, label: hospital?.name },
patientHospitalId: hospitalPatientID,
surgeons: [{}, {}],
}}
validate={formValidation}
mutators={{
...arrayMutators,
}}
onSubmit={handleSubmit}
>
{({ handleSubmit, values, dirty, valid, submitting }) => {
if (dirty) {
setIsFormDirty(true);
}

return (
<form
onSubmit={handleSubmit}
css={{
display: 'flex',
flexDirection: 'column',
height: 'calc(100vh)',
overflow: 'hidden',
}}
>
{patient && surgeons && hospitals && hospital && (
<RegisterEpisodeForm
values={values}
surgeons={surgeons?.results ?? []}
patient={patient}
selectedHospital={hospital}
hospitals={hospitals?.results ?? []}
/>
)}
<ButtonContainer>
<Button
color={'blue-500'}
buttonType="button"
onClick={handleSubmit}
disabled={isLoading || !valid || submitting || isSubmitLoading}
block
size="md"
>
Register an Episode
</Button>
</ButtonContainer>
</form>
);
}}
</Form>
</PageWrapper>
{showWarningModal && (
<ConfirmationModal
onClose={() => {
setShowWarningModal(false);
}}
title={'Cancel new registration?'}
subtitle={
'Are you sure you want to cancel registering an episode? All information you’ve entered will be lost!'
}
buttonText={'Yes, cancel new addition'}
onClick={() => history.push(`${urls.patients()}/${hospitalID}/${patientID}`)}
/>
)}
</>
);
};

export default RegisterEpisode;
Loading