Skip to content

Commit 9f4bb6e

Browse files
[PRMP-861] Upload documents for review
1 parent 7e8bc5e commit 9f4bb6e

File tree

8 files changed

+147
-27
lines changed

8 files changed

+147
-27
lines changed

app/src/components/blocks/_documentUpload/documentUploadCompleteStage/DocumentUploadCompleteStage.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ const DocumentUploadCompleteStage = ({ documents, documentConfig }: Props): Reac
4242
]);
4343

4444
useEffect(() => {
45-
if (!docsAreInFinishedState()) {
45+
if (!docsAreInFinishedState() || patientDetails === null) {
4646
navigate(routes.HOME);
4747
}
48-
}, [navigate, documents]);
48+
}, [navigate, documents, patientDetails]);
4949

50-
if (!docsAreInFinishedState()) {
50+
if (!docsAreInFinishedState() || patientDetails === null) {
5151
return <></>;
5252
}
5353

@@ -108,7 +108,7 @@ const DocumentUploadCompleteStage = ({ documents, documentConfig }: Props): Reac
108108

109109
<h3>What happens next</h3>
110110

111-
{journey === 'update' && (
111+
{journey === 'update' && patientDetails.canManageRecord && (
112112
<p>
113113
You can now view the updated {documentConfig.displayName} for this patient in
114114
this service by{' '}

app/src/helpers/requests/uploadDocuments.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const uploadDocumentToS3 = async ({
3636
}: UploadDocumentsToS3Args): Promise<void> => {
3737
const documentMetadata: S3Upload = uploadSession[document.id];
3838
const formData = new FormData();
39-
const docFields: S3UploadFields = documentMetadata.fields ?? [];
39+
const docFields: S3UploadFields = documentMetadata.fields ?? {} as S3UploadFields;
4040
Object.entries(docFields).forEach(([key, value]) => {
4141
formData.append(key, value);
4242
});

app/src/helpers/test/testBuilders.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const buildPatientDetails = (patientDetailsOverride?: Partial<PatientDetails>):
4040
restricted: false,
4141
active: true,
4242
deceased: false,
43+
canManageRecord: true,
4344
...patientDetailsOverride,
4445
};
4546

app/src/pages/documentUploadPage/DocumentUploadPage.tsx

Lines changed: 105 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ import { DOCUMENT_TYPE, getConfigForDocType } from '../../helpers/utils/document
4343
import { buildMockUploadSession } from '../../helpers/test/testBuilders';
4444
import { reduceDocumentsForUpload } from '../../helpers/utils/documentUpload';
4545
import DocumentUploadIndex from '../../components/blocks/_documentUpload/documentUploadIndex/DocumentUploadIndex';
46+
import { getDocumentReviewStatus, uploadDocumentForReview } from '../../helpers/requests/documentReview';
47+
import { DocumentReviewDto, DocumentReviewStatus, DocumentReviewStatusDto } from '../../types/blocks/documentReview';
4648

4749
const DocumentUploadPage = (): React.JSX.Element => {
4850
const patientDetails = usePatient();
@@ -158,7 +160,7 @@ const DocumentUploadPage = (): React.JSX.Element => {
158160
setExistingDocuments(newDocuments);
159161
};
160162

161-
const uploadSingleLloydGeorgeDocument = async (
163+
const uploadSingleDocument = async (
162164
document: UploadDocument,
163165
uploadSession: UploadSession,
164166
): Promise<void> => {
@@ -190,7 +192,7 @@ const DocumentUploadPage = (): React.JSX.Element => {
190192
uploadSession: UploadSession,
191193
): void => {
192194
uploadDocuments.forEach((document) => {
193-
void uploadSingleLloydGeorgeDocument(document, uploadSession);
195+
void uploadSingleDocument(document, uploadSession);
194196
});
195197
};
196198

@@ -211,17 +213,51 @@ const DocumentUploadPage = (): React.JSX.Element => {
211213
navigate.withParams(routeChildren.DOCUMENT_UPLOAD_UPLOADING);
212214
};
213215

216+
const getUploadSession = async (): Promise<UploadSession> => {
217+
if (isLocal) {
218+
return buildMockUploadSession(documents);
219+
} else if (patientDetails?.canManageRecord) {
220+
return await uploadDocuments({
221+
nhsNumber,
222+
documents: documents,
223+
baseUrl,
224+
baseHeaders,
225+
documentReferenceId: existingDocuments[0]?.id,
226+
});
227+
} else {
228+
const uploadSession: UploadSession = {};
229+
const requests: Promise<DocumentReviewDto>[] = [];
230+
231+
documents.forEach(document => {
232+
const documentReview = uploadDocumentForReview({
233+
nhsNumber,
234+
document,
235+
baseUrl,
236+
baseHeaders,
237+
});
238+
239+
documentReview.then((review: DocumentReviewDto) => {
240+
document.id = review.id;
241+
document.versionId = review.version;
242+
uploadSession[review.id] = {
243+
url: review.files[0].presignedUrl,
244+
};
245+
});
246+
247+
requests.push(documentReview);
248+
});
249+
250+
const sessions = await Promise.all(requests);
251+
252+
setDocuments(documents);
253+
254+
return Object.assign({}, ...sessions);
255+
}
256+
};
257+
214258
const startUpload = async (): Promise<void> => {
215259
try {
216-
const uploadSession: UploadSession = isLocal
217-
? buildMockUploadSession(documents)
218-
: await uploadDocuments({
219-
nhsNumber,
220-
documents: documents,
221-
baseUrl,
222-
baseHeaders,
223-
documentReferenceId: existingDocuments[0]?.id,
224-
});
260+
const uploadSession: UploadSession = await getUploadSession();
225261

226262
setUploadSession(uploadSession);
227263
const uploadingDocuments = markDocumentsAsUploading(documents, uploadSession);
@@ -282,6 +318,41 @@ const DocumentUploadPage = (): React.JSX.Element => {
282318
);
283319
};
284320

321+
const handleDocReviewStatusResult = (result: DocumentReviewStatusDto): void => {
322+
setDocuments((previousState) =>
323+
previousState.map((doc) => {
324+
if (doc.id !== result.id) {
325+
return doc;
326+
}
327+
328+
const updatedDoc = {
329+
...doc,
330+
};
331+
332+
switch (result.status) {
333+
case DocumentReviewStatus.PENDING_REVIEW:
334+
updatedDoc.state = DOCUMENT_UPLOAD_STATE.SUCCEEDED;
335+
break;
336+
337+
case DocumentReviewStatus.VIRUS_SCAN_FAILED:
338+
updatedDoc.state = DOCUMENT_UPLOAD_STATE.INFECTED;
339+
break;
340+
341+
case DocumentReviewStatus.REVIEW_PENDING_UPLOAD:
342+
updatedDoc.state = DOCUMENT_UPLOAD_STATE.SCANNING;
343+
break;
344+
345+
default:
346+
updatedDoc.state = DOCUMENT_UPLOAD_STATE.ERROR;
347+
updatedDoc.errorCode = result.reviewReason;
348+
break;
349+
}
350+
351+
return updatedDoc;
352+
}),
353+
);
354+
};
355+
285356
const startIntervalTimer = (uploadDocuments: Array<UploadDocument>): number => {
286357
return window.setInterval(async () => {
287358
interval.current = interval.current + 1;
@@ -314,14 +385,29 @@ const DocumentUploadPage = (): React.JSX.Element => {
314385
setDocuments(updatedDocuments);
315386
} else {
316387
try {
317-
const documentStatusResult = await getDocumentStatus({
318-
documents: uploadDocuments,
319-
baseUrl,
320-
baseHeaders,
321-
nhsNumber,
322-
});
323-
324-
handleDocStatusResult(documentStatusResult);
388+
if (patientDetails?.canManageRecord) {
389+
const documentStatusResult = await getDocumentStatus({
390+
documents: uploadDocuments,
391+
baseUrl,
392+
baseHeaders,
393+
nhsNumber,
394+
});
395+
396+
handleDocStatusResult(documentStatusResult);
397+
}
398+
else {
399+
uploadDocuments.forEach(async document => {
400+
void getDocumentReviewStatus({
401+
document,
402+
baseUrl,
403+
baseHeaders,
404+
nhsNumber,
405+
}).then(handleDocReviewStatusResult).catch((e) => {
406+
const error = e as AxiosError;
407+
navigate(routes.SERVER_ERROR + errorToParams(error));
408+
});
409+
});
410+
}
325411
} catch (e) {
326412
const error = e as AxiosError;
327413
navigate(routes.SERVER_ERROR + errorToParams(error));

app/src/pages/patientResultPage/PatientResultPage.test.tsx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ describe('PatientResultPage', () => {
237237

238238
const results = await runAxeTest(document.body);
239239
expect(results).toHaveNoViolations();
240-
});
240+
});
241241
});
242242

243243
describe('Navigation', () => {
@@ -258,6 +258,33 @@ describe('PatientResultPage', () => {
258258
});
259259
});
260260

261+
it('navigates to upload page after user selects patient they cannot manage when role is GP Clinical and feature flag is enabled', async () => {
262+
const patient = buildPatientDetails({ canManageRecord: false });
263+
264+
mockedUsePatient.mockReturnValue(patient);
265+
mockedUseRole.mockReturnValue(REPOSITORY_ROLE.GP_CLINICAL);
266+
mockedUseConfig.mockReturnValue({
267+
featureFlags: {
268+
uploadLambdaEnabled: true,
269+
uploadArfWorkflowEnabled: false,
270+
uploadLloydGeorgeWorkflowEnabled: true,
271+
uploadDocumentIteration3Enabled: true,
272+
},
273+
mockLocal: {},
274+
});
275+
276+
render(<PatientResultPage />);
277+
await userEvent.click(
278+
screen.getByRole('button', {
279+
name: CONFIRM_BUTTON_TEXT,
280+
}),
281+
);
282+
283+
await waitFor(() => {
284+
expect(mockedUseNavigate).toHaveBeenCalledWith(routes.DOCUMENT_UPLOAD);
285+
});
286+
});
287+
261288
it.each([REPOSITORY_ROLE.GP_ADMIN, REPOSITORY_ROLE.GP_CLINICAL])(
262289
"navigates to Lloyd George Record page after user selects Active patient, when role is '%s' and uploadDocumentIteration3Enabled is false",
263290
async (role) => {
@@ -276,7 +303,7 @@ describe('PatientResultPage', () => {
276303
);
277304

278305
it.each([REPOSITORY_ROLE.GP_ADMIN, REPOSITORY_ROLE.GP_CLINICAL])(
279-
"navigates to patient documents page after user selects Active patient, when role is '%s' and uploadDocumentIteration3Enabled is true",
306+
"navigates to patient documents page after user selects Active patient and canManageRecord, when role is '%s' and uploadDocumentIteration3Enabled is true",
280307
async (role) => {
281308
const patient = buildPatientDetails({ active: true });
282309
mockedUseRole.mockReturnValue(role);

app/src/pages/patientResultPage/PatientResultPage.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ const PatientResultPage = (): React.JSX.Element => {
3737
return;
3838
}
3939

40+
if (!patientDetails.canManageRecord && featureFlags.uploadDocumentIteration3Enabled) {
41+
navigate(routes.DOCUMENT_UPLOAD);
42+
return;
43+
}
44+
4045
if (patientDetails?.active) {
4146
navigate(
4247
featureFlags.uploadDocumentIteration3Enabled

app/src/types/generic/patientDetails.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ export type PatientDetails = {
88
restricted: boolean;
99
active: boolean;
1010
deceased: boolean;
11+
canManageRecord?: boolean;
1112
};

app/src/types/generic/uploadResult.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export type UploadSession = {
44

55
export type S3Upload = {
66
url: string;
7-
fields: S3UploadFields;
7+
fields?: S3UploadFields;
88
};
99

1010
export type S3UploadFields = {

0 commit comments

Comments
 (0)