Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add pager (and others) to contact info #2936

Merged
merged 12 commits into from
Nov 21, 2024
3 changes: 1 addition & 2 deletions containers/ecr-viewer/src/app/api/fhirPath.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
patientNameList: "Bundle.entry.resource.where(resourceType = 'Patient').name"
patientAddressList: "Bundle.entry.resource.where(resourceType = 'Patient').address"
patientPhoneNumbers: "Bundle.entry.resource.where(resourceType = 'Patient').telecom.where(system = 'phone')"
patientEmails: "Bundle.entry.resource.where(resourceType = 'Patient').telecom.where(system = 'email')"
patientTelecom: "Bundle.entry.resource.where(resourceType = 'Patient').telecom"
patientCounty: "Bundle.entry.resource.where(resourceType = 'Patient').address.first().county"

patientIds: "Bundle.entry.resource.where(resourceType = 'Patient').identifier"
Expand Down
6 changes: 3 additions & 3 deletions containers/ecr-viewer/src/app/services/ecrMetadataService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export const evaluateEcrMetadata = (
},
{
title: "Custodian Contact",
value: formatContactPoint(custodian?.telecom).join("\n"),
value: formatContactPoint(custodian?.telecom),
},
];

Expand Down Expand Up @@ -250,7 +250,7 @@ const evaluateEcrAuthorDetails = (
},
{
title: "Author Contact",
value: formatContactPoint(practitioner?.telecom).join("\n"),
value: formatContactPoint(practitioner?.telecom),
},
{
title: "Author Facility Name",
Expand All @@ -270,7 +270,7 @@ const evaluateEcrAuthorDetails = (
},
{
title: "Author Facility Contact",
value: formatContactPoint(organization?.telecom).join("\n"),
value: formatContactPoint(organization?.telecom),
},
]);
}
Expand Down
6 changes: 4 additions & 2 deletions containers/ecr-viewer/src/app/services/ecrSummaryService.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Bundle, Condition, Extension, Observation } from "fhir/r4";
import { evaluateData, PathMappings } from "@/app/view-data/utils/utils";
import {
formatContactPoint,
formatDate,
formatStartEndDateTime,
} from "@/app/services/formatService";
import { evaluate } from "@/app/view-data/utils/evaluate";
import {
evaluatePatientName,
evaluatePatientContactInfo,
evaluatePatientAddress,
evaluateEncounterDiagnosis,
} from "./evaluateFhirDataService";
Expand Down Expand Up @@ -72,7 +72,9 @@ export const evaluateEcrSummaryPatientDetails = (
},
{
title: "Patient Contact",
value: evaluatePatientContactInfo(fhirBundle, fhirPathMappings),
value: formatContactPoint(
evaluate(fhirBundle, fhirPathMappings.patientTelecom),
),
},
]);
};
Expand Down
28 changes: 3 additions & 25 deletions containers/ecr-viewer/src/app/services/evaluateFhirDataService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,26 +159,6 @@ export const evaluateEncounterId = (
return filteredIds[0] ?? "";
};

/**
* Evaluates patient contact info from the FHIR bundle and formats it into structured data for display.
* @param fhirBundle - The FHIR bundle containing patient contact info.
* @param mappings - The object containing the fhir paths.
* @returns All phone numbers and emails seperated by new lines
*/
export const evaluatePatientContactInfo = (
fhirBundle: Bundle,
mappings: PathMappings,
) => {
const phoneNumbers = formatContactPoint(
evaluate(fhirBundle, mappings.patientPhoneNumbers),
).join("\n");
const emails = evaluate(fhirBundle, mappings.patientEmails)
.map((email) => `${email.value}`)
.join("\n");

return `${phoneNumbers}\n${emails}`;
};

