Skip to content

Commit 44b680e

Browse files
committed
feat: Improve formatting on submit
[OCR-SCAN]
1 parent 6f13d67 commit 44b680e

File tree

2 files changed

+73
-47
lines changed

2 files changed

+73
-47
lines changed

frontend/src/app/pages/resource-ocr/encounter-form/encounter-form.component.ts

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ import { ResponseWrapper } from 'src/app/models/response-wrapper';
5050
import { Router } from '@angular/router';
5151
import {
5252
flattenTextFields,
53-
normalizeDates,
53+
normalizeFormValues,
5454
parsePractitionerName,
5555
} from 'src/lib/utils/format_functions';
5656

@@ -375,12 +375,6 @@ export class EncounterFormComponent implements OnInit {
375375
};
376376

377377
medicationGroup.get('data')?.setValue(nlmSearchResult);
378-
} else {
379-
medicationGroup.get('data')?.setValue({
380-
id: uuidV4(),
381-
text: enrichedMed.extracted_name,
382-
identifier: [uuidV4()],
383-
});
384378
}
385379

386380
// Set up the value change subscription for dosage enabling
@@ -910,22 +904,27 @@ export class EncounterFormComponent implements OnInit {
910904

911905
onSubmit() {
912906
this.form.markAllAsTouched();
913-
if (this.form.valid) {
914-
this.submitWizardLoading = true;
907+
if (!this.form.valid) {
908+
// Exit early if the form is invalid
909+
return;
910+
}
911+
912+
this.submitWizardLoading = true;
913+
this.error = null; // Clear previous errors
915914

915+
try {
916+
// --- Synchronous Data Processing ---
916917
let formValue = this.form.getRawValue();
917918

918-
// Normalize only organizations and practitioners
919+
// Normalize organizations and practitioners
919920
formValue.organizations = formValue.organizations.map((org: any) => ({
920921
...org,
921922
data: flattenTextFields(org.data),
922923
}));
923924

924925
formValue.practitioners = formValue.practitioners.map((prac: any) => {
925926
const flattenedData = flattenTextFields(prac.data);
926-
927927
const parsedName = parsePractitionerName(flattenedData.name);
928-
929928
return {
930929
...prac,
931930
data: {
@@ -935,42 +934,35 @@ export class EncounterFormComponent implements OnInit {
935934
};
936935
});
937936

938-
// Normalize dates in the entire form
939-
formValue = normalizeDates(formValue);
940-
941-
let resourceStorage = GenerateR4ResourceLookup(formValue);
937+
// Normalize dates and addresses and generate resource lookup
938+
formValue = normalizeFormValues(formValue);
939+
const resourceStorage = GenerateR4ResourceLookup(formValue);
942940

943-
//generate a ndjson file from the resourceList
944-
//make sure we extract the encounter resource
945-
946-
let fhirListResource = {
941+
// --- FHIR Resource Construction ---
942+
const fhirListResource = {
947943
resourceType: 'List',
948944
entry: [],
949945
encounter: null,
950946
contained: [],
951947
} as List;
952948

953949
let encounter = null;
954-
for (let resourceType in resourceStorage) {
950+
for (const resourceType in resourceStorage) {
955951
if (resourceType === 'Encounter') {
956-
//set the encounter to the first encounter
957-
let [encounterId] = Object.keys(resourceStorage[resourceType]);
952+
const [encounterId] = Object.keys(resourceStorage[resourceType]);
958953
encounter = resourceStorage[resourceType][encounterId];
959-
960954
if (!(encounter.type && encounter.reference)) {
961-
//this is not a reference
962955
fhirListResource.contained.push(encounter);
963956
}
964957
continue;
965958
}
966959

967-
for (let resourceId in resourceStorage[resourceType]) {
968-
let resourceFromStorage = resourceStorage[resourceType][resourceId];
960+
for (const resourceId in resourceStorage[resourceType]) {
961+
const resourceFromStorage = resourceStorage[resourceType][resourceId];
969962
if (
970963
(resourceFromStorage as Reference).type &&
971964
(resourceFromStorage as Reference).reference
972965
) {
973-
//this is a reference
974966
fhirListResource.entry.push({
975967
item: {
976968
reference:
@@ -980,35 +972,42 @@ export class EncounterFormComponent implements OnInit {
980972
},
981973
});
982974
} else {
983-
//this is not a reference
984975
fhirListResource.contained.push(
985976
resourceFromStorage as FhirResource
986977
);
987978
}
988979
}
989980
}
990981

991-
//set the encounter reference
982+
// Set the encounter reference
992983
fhirListResource.encounter = {
993984
reference: generateReferenceUriFromResourceOrReference(encounter),
994985
};
995986

996987
this.fastenApi
997988
.createRelatedResourcesFastenSource(fhirListResource)
998-
.subscribe(
999-
(resp) => {
989+
.subscribe({
990+
next: (resp) => {
1000991
this.submitWizardLoading = false;
1001-
// Redirect user to /medical-history after successful submission
992+
993+
// On success, redirect the user
1002994
this.router.navigate(['/medical-history']);
1003995
},
1004-
(err) => {
996+
error: (err) => {
997+
// Handle HTTP errors from the API call
1005998
this.error =
1006999
err?.error?.message ||
10071000
'An error occurred while submitting the form. Please try again.';
1008-
console.error(err);
1001+
console.error('API Error:', err);
10091002
this.submitWizardLoading = false;
1010-
}
1011-
);
1003+
},
1004+
});
1005+
} catch (err) {
1006+
// Catches errors from the data processing steps above.
1007+
this.error =
1008+
'An unexpected error occurred while preparing your data. Please check the form and try again.';
1009+
console.error('Data Processing Error:', err);
1010+
this.submitWizardLoading = false; // Ensure loading is stopped
10121011
}
10131012
}
10141013

frontend/src/lib/utils/format_functions.ts

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,50 @@ export function flattenTextFields(obj: any): any {
3636
return newObj;
3737
}
3838

39-
export function normalizeDates(obj: any): any {
39+
export function normalizeFormValues(
40+
obj: any,
41+
parentKey: string | null = null
42+
): any {
43+
// Return primitives and null values as is
44+
if (obj === null || typeof obj !== 'object') {
45+
return obj;
46+
}
47+
48+
// If it's an array, recursively process each item
4049
if (Array.isArray(obj)) {
41-
return obj.map(normalizeDates);
42-
} else if (obj !== null && typeof obj === 'object') {
43-
// Handle Angular datepicker object {year, month, day}
44-
if ('year' in obj && 'month' in obj && 'day' in obj) {
50+
return obj.map((item) => normalizeFormValues(item, parentKey));
51+
}
52+
53+
// --- Logic from normalizeDates --- //
54+
55+
// Skip processing children of 'medications'
56+
if (parentKey === 'medications') {
57+
return obj;
58+
}
59+
60+
// Handle Angular datepicker object: {year, month, day}
61+
if ('year' in obj && 'month' in obj && 'day' in obj) {
62+
// A simple check to avoid matching objects that coincidentally have these keys
63+
if (Object.keys(obj).length === 3) {
4564
const date = new Date(obj.year, obj.month - 1, obj.day);
4665
return date.toISOString();
4766
}
67+
}
4868

49-
const newObj: any = {};
50-
for (const key of Object.keys(obj)) {
51-
newObj[key] = normalizeDates(obj[key]);
69+
// --- Combined Recursive Logic --- //
70+
const newObj: any = {};
71+
for (const key of Object.keys(obj)) {
72+
// Logic from normalizeAddresses: if the key is 'address' and the value
73+
// is a single object, wrap it in an array after processing its contents.
74+
if (key === 'address' && obj[key] && !Array.isArray(obj[key])) {
75+
newObj[key] = [normalizeFormValues(obj[key], key)];
76+
} else {
77+
// Recursively process all other key-value pairs
78+
newObj[key] = normalizeFormValues(obj[key], key);
5279
}
53-
return newObj;
5480
}
55-
return obj;
81+
82+
return newObj;
5683
}
5784

5885
export function parsePractitionerName(fullName: string) {

0 commit comments

Comments
 (0)