From 8e1a8aa634bef773e51ded913809734402d3408a Mon Sep 17 00:00:00 2001
From: Rio Knightley
Date: Tue, 13 Feb 2024 11:07:42 +0000
Subject: [PATCH 01/15] Move arf components
---
.../completeStage/CompleteStage.test.tsx | 8 ++++----
.../{ => _arf}/completeStage/CompleteStage.tsx | 2 +-
.../documentInputForm/DocumentInputForm.tsx | 4 ++--
.../DocumentSearchResults.test.tsx | 6 +++---
.../DocumentSearchResults.tsx | 4 ++--
.../DocumentSearchResultsOptions.test.tsx | 10 +++++-----
.../DocumentSearchResultsOptions.tsx | 16 ++++++++--------
.../{ => _arf}/selectStage/SelectStage.test.tsx | 12 ++++++------
.../{ => _arf}/selectStage/SelectStage.tsx | 6 +++---
.../uploadSummary/UploadSummary.test.tsx | 12 ++++++------
.../{ => _arf}/uploadSummary/UploadSummary.tsx | 10 +++++-----
.../uploadingStage/UploadingStage.test.tsx | 4 ++--
.../{ => _arf}/uploadingStage/UploadingStage.tsx | 4 ++--
.../DocumentSearchResultsPage.tsx | 4 ++--
.../uploadDocumentsPage/UploadDocumentsPage.tsx | 6 +++---
15 files changed, 54 insertions(+), 54 deletions(-)
rename app/src/components/blocks/{ => _arf}/completeStage/CompleteStage.test.tsx (91%)
rename app/src/components/blocks/{ => _arf}/completeStage/CompleteStage.tsx (90%)
rename app/src/components/blocks/{ => _arf}/documentInputForm/DocumentInputForm.tsx (97%)
rename app/src/components/blocks/{ => _arf}/documentSearchResults/DocumentSearchResults.test.tsx (90%)
rename app/src/components/blocks/{ => _arf}/documentSearchResults/DocumentSearchResults.tsx (93%)
rename app/src/components/blocks/{ => _arf}/documentSearchResultsOptions/DocumentSearchResultsOptions.test.tsx (95%)
rename app/src/components/blocks/{ => _arf}/documentSearchResultsOptions/DocumentSearchResultsOptions.tsx (85%)
rename app/src/components/blocks/{ => _arf}/selectStage/SelectStage.test.tsx (97%)
rename app/src/components/blocks/{ => _arf}/selectStage/SelectStage.tsx (97%)
rename app/src/components/blocks/{ => _arf}/uploadSummary/UploadSummary.test.tsx (95%)
rename app/src/components/blocks/{ => _arf}/uploadSummary/UploadSummary.tsx (94%)
rename app/src/components/blocks/{ => _arf}/uploadingStage/UploadingStage.test.tsx (97%)
rename app/src/components/blocks/{ => _arf}/uploadingStage/UploadingStage.tsx (95%)
diff --git a/app/src/components/blocks/completeStage/CompleteStage.test.tsx b/app/src/components/blocks/_arf/completeStage/CompleteStage.test.tsx
similarity index 91%
rename from app/src/components/blocks/completeStage/CompleteStage.test.tsx
rename to app/src/components/blocks/_arf/completeStage/CompleteStage.test.tsx
index b5c3ba682..e2edf6ef4 100644
--- a/app/src/components/blocks/completeStage/CompleteStage.test.tsx
+++ b/app/src/components/blocks/_arf/completeStage/CompleteStage.test.tsx
@@ -4,14 +4,14 @@ import {
DOCUMENT_TYPE,
DOCUMENT_UPLOAD_STATE as documentUploadStates,
UploadDocument,
-} from '../../../types/pages/UploadDocumentsPage/types';
-import { buildPatientDetails, buildTextFile } from '../../../helpers/test/testBuilders';
+} from '../../../../types/pages/UploadDocumentsPage/types';
+import { buildPatientDetails, buildTextFile } from '../../../../helpers/test/testBuilders';
import CompleteStage from './CompleteStage';
import { useNavigate } from 'react-router';
-import usePatient from '../../../helpers/hooks/usePatient';
+import usePatient from '../../../../helpers/hooks/usePatient';
jest.mock('react-router');
-jest.mock('../../../helpers/hooks/usePatient');
+jest.mock('../../../../helpers/hooks/usePatient');
const mockedUsePatient = usePatient as jest.Mock;
const mockPatientDetails = buildPatientDetails();
diff --git a/app/src/components/blocks/completeStage/CompleteStage.tsx b/app/src/components/blocks/_arf/completeStage/CompleteStage.tsx
similarity index 90%
rename from app/src/components/blocks/completeStage/CompleteStage.tsx
rename to app/src/components/blocks/_arf/completeStage/CompleteStage.tsx
index c1ac70498..ed1d9d51f 100644
--- a/app/src/components/blocks/completeStage/CompleteStage.tsx
+++ b/app/src/components/blocks/_arf/completeStage/CompleteStage.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { Button } from 'nhsuk-react-components';
import { useNavigate } from 'react-router';
-import { UploadDocument } from '../../../types/pages/UploadDocumentsPage/types';
+import { UploadDocument } from '../../../../types/pages/UploadDocumentsPage/types';
import UploadSummary from '../uploadSummary/UploadSummary';
interface Props {
documents: Array;
diff --git a/app/src/components/blocks/documentInputForm/DocumentInputForm.tsx b/app/src/components/blocks/_arf/documentInputForm/DocumentInputForm.tsx
similarity index 97%
rename from app/src/components/blocks/documentInputForm/DocumentInputForm.tsx
rename to app/src/components/blocks/_arf/documentInputForm/DocumentInputForm.tsx
index 25d381759..f837869ea 100644
--- a/app/src/components/blocks/documentInputForm/DocumentInputForm.tsx
+++ b/app/src/components/blocks/_arf/documentInputForm/DocumentInputForm.tsx
@@ -4,8 +4,8 @@ import {
DOCUMENT_TYPE,
FileInputEvent,
UploadDocument,
-} from '../../../types/pages/UploadDocumentsPage/types';
-import formatFileSize from '../../../helpers/utils/formatFileSize';
+} from '../../../../types/pages/UploadDocumentsPage/types';
+import formatFileSize from '../../../../helpers/utils/formatFileSize';
import { FieldValues, UseControllerReturn } from 'react-hook-form';
type Props = {
diff --git a/app/src/components/blocks/documentSearchResults/DocumentSearchResults.test.tsx b/app/src/components/blocks/_arf/documentSearchResults/DocumentSearchResults.test.tsx
similarity index 90%
rename from app/src/components/blocks/documentSearchResults/DocumentSearchResults.test.tsx
rename to app/src/components/blocks/_arf/documentSearchResults/DocumentSearchResults.test.tsx
index 8724aa1e8..07f6fb8c6 100644
--- a/app/src/components/blocks/documentSearchResults/DocumentSearchResults.test.tsx
+++ b/app/src/components/blocks/_arf/documentSearchResults/DocumentSearchResults.test.tsx
@@ -1,6 +1,6 @@
-import { buildSearchResult } from '../../../helpers/test/testBuilders';
-import { getFormattedDatetime } from '../../../helpers/utils/formatDatetime';
-import { SearchResult } from '../../../types/generic/searchResult';
+import { buildSearchResult } from '../../../../helpers/test/testBuilders';
+import { getFormattedDatetime } from '../../../../helpers/utils/formatDatetime';
+import { SearchResult } from '../../../../types/generic/searchResult';
import DocumentSearchResults from './DocumentSearchResults';
import { render, screen, within } from '@testing-library/react';
diff --git a/app/src/components/blocks/documentSearchResults/DocumentSearchResults.tsx b/app/src/components/blocks/_arf/documentSearchResults/DocumentSearchResults.tsx
similarity index 93%
rename from app/src/components/blocks/documentSearchResults/DocumentSearchResults.tsx
rename to app/src/components/blocks/_arf/documentSearchResults/DocumentSearchResults.tsx
index 4568dacfc..e9238cc35 100644
--- a/app/src/components/blocks/documentSearchResults/DocumentSearchResults.tsx
+++ b/app/src/components/blocks/_arf/documentSearchResults/DocumentSearchResults.tsx
@@ -1,7 +1,7 @@
import { Table } from 'nhsuk-react-components';
-import { SearchResult } from '../../../types/generic/searchResult';
+import { SearchResult } from '../../../../types/generic/searchResult';
import { useState } from 'react';
-import { getFormattedDatetime } from '../../../helpers/utils/formatDatetime';
+import { getFormattedDatetime } from '../../../../helpers/utils/formatDatetime';
type Props = {
searchResults: Array;
diff --git a/app/src/components/blocks/documentSearchResultsOptions/DocumentSearchResultsOptions.test.tsx b/app/src/components/blocks/_arf/documentSearchResultsOptions/DocumentSearchResultsOptions.test.tsx
similarity index 95%
rename from app/src/components/blocks/documentSearchResultsOptions/DocumentSearchResultsOptions.test.tsx
rename to app/src/components/blocks/_arf/documentSearchResultsOptions/DocumentSearchResultsOptions.test.tsx
index 3d170916a..fc30f0b93 100644
--- a/app/src/components/blocks/documentSearchResultsOptions/DocumentSearchResultsOptions.test.tsx
+++ b/app/src/components/blocks/_arf/documentSearchResultsOptions/DocumentSearchResultsOptions.test.tsx
@@ -3,13 +3,13 @@ import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import axios from 'axios';
import DocumentSearchResultsOptions from './DocumentSearchResultsOptions';
-import { SUBMISSION_STATE } from '../../../types/pages/documentSearchResultsPage/types';
-import { routes } from '../../../types/generic/routes';
-import { buildPatientDetails } from '../../../helpers/test/testBuilders';
+import { SUBMISSION_STATE } from '../../../../types/pages/documentSearchResultsPage/types';
+import { routes } from '../../../../types/generic/routes';
+import { buildPatientDetails } from '../../../../helpers/test/testBuilders';
const mockedUseNavigate = jest.fn();
-jest.mock('../../../helpers/hooks/useBaseAPIHeaders');
-jest.mock('../../../helpers/hooks/useBaseAPIUrl');
+jest.mock('../../../../helpers/hooks/useBaseAPIHeaders');
+jest.mock('../../../../helpers/hooks/useBaseAPIUrl');
jest.mock('axios');
jest.mock('react-router', () => ({
useNavigate: () => mockedUseNavigate,
diff --git a/app/src/components/blocks/documentSearchResultsOptions/DocumentSearchResultsOptions.tsx b/app/src/components/blocks/_arf/documentSearchResultsOptions/DocumentSearchResultsOptions.tsx
similarity index 85%
rename from app/src/components/blocks/documentSearchResultsOptions/DocumentSearchResultsOptions.tsx
rename to app/src/components/blocks/_arf/documentSearchResultsOptions/DocumentSearchResultsOptions.tsx
index 3668ec9bf..4f60e49ae 100644
--- a/app/src/components/blocks/documentSearchResultsOptions/DocumentSearchResultsOptions.tsx
+++ b/app/src/components/blocks/_arf/documentSearchResultsOptions/DocumentSearchResultsOptions.tsx
@@ -1,15 +1,15 @@
import { Button, ButtonLink } from 'nhsuk-react-components';
-import SpinnerButton from '../../generic/spinnerButton/SpinnerButton';
-import { routes } from '../../../types/generic/routes';
-import { SUBMISSION_STATE } from '../../../types/pages/documentSearchResultsPage/types';
+import SpinnerButton from '../../../generic/spinnerButton/SpinnerButton';
+import { routes } from '../../../../types/generic/routes';
+import { SUBMISSION_STATE } from '../../../../types/pages/documentSearchResultsPage/types';
import { useNavigate } from 'react-router-dom';
-import getPresignedUrlForZip from '../../../helpers/requests/getPresignedUrlForZip';
+import getPresignedUrlForZip from '../../../../helpers/requests/getPresignedUrlForZip';
import { AxiosError } from 'axios';
import { Dispatch, SetStateAction, useEffect, useRef, useState } from 'react';
-import useBaseAPIHeaders from '../../../helpers/hooks/useBaseAPIHeaders';
-import { DOCUMENT_TYPE } from '../../../types/pages/UploadDocumentsPage/types';
-import useBaseAPIUrl from '../../../helpers/hooks/useBaseAPIUrl';
-import { errorToParams } from '../../../helpers/utils/errorToParams';
+import useBaseAPIHeaders from '../../../../helpers/hooks/useBaseAPIHeaders';
+import { DOCUMENT_TYPE } from '../../../../types/pages/UploadDocumentsPage/types';
+import useBaseAPIUrl from '../../../../helpers/hooks/useBaseAPIUrl';
+import { errorToParams } from '../../../../helpers/utils/errorToParams';
type Props = {
nhsNumber: string;
diff --git a/app/src/components/blocks/selectStage/SelectStage.test.tsx b/app/src/components/blocks/_arf/selectStage/SelectStage.test.tsx
similarity index 97%
rename from app/src/components/blocks/selectStage/SelectStage.test.tsx
rename to app/src/components/blocks/_arf/selectStage/SelectStage.test.tsx
index 8a8870a6b..f22199b95 100644
--- a/app/src/components/blocks/selectStage/SelectStage.test.tsx
+++ b/app/src/components/blocks/_arf/selectStage/SelectStage.test.tsx
@@ -4,19 +4,19 @@ import {
buildPatientDetails,
buildTextFile,
buildLgFile,
-} from '../../../helpers/test/testBuilders';
+} from '../../../../helpers/test/testBuilders';
import userEvent from '@testing-library/user-event';
-import { DOCUMENT_UPLOAD_STATE as documentUploadStates } from '../../../types/pages/UploadDocumentsPage/types';
+import { DOCUMENT_UPLOAD_STATE as documentUploadStates } from '../../../../types/pages/UploadDocumentsPage/types';
import { act } from 'react-dom/test-utils';
-import { PatientDetails } from '../../../types/generic/patientDetails';
-import usePatient from '../../../helpers/hooks/usePatient';
+import { PatientDetails } from '../../../../types/generic/patientDetails';
+import usePatient from '../../../../helpers/hooks/usePatient';
-jest.mock('../../../helpers/utils/toFileList', () => ({
+jest.mock('../../../../helpers/utils/toFileList', () => ({
__esModule: true,
default: () => [],
}));
-jest.mock('../../../helpers/hooks/usePatient');
jest.mock('react-router');
+jest.mock('../../../../helpers/hooks/usePatient');
const mockedUsePatient = usePatient as jest.Mock;
const mockPatient = buildPatientDetails();
diff --git a/app/src/components/blocks/selectStage/SelectStage.tsx b/app/src/components/blocks/_arf/selectStage/SelectStage.tsx
similarity index 97%
rename from app/src/components/blocks/selectStage/SelectStage.tsx
rename to app/src/components/blocks/_arf/selectStage/SelectStage.tsx
index 435ca5a77..c9aa62d8e 100644
--- a/app/src/components/blocks/selectStage/SelectStage.tsx
+++ b/app/src/components/blocks/_arf/selectStage/SelectStage.tsx
@@ -5,11 +5,11 @@ import {
FileInputEvent,
SetUploadDocuments,
UploadDocument,
-} from '../../../types/pages/UploadDocumentsPage/types';
+} from '../../../../types/pages/UploadDocumentsPage/types';
import { Button, Fieldset } from 'nhsuk-react-components';
import { useController, useForm } from 'react-hook-form';
-import toFileList from '../../../helpers/utils/toFileList';
-import PatientSummary from '../../generic/patientSummary/PatientSummary';
+import toFileList from '../../../../helpers/utils/toFileList';
+import PatientSummary from '../../../generic/patientSummary/PatientSummary';
import DocumentInputForm from '../documentInputForm/DocumentInputForm';
interface Props {
diff --git a/app/src/components/blocks/uploadSummary/UploadSummary.test.tsx b/app/src/components/blocks/_arf/uploadSummary/UploadSummary.test.tsx
similarity index 95%
rename from app/src/components/blocks/uploadSummary/UploadSummary.test.tsx
rename to app/src/components/blocks/_arf/uploadSummary/UploadSummary.test.tsx
index 243ae80dd..be11397f8 100644
--- a/app/src/components/blocks/uploadSummary/UploadSummary.test.tsx
+++ b/app/src/components/blocks/_arf/uploadSummary/UploadSummary.test.tsx
@@ -4,17 +4,17 @@ import UploadSummary, { Props } from './UploadSummary';
import {
DOCUMENT_UPLOAD_STATE as documentUploadStates,
UploadDocument,
-} from '../../../types/pages/UploadDocumentsPage/types';
-import { formatFileSize as formatSize } from '../../../helpers/utils/formatFileSize';
-import { getFormattedDate } from '../../../helpers/utils/formatDate';
+} from '../../../../types/pages/UploadDocumentsPage/types';
+import { formatFileSize as formatSize } from '../../../../helpers/utils/formatFileSize';
+import { getFormattedDate } from '../../../../helpers/utils/formatDate';
import {
buildDocument,
buildPatientDetails,
buildTextFile,
-} from '../../../helpers/test/testBuilders';
-import usePatient from '../../../helpers/hooks/usePatient';
+} from '../../../../helpers/test/testBuilders';
+import usePatient from '../../../../helpers/hooks/usePatient';
-jest.mock('../../../helpers/hooks/usePatient');
+jest.mock('../../../../helpers/hooks/usePatient');
const mockedUsePatient = usePatient as jest.Mock;
const mockPatient = buildPatientDetails();
diff --git a/app/src/components/blocks/uploadSummary/UploadSummary.tsx b/app/src/components/blocks/_arf/uploadSummary/UploadSummary.tsx
similarity index 94%
rename from app/src/components/blocks/uploadSummary/UploadSummary.tsx
rename to app/src/components/blocks/_arf/uploadSummary/UploadSummary.tsx
index e9c355b36..71de2a4fc 100644
--- a/app/src/components/blocks/uploadSummary/UploadSummary.tsx
+++ b/app/src/components/blocks/_arf/uploadSummary/UploadSummary.tsx
@@ -3,11 +3,11 @@ import React from 'react';
import {
DOCUMENT_UPLOAD_STATE,
UploadDocument,
-} from '../../../types/pages/UploadDocumentsPage/types';
-import formatFileSize from '../../../helpers/utils/formatFileSize';
-import { getFormattedDate } from '../../../helpers/utils/formatDate';
-import ErrorBox from '../../layout/errorBox/ErrorBox';
-import PatientSummary from '../../generic/patientSummary/PatientSummary';
+} from '../../../../types/pages/UploadDocumentsPage/types';
+import formatFileSize from '../../../../helpers/utils/formatFileSize';
+import { getFormattedDate } from '../../../../helpers/utils/formatDate';
+import ErrorBox from '../../../layout/errorBox/ErrorBox';
+import PatientSummary from '../../../generic/patientSummary/PatientSummary';
export interface Props {
documents: Array;
diff --git a/app/src/components/blocks/uploadingStage/UploadingStage.test.tsx b/app/src/components/blocks/_arf/uploadingStage/UploadingStage.test.tsx
similarity index 97%
rename from app/src/components/blocks/uploadingStage/UploadingStage.test.tsx
rename to app/src/components/blocks/_arf/uploadingStage/UploadingStage.test.tsx
index b0d649e7e..772d64120 100644
--- a/app/src/components/blocks/uploadingStage/UploadingStage.test.tsx
+++ b/app/src/components/blocks/_arf/uploadingStage/UploadingStage.test.tsx
@@ -5,8 +5,8 @@ import {
DOCUMENT_UPLOAD_STATE,
DOCUMENT_UPLOAD_STATE as documentUploadStates,
UploadDocument,
-} from '../../../types/pages/UploadDocumentsPage/types';
-import { buildTextFile } from '../../../helpers/test/testBuilders';
+} from '../../../../types/pages/UploadDocumentsPage/types';
+import { buildTextFile } from '../../../../helpers/test/testBuilders';
import UploadingStage from './UploadingStage';
describe('', () => {
diff --git a/app/src/components/blocks/uploadingStage/UploadingStage.tsx b/app/src/components/blocks/_arf/uploadingStage/UploadingStage.tsx
similarity index 95%
rename from app/src/components/blocks/uploadingStage/UploadingStage.tsx
rename to app/src/components/blocks/_arf/uploadingStage/UploadingStage.tsx
index 51b895cba..a9d37ba9c 100644
--- a/app/src/components/blocks/uploadingStage/UploadingStage.tsx
+++ b/app/src/components/blocks/_arf/uploadingStage/UploadingStage.tsx
@@ -2,9 +2,9 @@ import React from 'react';
import {
UploadDocument,
DOCUMENT_UPLOAD_STATE,
-} from '../../../types/pages/UploadDocumentsPage/types';
+} from '../../../../types/pages/UploadDocumentsPage/types';
import { Table, WarningCallout } from 'nhsuk-react-components';
-import formatFileSize from '../../../helpers/utils/formatFileSize';
+import formatFileSize from '../../../../helpers/utils/formatFileSize';
interface Props {
documents: Array;
diff --git a/app/src/pages/documentSearchResultsPage/DocumentSearchResultsPage.tsx b/app/src/pages/documentSearchResultsPage/DocumentSearchResultsPage.tsx
index 14eaf27a8..918892c77 100644
--- a/app/src/pages/documentSearchResultsPage/DocumentSearchResultsPage.tsx
+++ b/app/src/pages/documentSearchResultsPage/DocumentSearchResultsPage.tsx
@@ -1,14 +1,14 @@
import React, { useEffect, useRef, useState } from 'react';
import PatientSummary from '../../components/generic/patientSummary/PatientSummary';
import { SearchResult } from '../../types/generic/searchResult';
-import DocumentSearchResults from '../../components/blocks/documentSearchResults/DocumentSearchResults';
+import DocumentSearchResults from '../../components/blocks/_arf/documentSearchResults/DocumentSearchResults';
import { useNavigate } from 'react-router';
import { routes } from '../../types/generic/routes';
import { Link } from 'react-router-dom';
import { SUBMISSION_STATE } from '../../types/pages/documentSearchResultsPage/types';
import ProgressBar from '../../components/generic/progressBar/ProgressBar';
import ServiceError from '../../components/layout/serviceErrorBox/ServiceErrorBox';
-import DocumentSearchResultsOptions from '../../components/blocks/documentSearchResultsOptions/DocumentSearchResultsOptions';
+import DocumentSearchResultsOptions from '../../components/blocks/_arf/documentSearchResultsOptions/DocumentSearchResultsOptions';
import { AxiosError } from 'axios';
import getDocumentSearchResults from '../../helpers/requests/getDocumentSearchResults';
import useBaseAPIHeaders from '../../helpers/hooks/useBaseAPIHeaders';
diff --git a/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.tsx b/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.tsx
index ce5a32006..3dda00c05 100644
--- a/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.tsx
+++ b/app/src/pages/uploadDocumentsPage/UploadDocumentsPage.tsx
@@ -6,9 +6,9 @@ import {
UploadDocument,
} from '../../types/pages/UploadDocumentsPage/types';
import uploadDocument from '../../helpers/requests/uploadDocument';
-import SelectStage from '../../components/blocks/selectStage/SelectStage';
-import UploadingStage from '../../components/blocks/uploadingStage/UploadingStage';
-import CompleteStage from '../../components/blocks/completeStage/CompleteStage';
+import SelectStage from '../../components/blocks/_arf/selectStage/SelectStage';
+import UploadingStage from '../../components/blocks/_arf/uploadingStage/UploadingStage';
+import CompleteStage from '../../components/blocks/_arf/completeStage/CompleteStage';
import useBaseAPIHeaders from '../../helpers/hooks/useBaseAPIHeaders';
import usePatient from '../../helpers/hooks/usePatient';
import useBaseAPIUrl from '../../helpers/hooks/useBaseAPIUrl';
From e4509ae2647c8a164e1f8854c103bff69541f6ba Mon Sep 17 00:00:00 2001
From: Rio Knightley
Date: Tue, 13 Feb 2024 12:14:28 +0000
Subject: [PATCH 02/15] Add lloyd george upload page
---
.../LloydGeorgeUploadingStage.tsx | 59 +++++++++++++++++++
.../LloydGeorgeUploadPage.tsx | 10 ++++
.../PatientResultPage.test.tsx | 4 +-
.../patientResultPage/PatientResultPage.tsx | 5 +-
app/src/router/AppRouter.tsx | 29 +++++----
app/src/types/generic/routes.ts | 5 +-
6 files changed, 95 insertions(+), 17 deletions(-)
create mode 100644 app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.tsx
create mode 100644 app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
diff --git a/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.tsx b/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.tsx
new file mode 100644
index 000000000..559d40a68
--- /dev/null
+++ b/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.tsx
@@ -0,0 +1,59 @@
+import React from 'react';
+import { buildDocument, buildTextFile } from '../../../helpers/test/testBuilders';
+import { DOCUMENT_UPLOAD_STATE } from '../../../types/pages/UploadDocumentsPage/types';
+import { Table } from 'nhsuk-react-components';
+import formatFileSize from '../../../helpers/utils/formatFileSize';
+
+type Props = {};
+
+function LloydGeorgeUploadStage({}: Props) {
+ const files = [buildTextFile('one', 100), buildTextFile('two', 101)];
+ const documents = files.map((file) => buildDocument(file, DOCUMENT_UPLOAD_STATE.SUCCEEDED));
+ const getUploadMessage = (type: DOCUMENT_UPLOAD_STATE) => {
+ if (type === DOCUMENT_UPLOAD_STATE.SELECTED) return 'Waiting...';
+ else if (type === DOCUMENT_UPLOAD_STATE.UPLOADING) return 'Uploading...';
+ else if (type === DOCUMENT_UPLOAD_STATE.SUCCEEDED) return 'Uploaded';
+ else if (type === DOCUMENT_UPLOAD_STATE.FAILED) return 'Upload failed';
+ };
+ return (
+
+
+
+ File Name
+ File Size
+ File Upload Progress
+
+
+
+ {documents.map((document) => (
+
+ {document.file.name}
+ {formatFileSize(document.file.size)}
+
+
+
+ {document.state === DOCUMENT_UPLOAD_STATE.UPLOADING ? (
+ <> {Math.round(document.progress)}% uploaded... >
+ ) : (
+ <>{getUploadMessage(document.state)}>
+ )}
+
+
+
+ ))}
+
+
+ );
+}
+
+export default LloydGeorgeUploadStage;
diff --git a/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx b/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
new file mode 100644
index 000000000..a54f0a9e8
--- /dev/null
+++ b/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
@@ -0,0 +1,10 @@
+import React from 'react';
+import LloydGeorgeUploadStage from '../../components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage';
+
+type Props = {};
+
+function LloydGeorgeUploadPage({}: Props) {
+ return ;
+}
+
+export default LloydGeorgeUploadPage;
diff --git a/app/src/pages/patientResultPage/PatientResultPage.test.tsx b/app/src/pages/patientResultPage/PatientResultPage.test.tsx
index e8bad6098..1ab77b15a 100644
--- a/app/src/pages/patientResultPage/PatientResultPage.test.tsx
+++ b/app/src/pages/patientResultPage/PatientResultPage.test.tsx
@@ -195,7 +195,7 @@ describe('PatientResultPage', () => {
});
await waitFor(() => {
- expect(mockedUseNavigate).toHaveBeenCalledWith(routes.UPLOAD_DOCUMENTS);
+ expect(mockedUseNavigate).toHaveBeenCalledWith(routes.ARF_UPLOAD_DOCUMENTS);
});
},
);
@@ -230,7 +230,7 @@ describe('PatientResultPage', () => {
userEvent.click(screen.getByRole('button', { name: 'Accept details are correct' }));
await waitFor(() => {
- expect(mockedUseNavigate).toHaveBeenCalledWith(routes.DOWNLOAD_DOCUMENTS);
+ expect(mockedUseNavigate).toHaveBeenCalledWith(routes.ARF_DOWNLOAD_DOCUMENTS);
});
});
});
diff --git a/app/src/pages/patientResultPage/PatientResultPage.tsx b/app/src/pages/patientResultPage/PatientResultPage.tsx
index 3dcc2a026..b699a4568 100644
--- a/app/src/pages/patientResultPage/PatientResultPage.tsx
+++ b/app/src/pages/patientResultPage/PatientResultPage.tsx
@@ -30,14 +30,15 @@ function PatientResultPage() {
if (patientDetails?.active) {
navigate(routes.LLOYD_GEORGE);
} else {
- navigate(routes.UPLOAD_DOCUMENTS);
+ // TODO: What do we use to decide ARF route or LG route ?
+ navigate(routes.ARF_UPLOAD_DOCUMENTS);
}
}
// PCSE Role
else if (userIsPCSE) {
// Make PDS and Dynamo document store search request to download documents from patient
- navigate(routes.DOWNLOAD_DOCUMENTS);
+ navigate(routes.ARF_DOWNLOAD_DOCUMENTS);
}
};
const showWarning = patientDetails?.superseded || patientDetails?.restricted;
diff --git a/app/src/router/AppRouter.tsx b/app/src/router/AppRouter.tsx
index 5d7a147e1..a37b2b899 100644
--- a/app/src/router/AppRouter.tsx
+++ b/app/src/router/AppRouter.tsx
@@ -10,8 +10,8 @@ import UnauthorisedPage from '../pages/unauthorisedPage/UnauthorisedPage';
import LogoutPage from '../pages/logoutPage/LogoutPage';
import PatientSearchPage from '../pages/patientSearchPage/PatientSearchPage';
import PatientResultPage from '../pages/patientResultPage/PatientResultPage';
-import UploadDocumentsPage from '../pages/uploadDocumentsPage/UploadDocumentsPage';
-import DocumentSearchResultsPage from '../pages/documentSearchResultsPage/DocumentSearchResultsPage';
+import ArfUploadDocumentsPage from '../pages/uploadDocumentsPage/UploadDocumentsPage';
+import ArfSearchResultsPage from '../pages/documentSearchResultsPage/DocumentSearchResultsPage';
import LloydGeorgeRecordPage from '../pages/lloydGeorgeRecordPage/LloydGeorgeRecordPage';
import AuthGuard from './guards/authGuard/AuthGuard';
import PatientGuard from './guards/patientGuard/PatientGuard';
@@ -23,6 +23,7 @@ import FeedbackPage from '../pages/feedbackPage/FeedbackPage';
import ServerErrorPage from '../pages/serverErrorPage/ServerErrorPage';
import PrivacyPage from '../pages/privacyPage/PrivacyPage';
import useFeatureFlags from '../helpers/hooks/useFeatureFlags';
+import LloydGeorgeUploadPage from '../pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage';
const {
START,
@@ -35,12 +36,13 @@ const {
SERVER_ERROR,
FEEDBACK,
LOGOUT,
- DOWNLOAD_DOCUMENTS,
- LLOYD_GEORGE,
SEARCH_PATIENT,
VERIFY_PATIENT,
- UPLOAD_DOCUMENTS,
PRIVACY_POLICY,
+ LLOYD_GEORGE,
+ LLOYD_GEORGE_UPLOAD,
+ ARF_DOWNLOAD_DOCUMENTS,
+ ARF_UPLOAD_DOCUMENTS,
} = routes;
type Routes = {
@@ -104,18 +106,23 @@ export const routeMap: Routes = {
page: ,
type: ROUTE_TYPE.PATIENT,
},
- [UPLOAD_DOCUMENTS]: {
- page: ,
+ [LLOYD_GEORGE]: {
+ page: ,
type: ROUTE_TYPE.PATIENT,
unauthorized: [REPOSITORY_ROLE.PCSE],
},
- [DOWNLOAD_DOCUMENTS]: {
- page: ,
+ [LLOYD_GEORGE_UPLOAD]: {
+ page: ,
+ type: ROUTE_TYPE.PATIENT,
+ unauthorized: [REPOSITORY_ROLE.PCSE],
+ },
+ [ARF_DOWNLOAD_DOCUMENTS]: {
+ page: ,
type: ROUTE_TYPE.PATIENT,
unauthorized: [REPOSITORY_ROLE.GP_ADMIN, REPOSITORY_ROLE.GP_CLINICAL],
},
- [LLOYD_GEORGE]: {
- page: ,
+ [ARF_UPLOAD_DOCUMENTS]: {
+ page: ,
type: ROUTE_TYPE.PATIENT,
unauthorized: [REPOSITORY_ROLE.PCSE],
},
diff --git a/app/src/types/generic/routes.ts b/app/src/types/generic/routes.ts
index 2cea76a7c..02dd00d84 100644
--- a/app/src/types/generic/routes.ts
+++ b/app/src/types/generic/routes.ts
@@ -15,8 +15,9 @@ export enum routes {
SEARCH_PATIENT = '/search/patient',
VERIFY_PATIENT = '/search/patient/verify',
LLOYD_GEORGE = '/patient/view/lloyd-george-record',
- DOWNLOAD_DOCUMENTS = '/patient/download',
- UPLOAD_DOCUMENTS = '/patient/upload',
+ LLOYD_GEORGE_UPLOAD = '/patient/upload/lloyd-george-record',
+ ARF_DOWNLOAD_DOCUMENTS = '/patient/download',
+ ARF_UPLOAD_DOCUMENTS = '/patient/upload',
}
export enum ROUTE_TYPE {
From d068fdc81b22a454c47c63784d496d4fd6d6df8f Mon Sep 17 00:00:00 2001
From: Rio Knightley
Date: Tue, 13 Feb 2024 15:54:42 +0000
Subject: [PATCH 03/15] Lloyd george upload stage
---
.../LloydGeorgeRecordError.tsx | 7 +-
.../LloydGeorgeUploadingStage.test.tsx | 137 ++++++++++++++++++
.../LloydGeorgeUploadingStage.tsx | 118 ++++++++-------
.../LloydGeorgeUploadPage.tsx | 50 ++++++-
4 files changed, 260 insertions(+), 52 deletions(-)
create mode 100644 app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.test.tsx
diff --git a/app/src/components/blocks/lloydGeorgeRecordError/LloydGeorgeRecordError.tsx b/app/src/components/blocks/lloydGeorgeRecordError/LloydGeorgeRecordError.tsx
index a660519a5..2cb1ccbdb 100644
--- a/app/src/components/blocks/lloydGeorgeRecordError/LloydGeorgeRecordError.tsx
+++ b/app/src/components/blocks/lloydGeorgeRecordError/LloydGeorgeRecordError.tsx
@@ -53,7 +53,12 @@ function LloydGeorgeRecordError({ downloadStage, setStage }: Props) {
once the record is uploaded.
-
+ {
+ navigate(routes.LLOYD_GEORGE_UPLOAD);
+ }}
+ >
Upload patient record
diff --git a/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.test.tsx b/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.test.tsx
new file mode 100644
index 000000000..462132e59
--- /dev/null
+++ b/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.test.tsx
@@ -0,0 +1,137 @@
+import { render, screen } from '@testing-library/react';
+import { act } from 'react-dom/test-utils';
+import {
+ DOCUMENT_TYPE,
+ DOCUMENT_UPLOAD_STATE,
+ UploadDocument,
+} from '../../../types/pages/UploadDocumentsPage/types';
+import { buildTextFile } from '../../../helpers/test/testBuilders';
+import LloydGeorgeUploadStage from './LloydGeorgeUploadingStage';
+const mockSetStage = jest.fn();
+describe('', () => {
+ describe('with NHS number', () => {
+ const triggerUploadStateChange = (
+ document: UploadDocument,
+ state: DOCUMENT_UPLOAD_STATE,
+ progress: number,
+ ) => {
+ act(() => {
+ document.state = state;
+ document.progress = progress;
+ });
+ };
+
+ it('uploads documents and displays the progress', async () => {
+ const documentOne = {
+ file: buildTextFile('one', 100),
+ state: DOCUMENT_UPLOAD_STATE.UPLOADING,
+ id: '1',
+ progress: 50,
+ docType: DOCUMENT_TYPE.LLOYD_GEORGE,
+ };
+ render();
+
+ triggerUploadStateChange(documentOne, DOCUMENT_UPLOAD_STATE.UPLOADING, 0);
+
+ expect(screen.queryByTestId('upload-document-form')).not.toBeInTheDocument();
+ expect(
+ screen.getByText(
+ 'Do not close or navigate away from this browser until upload is complete. Each file will be uploaded and combined into one record.',
+ ),
+ ).toBeInTheDocument();
+ expect(screen.getByText('50% uploaded...')).toBeInTheDocument();
+ });
+
+ it('progress bar reflect the upload progress', async () => {
+ const documentOne = {
+ file: buildTextFile('one', 100),
+ state: DOCUMENT_UPLOAD_STATE.SELECTED,
+ id: '1',
+ progress: 0,
+ docType: DOCUMENT_TYPE.ARF,
+ };
+ const documentTwo = {
+ file: buildTextFile('two', 200),
+ state: DOCUMENT_UPLOAD_STATE.SELECTED,
+ id: '2',
+ progress: 0,
+ docType: DOCUMENT_TYPE.ARF,
+ };
+ const documentThree = {
+ file: buildTextFile('three', 100),
+ state: DOCUMENT_UPLOAD_STATE.SELECTED,
+ id: '3',
+ progress: 0,
+ docType: DOCUMENT_TYPE.ARF,
+ };
+
+ const { rerender } = render(
+ ,
+ );
+ const getProgressBarValue = (document: UploadDocument) => {
+ const progressBar: HTMLProgressElement = screen.getByRole('progressbar', {
+ name: `Uploading ${document.file.name}`,
+ });
+ return progressBar.value;
+ };
+ const getProgressText = (document: UploadDocument) => {
+ return screen.getByRole('status', {
+ name: `${document.file.name} upload status`,
+ }).textContent;
+ };
+
+ triggerUploadStateChange(documentOne, DOCUMENT_UPLOAD_STATE.UPLOADING, 10);
+ rerender(
+ ,
+ );
+ expect(getProgressBarValue(documentOne)).toEqual(10);
+ expect(getProgressText(documentOne)).toContain('10% uploaded...');
+
+ triggerUploadStateChange(documentOne, DOCUMENT_UPLOAD_STATE.UPLOADING, 70);
+ rerender(
+ ,
+ );
+ expect(getProgressBarValue(documentOne)).toEqual(70);
+ expect(getProgressText(documentOne)).toContain('70% uploaded...');
+
+ triggerUploadStateChange(documentTwo, DOCUMENT_UPLOAD_STATE.UPLOADING, 20);
+ rerender(
+ ,
+ );
+ expect(getProgressBarValue(documentTwo)).toEqual(20);
+ expect(getProgressText(documentTwo)).toContain('20% uploaded...');
+
+ triggerUploadStateChange(documentTwo, DOCUMENT_UPLOAD_STATE.SUCCEEDED, 100);
+ rerender(
+ ,
+ );
+ expect(getProgressBarValue(documentTwo)).toEqual(100);
+ expect(getProgressText(documentTwo)).toContain('Upload successful');
+
+ triggerUploadStateChange(documentOne, DOCUMENT_UPLOAD_STATE.FAILED, 0);
+ rerender(
+ ,
+ );
+ expect(getProgressBarValue(documentOne)).toEqual(0);
+ expect(getProgressText(documentOne)).toContain('Upload failed');
+ });
+ });
+});
diff --git a/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.tsx b/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.tsx
index 559d40a68..6af717d8a 100644
--- a/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.tsx
+++ b/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.tsx
@@ -1,58 +1,78 @@
-import React from 'react';
-import { buildDocument, buildTextFile } from '../../../helpers/test/testBuilders';
-import { DOCUMENT_UPLOAD_STATE } from '../../../types/pages/UploadDocumentsPage/types';
-import { Table } from 'nhsuk-react-components';
+import React, { Dispatch, SetStateAction } from 'react';
+import {
+ DOCUMENT_UPLOAD_STATE,
+ UploadDocument,
+} from '../../../types/pages/UploadDocumentsPage/types';
+import { Table, WarningCallout } from 'nhsuk-react-components';
import formatFileSize from '../../../helpers/utils/formatFileSize';
+import { LG_UPLOAD_STAGE } from '../../../pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage';
-type Props = {};
+type Props = {
+ documents: Array;
+ setStage: Dispatch>;
+};
-function LloydGeorgeUploadStage({}: Props) {
- const files = [buildTextFile('one', 100), buildTextFile('two', 101)];
- const documents = files.map((file) => buildDocument(file, DOCUMENT_UPLOAD_STATE.SUCCEEDED));
- const getUploadMessage = (type: DOCUMENT_UPLOAD_STATE) => {
- if (type === DOCUMENT_UPLOAD_STATE.SELECTED) return 'Waiting...';
- else if (type === DOCUMENT_UPLOAD_STATE.UPLOADING) return 'Uploading...';
- else if (type === DOCUMENT_UPLOAD_STATE.SUCCEEDED) return 'Uploaded';
- else if (type === DOCUMENT_UPLOAD_STATE.FAILED) return 'Upload failed';
+function LloydGeorgeUploadStage({ documents, setStage }: Props) {
+ const getUploadMessage = (document: UploadDocument) => {
+ if (document.state === DOCUMENT_UPLOAD_STATE.SELECTED) return 'Waiting...';
+ else if (document.state === DOCUMENT_UPLOAD_STATE.UPLOADING)
+ return `${Math.round(document.progress)}% uploaded...`;
+ else if (document.state === DOCUMENT_UPLOAD_STATE.SUCCEEDED) return 'Upload successful';
+ else if (document.state === DOCUMENT_UPLOAD_STATE.FAILED) return 'Upload failed';
};
return (
-
-
-
- File Name
- File Size
- File Upload Progress
-
-
-
- {documents.map((document) => (
-
- {document.file.name}
- {formatFileSize(document.file.size)}
-
-
-
- {document.state === DOCUMENT_UPLOAD_STATE.UPLOADING ? (
- <> {Math.round(document.progress)}% uploaded... >
- ) : (
- <>{getUploadMessage(document.state)}>
- )}
-
-
+ <>
+
+ Uploading record
+
+ Stay on this page
+
+ Do not close or navigate away from this browser until upload is complete. Each
+ file will be uploaded and combined into one record.
+
+
+
+
+
+ Filename
+ Size
+ Upload Progress
- ))}
-
-
+
+
+ {documents.map((document) => (
+
+ {document.file.name}
+
+ {formatFileSize(document.file.size)}
+
+
+
+
+ {getUploadMessage(document)}
+
+
+
+ ))}
+
+
+ >
);
}
diff --git a/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx b/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
index a54f0a9e8..f9d8ce30c 100644
--- a/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
+++ b/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
@@ -1,10 +1,56 @@
-import React from 'react';
+import React, { useState } from 'react';
import LloydGeorgeUploadStage from '../../components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage';
+import { buildDocument, buildTextFile } from '../../helpers/test/testBuilders';
+import { DOCUMENT_UPLOAD_STATE } from '../../types/pages/UploadDocumentsPage/types';
type Props = {};
+export enum LG_UPLOAD_STAGE {
+ SELECT = 0,
+ UPLOAD = 1,
+ COMPLETE = 2,
+}
+
function LloydGeorgeUploadPage({}: Props) {
- return ;
+ const [stage, setStage] = useState(LG_UPLOAD_STAGE.SELECT);
+ const files = [
+ buildTextFile('1of3_Lloyd_George_Record_[Barry ONEIL]_[9730182000]_[23-10-2018]', 100),
+ buildTextFile('2of3_Lloyd_George_Record_[Barry ONEIL]_[9730182000]_[23-10-2018]', 101),
+ ];
+ const documents = files.map((file) => {
+ return {
+ ...buildDocument(file, DOCUMENT_UPLOAD_STATE.SUCCEEDED),
+ progress: 100,
+ };
+ });
+ switch (stage) {
+ case LG_UPLOAD_STAGE.SELECT:
+ return (
+ // TODO, ADD FILE SELECT STAGE
+
+
+
select files
+
+ );
+ case LG_UPLOAD_STAGE.UPLOAD:
+ return ;
+ case LG_UPLOAD_STAGE.COMPLETE:
+ return (
+ // TODO, ADD UPLOAD COMPLETE STAGE
+
+
+
upload complete
+
+ );
+ default:
+ return null;
+ }
}
export default LloydGeorgeUploadPage;
From c4228b2b81f45eedbcab28c8e036bdcbba07feb6 Mon Sep 17 00:00:00 2001
From: Rio Knightley
Date: Wed, 14 Feb 2024 15:01:50 +0000
Subject: [PATCH 04/15] Add file input stage for lg upload
---
.../blocks/_arf/selectStage/SelectStage.tsx | 2 +-
.../LloydGeorgeFileInputStage.tsx | 244 ++++++++++++++++++
.../LloydGeorgeUploadingStage.test.tsx | 2 +-
.../LloydGeorgeUploadPage.tsx | 39 +--
4 files changed, 266 insertions(+), 21 deletions(-)
create mode 100644 app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
diff --git a/app/src/components/blocks/_arf/selectStage/SelectStage.tsx b/app/src/components/blocks/_arf/selectStage/SelectStage.tsx
index cb20f998a..2e1618f61 100644
--- a/app/src/components/blocks/_arf/selectStage/SelectStage.tsx
+++ b/app/src/components/blocks/_arf/selectStage/SelectStage.tsx
@@ -11,7 +11,7 @@ import { useController, useForm } from 'react-hook-form';
import toFileList from '../../../../helpers/utils/toFileList';
import PatientSummary from '../../../generic/patientSummary/PatientSummary';
import DocumentInputForm from '../documentInputForm/DocumentInputForm';
-import { ARFFormConfig, lloydGeorgeFormConfig } from '../../../helpers/utils/formConfig';
+import { ARFFormConfig, lloydGeorgeFormConfig } from '../../../../helpers/utils/formConfig';
interface Props {
uploadDocuments: () => void;
diff --git a/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx b/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
new file mode 100644
index 000000000..4da1b61ea
--- /dev/null
+++ b/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
@@ -0,0 +1,244 @@
+import React, { Dispatch, SetStateAction, useRef } from 'react';
+import BackButton from '../../../components/generic/backButton/BackButton';
+import { formatNhsNumber } from '../../../helpers/utils/formatNhsNumber';
+import { getFormattedDate } from '../../../helpers/utils/formatDate';
+import { buildPatientDetails } from '../../../helpers/test/testBuilders';
+import { Input, Button, Fieldset, InsetText, Table } from 'nhsuk-react-components';
+import { ReactComponent as FileSVG } from '../../../styles/file-input.svg';
+import {
+ DOCUMENT_TYPE,
+ DOCUMENT_UPLOAD_STATE,
+ FileInputEvent,
+ UploadDocument,
+} from '../../../types/pages/UploadDocumentsPage/types';
+import { useController, useForm } from 'react-hook-form';
+import formatFileSize from '../../../helpers/utils/formatFileSize';
+import { lloydGeorgeFormConfig } from '../../../helpers/utils/formConfig';
+import uploadDocument from '../../../helpers/requests/uploadDocument';
+import useBaseAPIUrl from '../../../helpers/hooks/useBaseAPIUrl';
+import useBaseAPIHeaders from '../../../helpers/hooks/useBaseAPIHeaders';
+import { LG_UPLOAD_STAGE } from '../../../pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage';
+
+type Props = {
+ documents: Array;
+ setDocuments: Dispatch>>;
+ setStage: Dispatch>;
+};
+
+function LloydGeorgeFileInputStage({ documents, setDocuments, setStage }: Props) {
+ const patientDetails = buildPatientDetails();
+ const nhsNumber: string = patientDetails?.nhsNumber || '';
+ const formattedNhsNumber = formatNhsNumber(nhsNumber);
+ const dob: String = patientDetails?.birthDate
+ ? getFormattedDate(new Date(patientDetails.birthDate))
+ : '';
+ let fileInputRef = useRef(null);
+
+ const { handleSubmit, control, formState } = useForm();
+ const lgController = useController(lloydGeorgeFormConfig(control));
+
+ const hasFileInput = documents.length;
+ const baseUrl = useBaseAPIUrl();
+ const baseHeaders = useBaseAPIHeaders();
+
+ const uploadDocuments = async () => {
+ try {
+ if (patientDetails) {
+ setStage(LG_UPLOAD_STAGE.UPLOAD);
+ await uploadDocument({
+ nhsNumber: patientDetails.nhsNumber,
+ setDocuments,
+ documents: documents,
+ baseUrl,
+ baseHeaders,
+ });
+ }
+ } catch (e) {}
+ };
+ const updateFileList = (fileArray: File[]) => {
+ const documentMap: Array = fileArray.map((file) => ({
+ id: Math.floor(Math.random() * 1000000).toString(),
+ file,
+ state: DOCUMENT_UPLOAD_STATE.SELECTED,
+ progress: 0,
+ docType: DOCUMENT_TYPE.LLOYD_GEORGE,
+ }));
+ const updatedDocList = [...documentMap, ...documents];
+ setDocuments(updatedDocList);
+ lgController.field.onChange(updatedDocList);
+ };
+ const onFileDrop = (e: React.DragEvent) => {
+ e.preventDefault();
+ e.stopPropagation();
+ let fileArray: File[] = [];
+ if (e.dataTransfer.items) {
+ [...e.dataTransfer.items].forEach((item) => {
+ const file = item.getAsFile();
+
+ if (item.kind === 'file' && file) {
+ fileArray.push(file);
+ }
+ });
+ } else if (e.dataTransfer.files) {
+ fileArray = [...e.dataTransfer.files];
+ }
+ if (fileArray) {
+ updateFileList(fileArray);
+ }
+ };
+ const onInput = (e: FileInputEvent) => {
+ const fileArray = Array.from(e.target.files ?? new FileList());
+ updateFileList(fileArray);
+ };
+ const onRemove = (index: number) => {
+ let updatedDocList: UploadDocument[] = [];
+ if (index >= 0) {
+ updatedDocList = [...documents.slice(0, index), ...documents.slice(index + 1)];
+ }
+ setDocuments(updatedDocList);
+ lgController.field.onChange(updatedDocList);
+ };
+
+ return (
+
+ );
+}
+
+export default LloydGeorgeFileInputStage;
diff --git a/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.test.tsx b/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.test.tsx
index 462132e59..df4442b16 100644
--- a/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.test.tsx
+++ b/app/src/components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage.test.tsx
@@ -8,7 +8,7 @@ import {
import { buildTextFile } from '../../../helpers/test/testBuilders';
import LloydGeorgeUploadStage from './LloydGeorgeUploadingStage';
const mockSetStage = jest.fn();
-describe('', () => {
+describe('', () => {
describe('with NHS number', () => {
const triggerUploadStateChange = (
document: UploadDocument,
diff --git a/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx b/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
index f9d8ce30c..0ba88dacb 100644
--- a/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
+++ b/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
-import LloydGeorgeUploadStage from '../../components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage';
-import { buildDocument, buildTextFile } from '../../helpers/test/testBuilders';
-import { DOCUMENT_UPLOAD_STATE } from '../../types/pages/UploadDocumentsPage/types';
+import LloydGeorgeUploadingStage from '../../components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage';
+import { UploadDocument } from '../../types/pages/UploadDocumentsPage/types';
+import LloydGeorgeFileInputStage from '../../components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage';
type Props = {};
@@ -13,27 +13,28 @@ export enum LG_UPLOAD_STAGE {
function LloydGeorgeUploadPage({}: Props) {
const [stage, setStage] = useState(LG_UPLOAD_STAGE.SELECT);
- const files = [
- buildTextFile('1of3_Lloyd_George_Record_[Barry ONEIL]_[9730182000]_[23-10-2018]', 100),
- buildTextFile('2of3_Lloyd_George_Record_[Barry ONEIL]_[9730182000]_[23-10-2018]', 101),
- ];
- const documents = files.map((file) => {
- return {
- ...buildDocument(file, DOCUMENT_UPLOAD_STATE.SUCCEEDED),
- progress: 100,
- };
- });
+ const [documents, setDocuments] = useState>([]);
+ // const files = [
+ // buildTextFile('1of3_Lloyd_George_Record_[Barry ONEIL]_[9730182000]_[23-10-2018]', 100),
+ // buildTextFile('2of3_Lloyd_George_Record_[Barry ONEIL]_[9730182000]_[23-10-2018]', 101),
+ // ];
+ // const documents = files.map((file) => {
+ // return {
+ // ...buildDocument(file, DOCUMENT_UPLOAD_STATE.SUCCEEDED),
+ // progress: 100,
+ // };
+ // });
switch (stage) {
case LG_UPLOAD_STAGE.SELECT:
return (
- // TODO, ADD FILE SELECT STAGE
-
-
-
select files
-
+
);
case LG_UPLOAD_STAGE.UPLOAD:
- return ;
+ return ;
case LG_UPLOAD_STAGE.COMPLETE:
return (
// TODO, ADD UPLOAD COMPLETE STAGE
From f6da6858e33017a81fa2f1ef421b6ad9eaf2c070 Mon Sep 17 00:00:00 2001
From: Rio Knightley
Date: Wed, 14 Feb 2024 15:24:14 +0000
Subject: [PATCH 05/15] Add jiggins lane fake pds patient
---
.../pds_patient_9000000004_M85143_gp.json | 399 ++++++++++++++++++
lambdas/services/mock_pds_service.py | 2 +
2 files changed, 401 insertions(+)
create mode 100644 lambdas/services/mock_data/pds_patient_9000000004_M85143_gp.json
diff --git a/lambdas/services/mock_data/pds_patient_9000000004_M85143_gp.json b/lambdas/services/mock_data/pds_patient_9000000004_M85143_gp.json
new file mode 100644
index 000000000..3b213b7f6
--- /dev/null
+++ b/lambdas/services/mock_data/pds_patient_9000000004_M85143_gp.json
@@ -0,0 +1,399 @@
+{
+ "resourceType": "Patient",
+ "id": "9000000004",
+ "identifier": [
+ {
+ "system": "https://fhir.nhs.uk/Id/nhs-number",
+ "value": "9000000004",
+ "extension": [
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSNumberVerificationStatus",
+ "valueCodeableConcept": {
+ "coding": [
+ {
+ "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-NHSNumberVerificationStatus",
+ "version": "1.0.0",
+ "code": "01",
+ "display": "Number present and verified"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ],
+ "meta": {
+ "versionId": "2",
+ "security": [
+ {
+ "system": "http://terminology.hl7.org/CodeSystem/v3-Confidentiality",
+ "code": "U",
+ "display": "unrestricted"
+ }
+ ]
+ },
+ "name": [
+ {
+ "id": "123",
+ "use": "usual",
+ "period": {
+ "start": "2020-01-01",
+ "end": "2025-12-31"
+ },
+ "given": ["Jane"],
+ "family": "Smith",
+ "prefix": ["Mrs"],
+ "suffix": ["MBE"]
+ },
+ {
+ "id": "1234",
+ "use": "other",
+ "period": {
+ "start": "2020-01-01",
+ "end": "2025-12-31"
+ },
+ "given": ["Jim"],
+ "family": "Stevens",
+ "prefix": ["Mr"],
+ "suffix": ["MBE"]
+ }
+ ],
+ "gender": "female",
+ "birthDate": "2010-10-22",
+ "multipleBirthInteger": 1,
+ "deceasedDateTime": "2010-10-22T00:00:00+00:00",
+ "generalPractitioner": [
+ {
+ "id": "254406A3",
+ "type": "Organization",
+ "identifier": {
+ "system": "https://fhir.nhs.uk/Id/ods-organization-code",
+ "value": "M85143",
+ "period": {
+ "start": "2020-01-01",
+ "end": "2025-12-31"
+ }
+ }
+ }
+ ],
+ "managingOrganization": {
+ "type": "Organization",
+ "identifier": {
+ "system": "https://fhir.nhs.uk/Id/ods-organization-code",
+ "value": "M85143",
+ "period": {
+ "start": "2020-01-01",
+ "end": "2025-12-31"
+ }
+ }
+ },
+ "extension": [
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NominatedPharmacy",
+ "valueReference": {
+ "identifier": {
+ "system": "https://fhir.nhs.uk/Id/ods-organization-code",
+ "value": "M85143"
+ }
+ }
+ },
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-PreferredDispenserOrganization",
+ "valueReference": {
+ "identifier": {
+ "system": "https://fhir.nhs.uk/Id/ods-organization-code",
+ "value": "M85143"
+ }
+ }
+ },
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-MedicalApplianceSupplier",
+ "valueReference": {
+ "identifier": {
+ "system": "https://fhir.nhs.uk/Id/ods-organization-code",
+ "value": "M85143"
+ }
+ }
+ },
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-DeathNotificationStatus",
+ "extension": [
+ {
+ "url": "deathNotificationStatus",
+ "valueCodeableConcept": {
+ "coding": [
+ {
+ "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-DeathNotificationStatus",
+ "version": "1.0.0",
+ "code": "2",
+ "display": "Formal - death notice received from Registrar of Deaths"
+ }
+ ]
+ }
+ },
+ {
+ "url": "systemEffectiveDate",
+ "valueDateTime": "2010-10-22T00:00:00+00:00"
+ }
+ ]
+ },
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-NHSCommunication",
+ "extension": [
+ {
+ "url": "language",
+ "valueCodeableConcept": {
+ "coding": [
+ {
+ "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage",
+ "version": "1.0.0",
+ "code": "fr",
+ "display": "French"
+ }
+ ]
+ }
+ },
+ {
+ "url": "interpreterRequired",
+ "valueBoolean": true
+ }
+ ]
+ },
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-ContactPreference",
+ "extension": [
+ {
+ "url": "PreferredWrittenCommunicationFormat",
+ "valueCodeableConcept": {
+ "coding": [
+ {
+ "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredWrittenCommunicationFormat",
+ "code": "12",
+ "display": "Braille"
+ }
+ ]
+ }
+ },
+ {
+ "url": "PreferredContactMethod",
+ "valueCodeableConcept": {
+ "coding": [
+ {
+ "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-PreferredContactMethod",
+ "code": "1",
+ "display": "Letter"
+ }
+ ]
+ }
+ },
+ {
+ "url": "PreferredContactTimes",
+ "valueString": "Not after 7pm"
+ }
+ ]
+ },
+ {
+ "url": "http://hl7.org/fhir/StructureDefinition/patient-birthPlace",
+ "valueAddress": {
+ "city": "Manchester",
+ "district": "Greater Manchester",
+ "country": "GBR"
+ }
+ },
+ {
+ "url": "https://fhir.nhs.uk/StructureDefinition/Extension-PDS-RemovalFromRegistration",
+ "extension": [
+ {
+ "url": "removalFromRegistrationCode",
+ "valueCodeableConcept": {
+ "coding": [
+ {
+ "system": "https://fhir.nhs.uk/CodeSystem/PDS-RemovalReasonExitCode",
+ "code": "SCT",
+ "display": "Transferred to Scotland"
+ }
+ ]
+ }
+ },
+ {
+ "url": "effectiveTime",
+ "valuePeriod": {
+ "start": "2020-01-01T00:00:00+00:00",
+ "end": "2025-12-31T00:00:00+00:00"
+ }
+ }
+ ]
+ }
+ ],
+ "telecom": [
+ {
+ "id": "789",
+ "period": {
+ "start": "2020-01-01",
+ "end": "2025-12-31"
+ },
+ "system": "phone",
+ "value": "01632960587",
+ "use": "home"
+ },
+ {
+ "id": "790",
+ "period": {
+ "start": "2019-01-01",
+ "end": "2022-12-31"
+ },
+ "system": "email",
+ "value": "jane.smith@example.com",
+ "use": "home"
+ },
+ {
+ "id": "OC789",
+ "period": {
+ "start": "2020-01-01",
+ "end": "2025-12-31"
+ },
+ "system": "other",
+ "value": "01632960587",
+ "use": "home",
+ "extension": [
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-OtherContactSystem",
+ "valueCoding": {
+ "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-OtherContactSystem",
+ "code": "textphone",
+ "display": "Minicom (Textphone)"
+ }
+ }
+ ]
+ }
+ ],
+ "contact": [
+ {
+ "id": "C123",
+ "period": {
+ "start": "2020-01-01",
+ "end": "2025-12-31"
+ },
+ "relationship": [
+ {
+ "coding": [
+ {
+ "system": "http://terminology.hl7.org/CodeSystem/v2-0131",
+ "code": "C",
+ "display": "Emergency Contact"
+ }
+ ]
+ }
+ ],
+ "telecom": [
+ {
+ "system": "phone",
+ "value": "01632960587"
+ }
+ ]
+ }
+ ],
+ "address": [
+ {
+ "id": "456",
+ "period": {
+ "start": "2020-01-01",
+ "end": "2025-12-31"
+ },
+ "use": "home",
+ "line": [
+ "1 Trevelyan Square",
+ "Boar Lane",
+ "City Centre",
+ "Leeds",
+ "West Yorkshire"
+ ],
+ "postalCode": "LS1 6AE",
+ "extension": [
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey",
+ "extension": [
+ {
+ "url": "type",
+ "valueCoding": {
+ "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType",
+ "code": "PAF"
+ }
+ },
+ {
+ "url": "value",
+ "valueString": "12345678"
+ }
+ ]
+ },
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey",
+ "extension": [
+ {
+ "url": "type",
+ "valueCoding": {
+ "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType",
+ "code": "UPRN"
+ }
+ },
+ {
+ "url": "value",
+ "valueString": "123456789012"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "T456",
+ "period": {
+ "start": "2020-01-01",
+ "end": "2025-12-31"
+ },
+ "use": "temp",
+ "text": "Student Accommodation",
+ "line": [
+ "1 Trevelyan Square",
+ "Boar Lane",
+ "City Centre",
+ "Leeds",
+ "West Yorkshire"
+ ],
+ "postalCode": "LS1 6AE",
+ "extension": [
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey",
+ "extension": [
+ {
+ "url": "type",
+ "valueCoding": {
+ "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType",
+ "code": "PAF"
+ }
+ },
+ {
+ "url": "value",
+ "valueString": "12345678"
+ }
+ ]
+ },
+ {
+ "url": "https://fhir.hl7.org.uk/StructureDefinition/Extension-UKCore-AddressKey",
+ "extension": [
+ {
+ "url": "type",
+ "valueCoding": {
+ "system": "https://fhir.hl7.org.uk/CodeSystem/UKCore-AddressKeyType",
+ "code": "UPRN"
+ }
+ },
+ {
+ "url": "value",
+ "valueString": "123456789012"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/lambdas/services/mock_pds_service.py b/lambdas/services/mock_pds_service.py
index 6cce0e751..202664add 100644
--- a/lambdas/services/mock_pds_service.py
+++ b/lambdas/services/mock_pds_service.py
@@ -27,6 +27,8 @@ def pds_request(self, nhs_number: str, *args, **kwargs) -> Response:
mock_pds_results.append(json.load(f))
with open("services/mock_data/pds_patient_9000000003_H85686_gp.json") as f:
mock_pds_results.append(json.load(f))
+ with open("services/mock_data/pds_patient_9000000004_M85143_gp.json") as f:
+ mock_pds_results.append(json.load(f))
with open("services/mock_data/pds_patient_9000000025_restricted.json") as f:
mock_pds_results.append(json.load(f))
From 7925e54dddd88567d6dbc44999db24b5358c8f0d Mon Sep 17 00:00:00 2001
From: Rio Knightley
Date: Wed, 14 Feb 2024 16:06:41 +0000
Subject: [PATCH 06/15] Add stage complete to upload
---
.../lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx b/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
index 4da1b61ea..e6f3c1cfc 100644
--- a/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
+++ b/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
@@ -2,7 +2,6 @@ import React, { Dispatch, SetStateAction, useRef } from 'react';
import BackButton from '../../../components/generic/backButton/BackButton';
import { formatNhsNumber } from '../../../helpers/utils/formatNhsNumber';
import { getFormattedDate } from '../../../helpers/utils/formatDate';
-import { buildPatientDetails } from '../../../helpers/test/testBuilders';
import { Input, Button, Fieldset, InsetText, Table } from 'nhsuk-react-components';
import { ReactComponent as FileSVG } from '../../../styles/file-input.svg';
import {
@@ -18,6 +17,7 @@ import uploadDocument from '../../../helpers/requests/uploadDocument';
import useBaseAPIUrl from '../../../helpers/hooks/useBaseAPIUrl';
import useBaseAPIHeaders from '../../../helpers/hooks/useBaseAPIHeaders';
import { LG_UPLOAD_STAGE } from '../../../pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage';
+import usePatient from '../../../helpers/hooks/usePatient';
type Props = {
documents: Array;
@@ -26,7 +26,7 @@ type Props = {
};
function LloydGeorgeFileInputStage({ documents, setDocuments, setStage }: Props) {
- const patientDetails = buildPatientDetails();
+ const patientDetails = usePatient();
const nhsNumber: string = patientDetails?.nhsNumber || '';
const formattedNhsNumber = formatNhsNumber(nhsNumber);
const dob: String = patientDetails?.birthDate
@@ -52,6 +52,7 @@ function LloydGeorgeFileInputStage({ documents, setDocuments, setStage }: Props)
baseUrl,
baseHeaders,
});
+ setStage(LG_UPLOAD_STAGE.COMPLETE);
}
} catch (e) {}
};
From 81b3fc181a8eeb5ce1fd1f0f3288ebc54d3f3e77 Mon Sep 17 00:00:00 2001
From: Rio Knightley
Date: Wed, 14 Feb 2024 16:08:59 +0000
Subject: [PATCH 07/15] Add lloyd george complete view
---
.../LloydGeorgeUploadPage.tsx | 26 +++----------------
1 file changed, 3 insertions(+), 23 deletions(-)
diff --git a/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx b/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
index 0ba88dacb..fe3c7056e 100644
--- a/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
+++ b/app/src/pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage.tsx
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
import LloydGeorgeUploadingStage from '../../components/blocks/lloydGeorgeUploadingStage/LloydGeorgeUploadingStage';
import { UploadDocument } from '../../types/pages/UploadDocumentsPage/types';
import LloydGeorgeFileInputStage from '../../components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage';
+import LloydGeorgeUploadComplete from '../../components/blocks/lloydGeorgeUploadComplete/LloydGeorgeUploadComplete';
type Props = {};
@@ -14,16 +15,7 @@ export enum LG_UPLOAD_STAGE {
function LloydGeorgeUploadPage({}: Props) {
const [stage, setStage] = useState(LG_UPLOAD_STAGE.SELECT);
const [documents, setDocuments] = useState>([]);
- // const files = [
- // buildTextFile('1of3_Lloyd_George_Record_[Barry ONEIL]_[9730182000]_[23-10-2018]', 100),
- // buildTextFile('2of3_Lloyd_George_Record_[Barry ONEIL]_[9730182000]_[23-10-2018]', 101),
- // ];
- // const documents = files.map((file) => {
- // return {
- // ...buildDocument(file, DOCUMENT_UPLOAD_STATE.SUCCEEDED),
- // progress: 100,
- // };
- // });
+
switch (stage) {
case LG_UPLOAD_STAGE.SELECT:
return (
@@ -36,19 +28,7 @@ function LloydGeorgeUploadPage({}: Props) {
case LG_UPLOAD_STAGE.UPLOAD:
return ;
case LG_UPLOAD_STAGE.COMPLETE:
- return (
- // TODO, ADD UPLOAD COMPLETE STAGE
-
-
-
upload complete
-
- );
+ return ;
default:
return null;
}
From 6d54a3323877ac9e7614683bdc9645042a0c6a8a Mon Sep 17 00:00:00 2001
From: Rio Knightley
Date: Wed, 14 Feb 2024 16:57:58 +0000
Subject: [PATCH 08/15] Add lloyd george upload stages
---
.../LloydGeorgeFileInputStage.test.tsx} | 107 ++++----
.../LloydGeorgeFileInputStage.tsx | 2 +-
.../UploadLloydGeorgeRecordPage.tsx | 235 ------------------
3 files changed, 65 insertions(+), 279 deletions(-)
rename app/src/{pages/uploadLloydGeorgeRecordPage/UploadLloydGeorgeRecordPage.test.tsx => components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.test.tsx} (87%)
delete mode 100644 app/src/pages/uploadLloydGeorgeRecordPage/UploadLloydGeorgeRecordPage.tsx
diff --git a/app/src/pages/uploadLloydGeorgeRecordPage/UploadLloydGeorgeRecordPage.test.tsx b/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.test.tsx
similarity index 87%
rename from app/src/pages/uploadLloydGeorgeRecordPage/UploadLloydGeorgeRecordPage.test.tsx
rename to app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.test.tsx
index e1a65339e..c7dd7526b 100644
--- a/app/src/pages/uploadLloydGeorgeRecordPage/UploadLloydGeorgeRecordPage.test.tsx
+++ b/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.test.tsx
@@ -1,25 +1,38 @@
import { fireEvent, render, screen } from '@testing-library/react';
-import { buildPatientDetails, buildLgFile } from '../../helpers/test/testBuilders';
-import { DOCUMENT_UPLOAD_STATE as documentUploadStates } from '../../types/pages/UploadDocumentsPage/types';
-import { PatientDetails } from '../../types/generic/patientDetails';
-import usePatient from '../../helpers/hooks/usePatient';
-import UploadLloydGeorgeRecordPage from './UploadLloydGeorgeRecordPage';
-import { formatNhsNumber } from '../../helpers/utils/formatNhsNumber';
+import {
+ buildPatientDetails,
+ buildLgFile,
+ buildDocument,
+} from '../../../helpers/test/testBuilders';
+import usePatient from '../../../helpers/hooks/usePatient';
+import { formatNhsNumber } from '../../../helpers/utils/formatNhsNumber';
import { act } from 'react-dom/test-utils';
import userEvent from '@testing-library/user-event';
-
-jest.mock('../../helpers/utils/toFileList', () => ({
+import LloydGeorgeFileInputStage, { Props } from './LloydGeorgeFileInputStage';
+import {
+ DOCUMENT_UPLOAD_STATE,
+ UploadDocument,
+} from '../../../types/pages/UploadDocumentsPage/types';
+import { useState } from 'react';
+
+jest.mock('../../../helpers/utils/toFileList', () => ({
__esModule: true,
default: () => [],
}));
-jest.mock('../../helpers/hooks/usePatient');
+jest.mock('../../../helpers/hooks/usePatient');
jest.mock('react-router');
-jest.mock('../../helpers/hooks/useBaseAPIHeaders');
-
+jest.mock('../../../helpers/hooks/useBaseAPIHeaders');
+const setStageMock = jest.fn();
const mockedUsePatient = usePatient as jest.Mock;
const mockPatient = buildPatientDetails();
-
-describe('', () => {
+const lgDocumentOne = buildLgFile(1, 2);
+const lgDocumentTwo = buildLgFile(2, 2);
+const lgFiles = [lgDocumentOne, lgDocumentTwo];
+const uploadFiles = [
+ buildDocument(lgDocumentOne, DOCUMENT_UPLOAD_STATE.UPLOADING),
+ buildDocument(lgDocumentTwo, DOCUMENT_UPLOAD_STATE.UPLOADING),
+];
+describe('', () => {
beforeEach(() => {
process.env.REACT_APP_ENVIRONMENT = 'jest';
mockedUsePatient.mockReturnValue(mockPatient);
@@ -29,25 +42,14 @@ describe('', () => {
});
describe('upload documents with an NHS number', () => {
- const lgDocumentOne = buildLgFile(1, 2);
- const lgDocumentTwo = buildLgFile(2, 2);
- const lgFiles = [lgDocumentOne, lgDocumentTwo];
- const setDocumentMock = jest.fn();
- setDocumentMock.mockImplementation((document) => {
- document.state = documentUploadStates.SELECTED;
- document.id = '1';
- });
-
- const mockPatientDetails: PatientDetails = buildPatientDetails();
-
it('renders the page', async () => {
- render();
+ renderApp();
expect(
screen.getByRole('heading', { name: 'Upload a Lloyd George record' }),
).toBeInTheDocument();
expect(
- screen.getByText('NHS number: ' + formatNhsNumber(mockPatientDetails.nhsNumber)),
+ screen.getByText('NHS number: ' + formatNhsNumber(mockPatient.nhsNumber)),
).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Select files' })).toBeInTheDocument();
@@ -57,13 +59,13 @@ describe('', () => {
});
it('can upload documents to LG forms using button', async () => {
- render();
+ renderApp();
expect(
screen.getByRole('heading', { name: 'Upload a Lloyd George record' }),
).toBeInTheDocument();
expect(
- screen.getByText('NHS number: ' + formatNhsNumber(mockPatientDetails.nhsNumber)),
+ screen.getByText('NHS number: ' + formatNhsNumber(mockPatient.nhsNumber)),
).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Upload' })).toBeInTheDocument();
@@ -78,15 +80,17 @@ describe('', () => {
expect(screen.getByRole('button', { name: 'Upload' })).toBeEnabled();
});
+
it('can upload documents to LG forms using drag and drop when dataTransfer type is files', async () => {
- render();
+ renderApp();
+
const dropzone = screen.getByTestId('dropzone');
expect(
screen.getByRole('heading', { name: 'Upload a Lloyd George record' }),
).toBeInTheDocument();
expect(
- screen.getByText('NHS number: ' + formatNhsNumber(mockPatientDetails.nhsNumber)),
+ screen.getByText('NHS number: ' + formatNhsNumber(mockPatient.nhsNumber)),
).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Upload' })).toBeInTheDocument();
@@ -103,14 +107,14 @@ describe('', () => {
expect(screen.getByRole('button', { name: 'Upload' })).toBeEnabled();
});
it('can upload documents to LG forms using drag and drop when dataTransfer type is items', async () => {
- render();
+ renderApp();
const dropzone = screen.getByTestId('dropzone');
expect(
screen.getByRole('heading', { name: 'Upload a Lloyd George record' }),
).toBeInTheDocument();
expect(
- screen.getByText('NHS number: ' + formatNhsNumber(mockPatientDetails.nhsNumber)),
+ screen.getByText('NHS number: ' + formatNhsNumber(mockPatient.nhsNumber)),
).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Upload' })).toBeInTheDocument();
@@ -134,7 +138,7 @@ describe('', () => {
expect(screen.getByRole('button', { name: 'Upload' })).toBeEnabled();
});
it('can upload documents to LG forms using drag and drop and button', async () => {
- render();
+ renderApp();
const dropzone = screen.getByTestId('dropzone');
expect(
@@ -157,7 +161,7 @@ describe('', () => {
expect(screen.getByRole('button', { name: 'Upload' })).toBeEnabled();
});
it('does upload and then remove a file', async () => {
- render();
+ renderApp();
act(() => {
userEvent.upload(screen.getByTestId('button-input'), lgFiles);
@@ -177,7 +181,7 @@ describe('', () => {
expect(screen.getByText(lgDocumentTwo.name)).toBeInTheDocument();
});
it('does upload and then remove all a files', async () => {
- render();
+ renderApp();
act(() => {
userEvent.upload(screen.getByTestId('button-input'), lgFiles);
@@ -198,7 +202,7 @@ describe('', () => {
expect(screen.queryByText(lgDocumentTwo.name)).not.toBeInTheDocument();
});
it('does not upload either forms if selected file is more than 5GB', async () => {
- render();
+ renderApp();
const documentBig = buildLgFile(3, 2, 6 * Math.pow(1024, 3));
@@ -218,7 +222,7 @@ describe('', () => {
});
it('does not upload LG form if selected file is not PDF', async () => {
- render();
+ renderApp();
const lgFileWithBadType = new File(
['test'],
@@ -246,7 +250,7 @@ describe('', () => {
});
it('does not upload LG form if total number of file does not match file name', async () => {
- render();
+ renderApp();
const lgExtraFile = buildLgFile(3, 3);
@@ -268,7 +272,7 @@ describe('', () => {
});
it('does not upload LG form if selected file does not match naming conventions', async () => {
- render();
+ renderApp();
const pdfFileWithBadName = new File(['test'], `test_not_up_to_naming_conventions.pdf`, {
type: 'application/pdf',
@@ -291,7 +295,7 @@ describe('', () => {
});
it('does not upload LG form if selected file number is bigger than number of total files', async () => {
- render();
+ renderApp();
const pdfFileWithBadNumber = buildLgFile(2, 1);
act(() => {
@@ -312,7 +316,7 @@ describe('', () => {
});
it('does not upload LG form if files do not match each other', async () => {
- render();
+ renderApp();
const joeBloggsFile = new File(
['test'],
@@ -351,7 +355,7 @@ describe('', () => {
it('does not upload LG form if two or more files match name/size', async () => {
const duplicateFileWarning = 'There are two or more documents with the same name.';
- render();
+ renderApp();
act(() => {
userEvent.upload(screen.getByTestId(`button-input`), [
@@ -375,7 +379,7 @@ describe('', () => {
});
it("does allow the user to add the same file again if they remove for '%s' input", async () => {
- render();
+ renderApp();
act(() => {
userEvent.upload(screen.getByTestId(`button-input`), [
@@ -398,4 +402,21 @@ describe('', () => {
expect(await screen.findByText(lgDocumentOne.name)).toBeInTheDocument();
});
});
+
+ const TestApp = (props: Partial) => {
+ const [documents, setDocuments] = useState>([]);
+
+ return (
+
+ );
+ };
+
+ const renderApp = (props?: Partial) => {
+ render();
+ };
});
diff --git a/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx b/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
index e6f3c1cfc..c081fa6a9 100644
--- a/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
+++ b/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
@@ -19,7 +19,7 @@ import useBaseAPIHeaders from '../../../helpers/hooks/useBaseAPIHeaders';
import { LG_UPLOAD_STAGE } from '../../../pages/lloydGeorgeUploadPage/LloydGeorgeUploadPage';
import usePatient from '../../../helpers/hooks/usePatient';
-type Props = {
+export type Props = {
documents: Array;
setDocuments: Dispatch>>;
setStage: Dispatch>;
diff --git a/app/src/pages/uploadLloydGeorgeRecordPage/UploadLloydGeorgeRecordPage.tsx b/app/src/pages/uploadLloydGeorgeRecordPage/UploadLloydGeorgeRecordPage.tsx
deleted file mode 100644
index 8d7392a69..000000000
--- a/app/src/pages/uploadLloydGeorgeRecordPage/UploadLloydGeorgeRecordPage.tsx
+++ /dev/null
@@ -1,235 +0,0 @@
-import React, { useRef, useState } from 'react';
-import BackButton from '../../components/generic/backButton/BackButton';
-import { formatNhsNumber } from '../../helpers/utils/formatNhsNumber';
-import { getFormattedDate } from '../../helpers/utils/formatDate';
-import { buildPatientDetails } from '../../helpers/test/testBuilders';
-import { Input, Button, Fieldset, InsetText, Table } from 'nhsuk-react-components';
-import { ReactComponent as FileSVG } from '../../styles/file-input.svg';
-import {
- DOCUMENT_TYPE,
- DOCUMENT_UPLOAD_STATE,
- FileInputEvent,
- UploadDocument,
-} from '../../types/pages/UploadDocumentsPage/types';
-import { useController, useForm } from 'react-hook-form';
-import formatFileSize from '../../helpers/utils/formatFileSize';
-import { lloydGeorgeFormConfig } from '../../helpers/utils/formConfig';
-import uploadDocument from '../../helpers/requests/uploadDocument';
-import useBaseAPIUrl from '../../helpers/hooks/useBaseAPIUrl';
-import useBaseAPIHeaders from '../../helpers/hooks/useBaseAPIHeaders';
-
-function UploadLloydGeorgeRecordPage() {
- const patientDetails = buildPatientDetails();
- const nhsNumber: string = patientDetails?.nhsNumber || '';
- const formattedNhsNumber = formatNhsNumber(nhsNumber);
- const dob: String = patientDetails?.birthDate
- ? getFormattedDate(new Date(patientDetails.birthDate))
- : '';
- let fileInputRef = useRef(null);
- const [lgDocuments, setLgDocuments] = useState>([]);
-
- const { handleSubmit, control, formState } = useForm();
- const lgController = useController(lloydGeorgeFormConfig(control));
-
- const hasFileInput = lgDocuments.length;
- const baseUrl = useBaseAPIUrl();
- const baseHeaders = useBaseAPIHeaders();
-
- const uploadDocuments = async () => {
- if (patientDetails) {
- await uploadDocument({
- nhsNumber: patientDetails.nhsNumber,
- setDocuments: setLgDocuments,
- documents: lgDocuments,
- baseUrl,
- baseHeaders,
- });
- }
- };
- const updateFileList = (fileArray: File[]) => {
- const documentMap: Array = fileArray.map((file) => ({
- id: Math.floor(Math.random() * 1000000).toString(),
- file,
- state: DOCUMENT_UPLOAD_STATE.SELECTED,
- progress: 0,
- docType: DOCUMENT_TYPE.LLOYD_GEORGE,
- }));
- const updatedDocList = [...documentMap, ...lgDocuments];
- setLgDocuments(updatedDocList);
- lgController.field.onChange(updatedDocList);
- };
- const onFileDrop = (e: React.DragEvent) => {
- e.preventDefault();
- e.stopPropagation();
- let fileArray: File[] = [];
- if (e.dataTransfer.items) {
- [...e.dataTransfer.items].forEach((item) => {
- const file = item.getAsFile();
-
- if (item.kind === 'file' && file) {
- fileArray.push(file);
- }
- });
- } else if (e.dataTransfer.files) {
- fileArray = [...e.dataTransfer.files];
- }
- if (fileArray) {
- updateFileList(fileArray);
- }
- };
- const onInput = (e: FileInputEvent) => {
- const fileArray = Array.from(e.target.files ?? new FileList());
- updateFileList(fileArray);
- };
- const onRemove = (index: number) => {
- let updatedDocList: UploadDocument[] = [];
- if (index >= 0) {
- updatedDocList = [...lgDocuments.slice(0, index), ...lgDocuments.slice(index + 1)];
- }
- setLgDocuments(updatedDocList);
- lgController.field.onChange(updatedDocList);
- };
-
- return (
-
- );
-}
-
-export default UploadLloydGeorgeRecordPage;
From 8c91a5e3bfdf97e81636ac6ae9cad4c509a04fb4 Mon Sep 17 00:00:00 2001
From: Rio Knightley
Date: Thu, 15 Feb 2024 12:19:06 +0000
Subject: [PATCH 09/15] Fix sonarcloud issue
---
.../DocumentSearchResultsOptions.tsx | 8 +-
.../blocks/_arf/selectStage/SelectStage.tsx | 82 +++++++++----------
.../_arf/uploadSummary/UploadSummary.tsx | 74 ++++++++---------
.../_arf/uploadingStage/UploadingStage.tsx | 6 +-
.../DeleteDocumentsStage.tsx | 4 +-
.../LloydGeorgeFileInputStage.tsx | 3 +-
.../LloydGeorgeRecordStage.tsx | 2 +-
.../LloydGeorgeUploadingStage.tsx | 6 +-
.../LloydGeorgeUploadPage.tsx | 2 +-
.../PatientResultPage.test.tsx | 2 +-
.../patientResultPage/PatientResultPage.tsx | 3 +-
11 files changed, 93 insertions(+), 99 deletions(-)
diff --git a/app/src/components/blocks/_arf/documentSearchResultsOptions/DocumentSearchResultsOptions.tsx b/app/src/components/blocks/_arf/documentSearchResultsOptions/DocumentSearchResultsOptions.tsx
index 4f60e49ae..ceb278d2d 100644
--- a/app/src/components/blocks/_arf/documentSearchResultsOptions/DocumentSearchResultsOptions.tsx
+++ b/app/src/components/blocks/_arf/documentSearchResultsOptions/DocumentSearchResultsOptions.tsx
@@ -1,4 +1,4 @@
-import { Button, ButtonLink } from 'nhsuk-react-components';
+import { Button } from 'nhsuk-react-components';
import SpinnerButton from '../../../generic/spinnerButton/SpinnerButton';
import { routes } from '../../../../types/generic/routes';
import { SUBMISSION_STATE } from '../../../../types/pages/documentSearchResultsPage/types';
@@ -15,7 +15,6 @@ type Props = {
nhsNumber: string;
downloadState: string;
updateDownloadState: (newState: SUBMISSION_STATE) => void;
- numberOfFiles: number;
setIsDeletingDocuments: Dispatch>;
};
@@ -97,15 +96,14 @@ const DocumentSearchResultsOptions = (props: Props) => {
>
Download Manifest URL
-
Delete All Documents
-
+
{props.downloadState === SUBMISSION_STATE.SUCCEEDED && (
diff --git a/app/src/components/blocks/_arf/selectStage/SelectStage.tsx b/app/src/components/blocks/_arf/selectStage/SelectStage.tsx
index 2e1618f61..f2ccff971 100644
--- a/app/src/components/blocks/_arf/selectStage/SelectStage.tsx
+++ b/app/src/components/blocks/_arf/selectStage/SelectStage.tsx
@@ -81,49 +81,47 @@ function SelectStage({ uploadDocuments, setDocuments }: Props) {
};
return (
- <>
-
- >
+
+
+
+
);
}
diff --git a/app/src/components/blocks/_arf/uploadSummary/UploadSummary.tsx b/app/src/components/blocks/_arf/uploadSummary/UploadSummary.tsx
index 71de2a4fc..092aeeefa 100644
--- a/app/src/components/blocks/_arf/uploadSummary/UploadSummary.tsx
+++ b/app/src/components/blocks/_arf/uploadSummary/UploadSummary.tsx
@@ -75,45 +75,43 @@ const UploadSummary = ({ documents }: Props) => {
)}
{successfulUploads.length > 0 && (
- <>
-
-
+
+ View successfully uploaded documents
+
+
+
- View successfully uploaded documents
-
-
-
-
-
- File Name
- File Size
-
-
-
- {successfulUploads.map((document) => {
- return (
-
- {document.file.name}
-
- {formatFileSize(document.file.size)}
-
-
- );
- })}
-
-
-
-
- >
+
+
+ File Name
+ File Size
+
+
+
+ {successfulUploads.map((document) => {
+ return (
+
+ {document.file.name}
+
+ {formatFileSize(document.file.size)}
+
+
+ );
+ })}
+
+
+
+
)}
diff --git a/app/src/components/blocks/_arf/uploadingStage/UploadingStage.tsx b/app/src/components/blocks/_arf/uploadingStage/UploadingStage.tsx
index a9d37ba9c..3c158946d 100644
--- a/app/src/components/blocks/_arf/uploadingStage/UploadingStage.tsx
+++ b/app/src/components/blocks/_arf/uploadingStage/UploadingStage.tsx
@@ -32,7 +32,7 @@ function UploadingStage({ documents }: Props) {
className: 'nhsuk-u-visually-hidden',
}}
>
-
+
File Name
File Size
@@ -50,13 +50,13 @@ function UploadingStage({ documents }: Props) {
max="100"
value={document.progress}
>
-
+
+
))}
diff --git a/app/src/components/blocks/deleteDocumentsStage/DeleteDocumentsStage.tsx b/app/src/components/blocks/deleteDocumentsStage/DeleteDocumentsStage.tsx
index f3a1da7b8..3726968e0 100644
--- a/app/src/components/blocks/deleteDocumentsStage/DeleteDocumentsStage.tsx
+++ b/app/src/components/blocks/deleteDocumentsStage/DeleteDocumentsStage.tsx
@@ -52,10 +52,10 @@ function DeleteDocumentsStage({
const baseHeaders = useBaseAPIHeaders();
const navigate = useNavigate();
const featureFlags = useFeatureFlags();
- const nhsNumber: string = patientDetails?.nhsNumber || '';
+ const nhsNumber: string = patientDetails?.nhsNumber ?? '';
const formattedNhsNumber = formatNhsNumber(nhsNumber);
- const dob: String = patientDetails?.birthDate
+ const dob: string = patientDetails?.birthDate
? getFormattedDate(new Date(patientDetails.birthDate))
: '';
diff --git a/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx b/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
index c081fa6a9..35475616b 100644
--- a/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
+++ b/app/src/components/blocks/lloydGeorgeFileInputStage/LloydGeorgeFileInputStage.tsx
@@ -29,7 +29,7 @@ function LloydGeorgeFileInputStage({ documents, setDocuments, setStage }: Props)
const patientDetails = usePatient();
const nhsNumber: string = patientDetails?.nhsNumber || '';
const formattedNhsNumber = formatNhsNumber(nhsNumber);
- const dob: String = patientDetails?.birthDate
+ const dob: string = patientDetails?.birthDate
? getFormattedDate(new Date(patientDetails.birthDate))
: '';
let fileInputRef = useRef(null);
@@ -141,6 +141,7 @@ function LloydGeorgeFileInputStage({ documents, setDocuments, setStage }: Props)
Select the files you wish to upload