/**
* Calculates the age of a patient to a given date or today, unless DOD exists.
* @param fhirBundle - The FHIR bundle containing patient information.
Expand Down Expand Up @@ -340,7 +320,7 @@ export const evaluateDemographicsData = (
},
{
title: "Contact",
value: evaluatePatientContactInfo(fhirBundle, mappings),
value: formatContactPoint(evaluate(fhirBundle, mappings.patientTelecom)),
},
{
title: "Emergency Contact",
Expand Down Expand Up @@ -509,7 +489,7 @@ export const evaluateProviderData = (
},
{
title: "Provider Contact",
value: formatContactPoint(practitioner?.telecom).join("\n"),
value: formatContactPoint(practitioner?.telecom),
},
{
title: "Provider Facility Name",
Expand Down Expand Up @@ -565,9 +545,7 @@ export const evaluateEmergencyContact = (

const phoneNumbers = formatContactPoint(contact.telecom);

return [relationship, address, ...phoneNumbers]
.filter(Boolean)
.join("\n");
return [relationship, address, phoneNumbers].filter(Boolean).join("\n");
})
.join("\n\n");
};
Expand Down
68 changes: 48 additions & 20 deletions containers/ecr-viewer/src/app/services/formatService.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -563,36 +563,64 @@ export const removeHtmlElements = (element: string): string => {
return element.replace(regex, "");
};

const contactSortOrder = [
"phone",
"fax",
"sms",
"pager",
"url",
"email",
"other",
"",
];

/**
* Converts contact points into an array of phone numbers and emails
* Sorts an array of contact points in display order (`contactSortOrder`).
* @param contactPoints - array of contact points
* @returns array of phone numbers and emails
* @returns sorted array of contact points
*/
const sortContacts = (contactPoints: ContactPoint[]): ContactPoint[] => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a JSDoc for this helper function?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added!

return contactPoints.sort((a, b) => {
const aInd =
contactSortOrder.indexOf(a.system ?? "") ?? contactSortOrder.length;
const bInd =
contactSortOrder.indexOf(b.system ?? "") ?? contactSortOrder.length;
return aInd - bInd;
});
};

