Skip to content
This repository has been archived by the owner on Nov 30, 2023. It is now read-only.

Commit

Permalink
Ctw 354/manage inconsistent coding in history panel (#88)
Browse files Browse the repository at this point in the history
Manage inconsistent coding in Conditions History Panel. Now supports
SNOMED, ICD-10, ICD-10CM, ICD-9, ICD-9CM for code matching. Will now
filter out summary and lens tags as well. Also now uses react query for
history searches for faster performance when going back to already
visited history searches.
  • Loading branch information
luthfib committed Oct 4, 2022
1 parent 5235049 commit 67ddbb0
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 118 deletions.
5 changes: 5 additions & 0 deletions .changeset/dirty-pandas-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@zus-health/ctw-component-library": minor
---

Manage inconsistent coding in Conditions History Panel. Now supports SNOMED, ICD-10, ICD-10CM, ICD-9, ICD-9CM for code matching. Will now filter out summary and lens tags as well.
9 changes: 3 additions & 6 deletions src/components/content/conditions-history-drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ConditionHistory } from "./conditions-history";

export type ConditionHistoryDrawerProps = {
className?: string;
condition?: ConditionModel;
condition: ConditionModel;
isOpen: boolean;
onClose: () => void;
};
Expand All @@ -15,11 +15,8 @@ export function ConditionHistoryDrawer({
isOpen,
onClose,
}: ConditionHistoryDrawerProps) {
const data = ConditionHistory({
icd10Code: condition?.icd10Code,
snomedCode: condition?.snomedCode,
});
const conditionName = condition?.display;
const data = ConditionHistory({ condition });
const conditionName = condition.display;
const title = "Condition History";

return (
Expand Down
173 changes: 86 additions & 87 deletions src/components/content/conditions-history.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { getConditionHistory } from "@/fhir/conditions";
import { useFhirClientRef } from "@/fhir/utils";
import { ConditionModel } from "@/models/conditions";
import { useQuery } from "@tanstack/react-query";
import { useEffect, useState } from "react";
import { useCTW } from "../core/ctw-provider";
import {
DataListStack,
DataListStackEntries,
Expand All @@ -12,110 +13,108 @@ import { Spinner } from "../core/spinner";

const CONDITION_HISTORY_LIMIT = 10;

export type ConditionHistoryProps = {
icd10Code?: string | undefined;
snomedCode?: string | undefined;
};

export function ConditionHistory({
icd10Code,
snomedCode,
}: ConditionHistoryProps) {
export function ConditionHistory({ condition }: { condition: ConditionModel }) {
const [conditions, setConditions] = useState<DataListStackEntries>([]);
const [loading, setLoading] = useState(true);
const { getCTWFhirClient } = useCTW();
const [patientUPID, setPatientUPID] = useState("");
const [conditionForSearch, setConditionForSearch] =
useState<ConditionModel>();
const fhirClientRef = useFhirClientRef();
const { patientPromise } = usePatient();
const historyResponse = useQuery(
["conditions", patientUPID, conditionForSearch],
getConditionHistory,
{
enabled: !!patientUPID && !!fhirClientRef,
meta: { fhirClientRef },
}
);

useEffect(() => {
async function load() {
const fhirClient = await getCTWFhirClient();
setConditionForSearch(condition);
const patientTemp = await patientPromise;
if (patientTemp.UPID) {
setPatientUPID(patientTemp.UPID);
}

const allConditions = await getConditionHistory(
fhirClient,
patientTemp.UPID
);
const models = allConditions.map(
(condition) => new ConditionModel(condition)
);

const filteredConditions = models.filter(
(condition) =>
(condition.icd10Code === icd10Code &&
typeof icd10Code !== "undefined") ||
(condition.snomedCode === snomedCode &&
typeof snomedCode !== "undefined")
);

setConditions(filteredConditions.map((model) => setupData(model)));
setLoading(false);
}

load();

function setupData(condition: ConditionModel): DataListStackEntry {
let data = [
{
label: "Verification Status",
value: condition.verificationStatus,
},
{
label: "Clinical Status",
value: condition.clinicalStatus,
},
{
label: "Recorded Date",
value: condition.recordedDate,
},
];
const ICD10Fields = [
{
label: "ICD10 Display",
value: condition.icd10Display,
},
{
label: "ICD10 Code",
value: condition.icd10Code,
},
{
label: "ICD10 System",
value: condition.icd10System,
},
];
const SNOMEDFields = [
{
label: "SNOMED Display",
value: condition.snomedDisplay,
},
{
label: "SNOMED Code",
value: condition.snomedCode,
},
{
label: "SNOMED System",
value: condition.snomedSystem,
},
];
if (historyResponse.data) {
const filteredConditions = historyResponse.data.map(
(c) => new ConditionModel(c)
);

if (icd10Code) {
data = data.concat(ICD10Fields);
setConditions(filteredConditions.map((model) => setupData(model)));
setLoading(false);
}

if (snomedCode) {
data = data.concat(SNOMEDFields);
function setupData(
conditionForSetup: ConditionModel
): DataListStackEntry {
let data = [
{
label: "Verification Status",
value: conditionForSetup.verificationStatus,
},
{
label: "Clinical Status",
value: conditionForSetup.clinicalStatus,
},
{
label: "Recorded Date",
value: conditionForSetup.recordedDate,
},
];
const ICD10Fields = [
{
label: "ICD10 Display",
value: conditionForSetup.icd10Display,
},
{
label: "ICD10 Code",
value: conditionForSetup.icd10Code,
},
{
label: "ICD10 System",
value: conditionForSetup.icd10System,
},
];
const SNOMEDFields = [
{
label: "SNOMED Display",
value: conditionForSetup.snomedDisplay,
},
{
label: "SNOMED Code",
value: conditionForSetup.snomedCode,
},
{
label: "SNOMED System",
value: conditionForSetup.snomedSystem,
},
];

if (conditionForSetup.icd10Code) {
data = data.concat(ICD10Fields);
}

if (conditionForSetup.snomedCode) {
data = data.concat(SNOMEDFields);
}

return {
id: conditionForSetup.id,
data: [...data],
};
}

return {
id: condition.id,
data: [...data],
};
}

load();

return function cleanup() {
setConditions([]);
setLoading(true);
};
}, [getCTWFhirClient, icd10Code, snomedCode, patientPromise]);
}, [condition, patientPromise, historyResponse.data]);

if (conditions.length === 0 && !loading) {
return <div>No history found.</div>;
Expand Down
8 changes: 4 additions & 4 deletions src/components/core/ctw-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ function CTWProvider({ theme, children, ...ctwState }: CTWProviderProps) {

return (
<div style={mapToCSSVar(theme?.colors || {})}>
<QueryClientProvider client={queryClient}>
<CTWStateContext.Provider value={providerState}>
<CTWStateContext.Provider value={providerState}>
<QueryClientProvider client={queryClient}>
{children}
</CTWStateContext.Provider>
</QueryClientProvider>
</QueryClientProvider>
</CTWStateContext.Provider>
</div>
);
}
Expand Down
27 changes: 22 additions & 5 deletions src/fhir/conditions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ConditionModel } from "@/models/conditions";
import { QueryFunctionContext } from "@tanstack/react-query";
import Client from "fhir-kit-client";
import { sortBy } from "lodash";

import {
Expand All @@ -19,10 +18,10 @@ import {
import { getFhirClientFromQuery } from "./utils";

export const CONDITION_CODE_SYSTEMS = [
SYSTEM_ICD9_CM,
SYSTEM_ICD9,
SYSTEM_ICD10_CM,
SYSTEM_ICD9_CM,
SYSTEM_ICD10,
SYSTEM_ICD10_CM,
SYSTEM_SNOMED,
];

Expand All @@ -38,6 +37,11 @@ export type ConditionFilters = {
"clinical-status"?: ClinicalStatus | ClinicalStatus[];
};

export type QueryKeyConditionHistory = [
string,
string,
ConditionModel | undefined
];
export type QueryKeyPatientConditions = [string, string, ConditionFilters];
export type QueryKeyOtherProviderConditions = [string, string];

Expand Down Expand Up @@ -87,18 +91,31 @@ export async function getOtherProviderConditions(
}

export async function getConditionHistory(
fhirClient: Client,
patientUPID: string
queryParams: QueryFunctionContext<QueryKeyConditionHistory>
) {
try {
const { meta, queryKey } = queryParams;
const fhirClient = getFhirClientFromQuery(meta);
const [_, patientUPID, condition] = queryKey;

if (!condition) {
throw Error("Condition is required");
}

const tokens = condition.knownCodings.map(
(coding) => `${coding.system}|${coding.code}`
);

const { resources: conditions } = await searchCommonRecords(
"Condition",
fhirClient,
{
patientUPID,
_include: ["Condition:patient", "Condition:encounter"],
code: tokens.join(","),
}
);

return conditions;
} catch (e) {
throw new Error(
Expand Down
2 changes: 1 addition & 1 deletion src/fhir/search-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export async function searchCommonRecords<T extends ResourceTypeString>(
): Promise<SearchReturn<T>> {
return searchAllRecords(resourceType, fhirClient, {
...searchParams,
"_tag:not": LENS_TAGS.join(","),
"_tag:not": [...LENS_TAGS, ...SUMMARY_TAGS].join(","),
});
}

Expand Down
6 changes: 3 additions & 3 deletions src/fhir/system-urls.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export const SYSTEM_CCS =
"https://www.hcup-us.ahrq.gov/toolssoftware/ccsr/dxccsr.jsp";

export const SYSTEM_CONDITION_VERIFICATION_STATUS =
"http://terminology.hl7.org/CodeSystem/condition-ver-status";

export const SYSTEM_CONDITION_CLINICAL =
"http://terminology.hl7.org/CodeSystem/condition-clinical";

export const SYSTEM_CONDITION_VERIFICATION_STATUS =
"http://terminology.hl7.org/CodeSystem/condition-ver-status";

export const SYSTEM_ICD9 = "http://hl7.org/fhir/sid/icd-9";

export const SYSTEM_ICD9_CM = "http://hl7.org/fhir/sid/icd-9-cm";
Expand Down
24 changes: 12 additions & 12 deletions src/models/conditions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ export class ConditionModel {
);
}

get ccsGrouping(): string | undefined {
return findCoding(SYSTEM_CCS, this.resource.code)?.display;
}

get clinicalStatus(): string {
return codeableConceptLabel(this.resource.clinicalStatus);
}
Expand All @@ -73,14 +77,6 @@ export class ConditionModel {
);
}

get knownCodings(): fhir4.Coding[] {
return compact(
CONDITION_CODE_SYSTEMS.map((system) =>
findCoding(system, this.resource.code)
)
);
}

get icd10Code(): string | undefined {
return findCoding(SYSTEM_ICD10, this.resource.code)?.code;
}
Expand All @@ -93,14 +89,18 @@ export class ConditionModel {
return findCoding(SYSTEM_ICD10, this.resource.code)?.display;
}

get ccsGrouping(): string | undefined {
return findCoding(SYSTEM_CCS, this.resource.code)?.display;
}

get id(): string {
return this.resource.id || "";
}

get knownCodings(): fhir4.Coding[] {
return compact(
CONDITION_CODE_SYSTEMS.map((system) =>
findCoding(system, this.resource.code)
)
);
}

get notes(): string[] {
return this.resource.note?.map((note) => note.text) || [];
}
Expand Down

0 comments on commit 67ddbb0

Please sign in to comment.