/**
* Converts contact points into an array of phone numbers and emails and returns them
* in a consistent sort order for display.
* @param contactPoints - array of contact points
* @returns string of formatted and sorted phone numbers and emails
*/
export const formatContactPoint = (
contactPoints: ContactPoint[] | undefined,
): string[] => {
): string => {
if (!contactPoints || !contactPoints.length) {
return [];
return "";
}
const contactArr: string[] = [];
for (const contactPoint of contactPoints) {
if (contactPoint.system === "phone" && contactPoint.value) {
const phoneNumberUse = toSentenceCase(contactPoint.use);
contactArr.push(
[phoneNumberUse, formatPhoneNumber(contactPoint.value)]
.filter((c) => c)
.join(": "),
);
} else if (contactPoint.system === "email" && contactPoint.value) {
contactArr.push(contactPoint.value);
} else if (contactPoint.system === "fax" && contactPoint.value) {
const faxNumberUse = toSentenceCase(contactPoint.use ?? "");
for (const { system, value, use } of sortContacts(contactPoints)) {
// No value, nothing to format/show
if (!value) continue;

if (system === "phone") {
const phoneNumberUse = toSentenceCase(use);
contactArr.push(
[faxNumberUse, "Fax:", formatPhoneNumber(contactPoint.value ?? "")]
.join(" ")
.trim(),
[phoneNumberUse, formatPhoneNumber(value)].filter((c) => c).join(": "),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the .filter((c) => c) still necessary here? Since we're already checking if there's a value on line 601

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, because Use might be empty and then we don't want the : rendered

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh, good call! Thanks!!

);
} else if (system === "email") {
contactArr.push(value);
} else {
const _use = toSentenceCase(use ?? "");
const _system = toSentenceCase(system ?? "");
const _value = ["fax", "pager", "sms"].includes(system as string)
? formatPhoneNumber(value)
: value;
contactArr.push([_use, `${_system}:`, _value].join(" ").trim());
}
}
return contactArr;
return contactArr.join("\n");
};
Original file line number Diff line number Diff line change
Expand Up @@ -62,26 +62,6 @@ exports[`Snapshot test for Accordion Content Given no data, info message for emp
class="section__line_gray"
/>
</div>
<div>
<div
class="grid-row"
>
<div
class="data-title padding-right-1"
>
Contact
</div>
<div
class="grid-col maxw7 text-pre-line"
>


</div>
</div>
<div
class="section__line_gray"
/>
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -455,6 +435,25 @@ exports[`Snapshot test for Accordion Content Given no data, info message for emp
class="section__line_gray"
/>
</div>
<div>
<div
class="grid-row"
>
<div
class="data-title padding-right-1"
>
Contact
</div>
<div
class="grid-col maxw7 text-pre-line text-italic text-base"
>
No data
</div>
</div>
<div
class="section__line_gray"
/>
</div>
<div>
<div
class="grid-row"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -609,15 +609,15 @@ describe("formatVitals", () => {
});

describe("formatContactPoint", () => {
it("should return empty array if contact points is null", () => {
it("should return empty string if contact points is null", () => {
const actual = formatContactPoint(undefined);
expect(actual).toBeEmpty();
expect(actual).toBe("");
});
it("should return empty array if contact points is contact points is empty", () => {
it("should return empty string if contact points is contact points is empty", () => {
const actual = formatContactPoint([]);
expect(actual).toBeEmpty();
expect(actual).toBe("");
});
it("should return empty array if contact point value is empty ", () => {
it("should return empty string if contact point value is empty ", () => {
const contactPoints: ContactPoint[] = [
{
system: "phone",
Expand All @@ -629,7 +629,7 @@ describe("formatContactPoint", () => {
},
];
const actual = formatContactPoint(contactPoints);
expect(actual).toBeEmpty();
expect(actual).toBe("");
});
it("should return phone contact information ", () => {
const contactPoints: ContactPoint[] = [
Expand All @@ -644,7 +644,7 @@ describe("formatContactPoint", () => {
},
];
const actual = formatContactPoint(contactPoints);
expect(actual).toEqual(["Work: 248-555-1234", "313-555-1234"]);
expect(actual).toEqual("Work: 248-555-1234\n313-555-1234");
});
it("should return email information ", () => {
const contactPoints: ContactPoint[] = [
Expand All @@ -659,7 +659,7 @@ describe("formatContactPoint", () => {
},
];
const actual = formatContactPoint(contactPoints);
expect(actual).toEqual(["[email protected]", "medicine@example.com"]);
expect(actual).toEqual("[email protected]\nmedicine@example.com");
});
it("should return fax information ", () => {
const contactPoints: ContactPoint[] = [
Expand All @@ -674,7 +674,40 @@ describe("formatContactPoint", () => {
},
];
const actual = formatContactPoint(contactPoints);
expect(actual).toEqual(["Work Fax: 313-555-1234", "Fax: 313-555-1235"]);
expect(actual).toEqual("Work Fax: 313-555-1234\nFax: 313-555-1235");
});
it("should sort by system ", () => {
const contactPoints: ContactPoint[] = [
{
system: "fax",
value: "+13135551234",
use: "work",
},
{
system: "email",
value: "[email protected]",
},
{
system: "pager",
value: "+1 313 555-1235",
},
{
system: "phone",
value: "+1 313 555-1236",
},
{
system: "email",
value: "[email protected]",
},
{
system: "other",
value: "123",
},
];
const actual = formatContactPoint(contactPoints);
expect(actual).toEqual(
"313-555-1236\nWork Fax: 313-555-1234\nPager: 313-555-1235\[email protected]\[email protected]\nOther: 123",
);
});
});

Expand Down
2 changes: 1 addition & 1 deletion containers/fhir-converter/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build

# Download FHIR-Converter
RUN git clone https://github.com/skylight-hq/FHIR-Converter.git --branch v7.0-skylight-11 --single-branch /build/FHIR-Converter
RUN git clone https://github.com/skylight-hq/FHIR-Converter.git --branch v7.0-skylight-12 --single-branch /build/FHIR-Converter

WORKDIR /build/FHIR-Converter

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2107,6 +2107,10 @@
'use': 'work',
'value': '+1-777-666-5658',
}),
dict({
'system': 'pager',
'value': '+1-777-666-5659',
}),
]),
}),
]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
</addr>
<telecom use="HP" value="tel:+1-777-666-5657" />
<telecom use="WP" value="tel:+1-777-666-5658" />
<telecom use="PG" value="tel:+1-777-666-5659" />
<associatedPerson>
<name>
<given>Mama</given>
Expand Down
Loading