Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,6 @@ npm run ehr:e2e:local:ui

Full E2E Documentation: [E2E_README.md](./E2E_README.md)

## Setting up Terminology Search

<!-- cSpell:disable-next umls -->

Ottehr uses UMLS Terminology Services for searching for ICD-10 and CPT codes.

To set up the terminology search service, please follow these instructions in the [Oystehr docs](https://docs.oystehr.com/oystehr/services/zambda/examples/terminology-search/#1-get-a-national-library-of-medicine-api-key), and then save the API key as `NLM_API_KEY` in the Zambdas secrets.

## Repository Structure

This repository uses a monorepo structure.
Expand Down
4 changes: 2 additions & 2 deletions apps/ehr/src/components/input/SingleCptInput.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from 'react';
import { useGetIcd10Search } from 'src/features/visits/shared/stores/appointment/appointment.queries';
import { useDebounce } from 'src/shared/hooks/useDebounce';
import { CPTCodeDTO } from 'utils';
import { useGetCPTHCPCSSearch } from '../../features/visits/shared/stores/appointment/appointment.queries';
import { AutocompleteInput } from './AutocompleteInput';

type Props = {
Expand All @@ -13,7 +13,7 @@ type Props = {

export const SingleCptCodeInput: React.FC<Props> = ({ name, label, required, dataTestId }) => {
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
const { isFetching, data } = useGetIcd10Search({ search: debouncedSearchTerm, sabs: 'CPT' });
const { isFetching, data } = useGetCPTHCPCSSearch({ search: debouncedSearchTerm, type: 'both' });
const options = ((data as { codes?: CPTCodeDTO[] })?.codes || []).map((cptCodeDto) => {
return {
label: `${cptCodeDto.code} ${cptCodeDto.display}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { useNavigate } from 'react-router-dom';
import { dataTestIds } from 'src/constants/data-test-ids';
import { getRadiologyUrl } from 'src/features/visits/in-person/routing/helpers';
import {
useGetIcd10Search,
useGetCPTHCPCSSearch,
useICD10SearchNew,
} from 'src/features/visits/shared/stores/appointment/appointment.queries';
import {
Expand Down Expand Up @@ -66,9 +66,9 @@ export const CreateRadiologyOrder: React.FC<CreateRadiologyOrdersProps> = () =>

// used to fetch cpt codes
const [cptDebouncedSearchTerm, setCptDebouncedSearchTerm] = useState('');
const { isFetching: isSearchingCpt, data: cptData } = useGetIcd10Search({
const { isFetching: isSearchingCpt, data: cptData } = useGetCPTHCPCSSearch({
search: cptDebouncedSearchTerm,
sabs: 'CPT',
type: 'cpt',
radiologyOnly: true, // Only fetch CPT codes related to radiology
});
const cptSearchOptions = cptData?.codes || radiologyStudiesConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import {
import { DiagnosesField } from '../../shared/components/assessment-tab/DiagnosesField';
import { PageTitle } from '../../shared/components/PageTitle';
import { useGetAppointmentAccessibility } from '../../shared/hooks/useGetAppointmentAccessibility';
import { useGetIcd10Search, useRecommendBillingCodes } from '../../shared/stores/appointment/appointment.queries';
import { useGetCPTHCPCSSearch, useRecommendBillingCodes } from '../../shared/stores/appointment/appointment.queries';
import { useChartData, useDeleteChartData, useSaveChartData } from '../../shared/stores/appointment/appointment.store';
import { useAppFlags } from '../../shared/stores/contexts/useAppFlags';
import AiSuggestion from '../components/AiSuggestion';
Expand Down Expand Up @@ -401,7 +401,7 @@ export default function ProceduresNew(): ReactElement {
};

const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
const { isFetching: isSearching, data } = useGetIcd10Search({ search: debouncedSearchTerm, sabs: 'CPT' });
const { isFetching: isSearching, data } = useGetCPTHCPCSSearch({ search: debouncedSearchTerm, type: 'both' });
const cptSearchOptions = (data as { codes?: CPTCodeDTO[] })?.codes || [];
const { debounce } = useDebounce(800);
const debouncedHandleInputChange = (data: string): void => {
Expand Down
8 changes: 0 additions & 8 deletions apps/ehr/src/features/visits/shared/api/oystehrApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import {
GetTelemedAppointmentsResponseEhr,
GetUnsolicitedResultsResourcesInput,
GetUnsolicitedResultsResourcesOutput,
IcdSearchRequestParams,
IcdSearchResponse,
InitTelemedSessionRequestParams,
InitTelemedSessionResponse,
LabOrderResourcesRes,
Expand Down Expand Up @@ -138,7 +136,6 @@ export const getOystehrTelemedAPI = (
getPatientInstructions: typeof getPatientInstructions;
savePatientInstruction: typeof savePatientInstruction;
deletePatientInstruction: typeof deletePatientInstruction;
icdSearch: typeof icdSearch;
recommendBillingSuggestions: typeof recommendBillingSuggestions;
recommendBillingCodes: typeof recommendBillingCodes;
createUpdateMedicationOrder: typeof createUpdateMedicationOrder;
Expand Down Expand Up @@ -302,10 +299,6 @@ export const getOystehrTelemedAPI = (
return await makeZapRequest('create update patient followup', parameters);
};

const icdSearch = async (parameters: IcdSearchRequestParams): Promise<IcdSearchResponse> => {
return await makeZapRequest('icd search', parameters);
};

const recommendBillingSuggestions = async (parameters: {
diagnoses: DiagnosisDTO[] | undefined;
billing: CPTCodeDTO[] | undefined;
Expand Down Expand Up @@ -394,7 +387,6 @@ export const getOystehrTelemedAPI = (
getPatientInstructions,
savePatientInstruction,
deletePatientInstruction,
icdSearch,
recommendBillingSuggestions,
recommendBillingCodes,
getMedicationOrders,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import { useDebounce } from 'src/shared/hooks/useDebounce';
import { APIErrorCode, CPTCodeOption, emCodeOptions } from 'utils';
import { useGetAppointmentAccessibility } from '../../hooks/useGetAppointmentAccessibility';
import { useGetIcd10Search } from '../../stores/appointment/appointment.queries';
import { useGetCPTHCPCSSearch } from '../../stores/appointment/appointment.queries';
import { useChartData, useDeleteChartData, useSaveChartData } from '../../stores/appointment/appointment.store';

export const BillingCodesContainer: FC = () => {
Expand All @@ -24,7 +24,7 @@
isFetching: isSearching,
data,
error: icdSearchError,
} = useGetIcd10Search({ search: debouncedSearchTerm, sabs: 'CPT' });
} = useGetCPTHCPCSSearch({ search: debouncedSearchTerm, type: 'both' });

Check failure on line 27 in apps/ehr/src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx

View workflow job for this annotation

GitHub Actions / run-pipeline / automated-tests / automated-tests (22)

tests/component/BillingCodesContainer.test.tsx > BillingCodesContainer > E&M code operations > should show error on E&M save failure

Error: [vitest] No "useGetCPTHCPCSSearch" export is defined on the "../../src/features/visits/shared/stores/appointment/appointment.queries" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside: vi.mock(import("../../src/features/visits/shared/stores/appointment/appointment.queries"), async (importOriginal) => { const actual = await importOriginal() return { ...actual, // your mocked methods } }) ❯ BillingCodesContainer src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx:27:7 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26466:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26434:7

Check failure on line 27 in apps/ehr/src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx

View workflow job for this annotation

GitHub Actions / run-pipeline / automated-tests / automated-tests (22)

tests/component/BillingCodesContainer.test.tsx > BillingCodesContainer > E&M code operations > should delete E&M code when cleared

Error: [vitest] No "useGetCPTHCPCSSearch" export is defined on the "../../src/features/visits/shared/stores/appointment/appointment.queries" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside: vi.mock(import("../../src/features/visits/shared/stores/appointment/appointment.queries"), async (importOriginal) => { const actual = await importOriginal() return { ...actual, // your mocked methods } }) ❯ BillingCodesContainer src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx:27:7 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26466:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26434:7

Check failure on line 27 in apps/ehr/src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx

View workflow job for this annotation

GitHub Actions / run-pipeline / automated-tests / automated-tests (22)

tests/component/BillingCodesContainer.test.tsx > BillingCodesContainer > E&M code operations > should update local state when E&M code selected

Error: [vitest] No "useGetCPTHCPCSSearch" export is defined on the "../../src/features/visits/shared/stores/appointment/appointment.queries" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside: vi.mock(import("../../src/features/visits/shared/stores/appointment/appointment.queries"), async (importOriginal) => { const actual = await importOriginal() return { ...actual, // your mocked methods } }) ❯ BillingCodesContainer src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx:27:7 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26466:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26434:7

Check failure on line 27 in apps/ehr/src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx

View workflow job for this annotation

GitHub Actions / run-pipeline / automated-tests / automated-tests (22)

tests/component/BillingCodesContainer.test.tsx > BillingCodesContainer > E&M code operations > should save E&M code when selected

Error: [vitest] No "useGetCPTHCPCSSearch" export is defined on the "../../src/features/visits/shared/stores/appointment/appointment.queries" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside: vi.mock(import("../../src/features/visits/shared/stores/appointment/appointment.queries"), async (importOriginal) => { const actual = await importOriginal() return { ...actual, // your mocked methods } }) ❯ BillingCodesContainer src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx:27:7 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26466:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26434:7

Check failure on line 27 in apps/ehr/src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx

View workflow job for this annotation

GitHub Actions / run-pipeline / automated-tests / automated-tests (22)

tests/component/BillingCodesContainer.test.tsx > BillingCodesContainer > rendering > should show configuration prompt when NLM API key missing

Error: [vitest] No "useGetCPTHCPCSSearch" export is defined on the "../../src/features/visits/shared/stores/appointment/appointment.queries" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside: vi.mock(import("../../src/features/visits/shared/stores/appointment/appointment.queries"), async (importOriginal) => { const actual = await importOriginal() return { ...actual, // your mocked methods } }) ❯ BillingCodesContainer src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx:27:7 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26466:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26434:7

Check failure on line 27 in apps/ehr/src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx

View workflow job for this annotation

GitHub Actions / run-pipeline / automated-tests / automated-tests (22)

tests/component/BillingCodesContainer.test.tsx > BillingCodesContainer > rendering > should display existing CPT codes list

Error: [vitest] No "useGetCPTHCPCSSearch" export is defined on the "../../src/features/visits/shared/stores/appointment/appointment.queries" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside: vi.mock(import("../../src/features/visits/shared/stores/appointment/appointment.queries"), async (importOriginal) => { const actual = await importOriginal() return { ...actual, // your mocked methods } }) ❯ BillingCodesContainer src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx:27:7 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26466:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26434:7

Check failure on line 27 in apps/ehr/src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx

View workflow job for this annotation

GitHub Actions / run-pipeline / automated-tests / automated-tests (22)

tests/component/BillingCodesContainer.test.tsx > BillingCodesContainer > rendering > should display existing E&M code

Error: [vitest] No "useGetCPTHCPCSSearch" export is defined on the "../../src/features/visits/shared/stores/appointment/appointment.queries" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside: vi.mock(import("../../src/features/visits/shared/stores/appointment/appointment.queries"), async (importOriginal) => { const actual = await importOriginal() return { ...actual, // your mocked methods } }) ❯ BillingCodesContainer src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx:27:7 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26466:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26434:7

Check failure on line 27 in apps/ehr/src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx

View workflow job for this annotation

GitHub Actions / run-pipeline / automated-tests / automated-tests (22)

tests/component/BillingCodesContainer.test.tsx > BillingCodesContainer > rendering > should render CPT codes search field

Error: [vitest] No "useGetCPTHCPCSSearch" export is defined on the "../../src/features/visits/shared/stores/appointment/appointment.queries" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside: vi.mock(import("../../src/features/visits/shared/stores/appointment/appointment.queries"), async (importOriginal) => { const actual = await importOriginal() return { ...actual, // your mocked methods } }) ❯ BillingCodesContainer src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx:27:7 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26466:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26434:7

Check failure on line 27 in apps/ehr/src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx

View workflow job for this annotation

GitHub Actions / run-pipeline / automated-tests / automated-tests (22)

tests/component/BillingCodesContainer.test.tsx > BillingCodesContainer > rendering > should render E&M code dropdown

Error: [vitest] No "useGetCPTHCPCSSearch" export is defined on the "../../src/features/visits/shared/stores/appointment/appointment.queries" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside: vi.mock(import("../../src/features/visits/shared/stores/appointment/appointment.queries"), async (importOriginal) => { const actual = await importOriginal() return { ...actual, // your mocked methods } }) ❯ BillingCodesContainer src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx:27:7 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26466:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26434:7

Check failure on line 27 in apps/ehr/src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx

View workflow job for this annotation

GitHub Actions / run-pipeline / automated-tests / automated-tests (22)

tests/component/BillingCodesContainer.test.tsx > BillingCodesContainer > rendering > should render billing title

Error: [vitest] No "useGetCPTHCPCSSearch" export is defined on the "../../src/features/visits/shared/stores/appointment/appointment.queries" mock. Did you forget to return it from "vi.mock"? If you need to partially mock a module, you can use "importOriginal" helper inside: vi.mock(import("../../src/features/visits/shared/stores/appointment/appointment.queries"), async (importOriginal) => { const actual = await importOriginal() return { ...actual, // your mocked methods } }) ❯ BillingCodesContainer src/features/visits/shared/components/assessment-tab/BillingCodesContainer.tsx:27:7 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12 ❯ workLoopSync ../../node_modules/react-dom/cjs/react-dom.development.js:26466:5 ❯ renderRootSync ../../node_modules/react-dom/cjs/react-dom.development.js:26434:7
const cptSearchOptions = data?.codes || [];

const { mutate: saveEMChartData, isPending: isSaveEMLoading } = useSaveChartData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export const useOystehrAPIClient = (): ReturnType<typeof getOystehrTelemedAPI> |
deletePatientInstructionZambdaID: 'delete-patient-instruction',
createUpdateMedicationOrderZambdaID: 'create-update-medication-order',
getMedicationOrdersZambdaID: 'get-medication-orders',
icdSearchZambdaId: 'icd-search',
recommendBillingSuggestionsZambdaID: 'recommend-billing-suggestions',
recommendBillingCodesZambdaID: 'recommend-billing-codes',
isAppLocal: import.meta.env.VITE_APP_IS_LOCAL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import { useApiClients } from 'src/hooks/useAppClients';
import useEvolveUser from 'src/hooks/useEvolveUser';
import {
APIError,
APIErrorCode,
CancelMatchUnsolicitedResultTask,
CPTCodeDTO,
CPTSearchRequestParams,
createSmsModel,
DiagnosisDTO,
filterResources,
Expand All @@ -51,7 +51,6 @@ import {
GetUnsolicitedResultsTasksOutput,
Icd10SearchRequestParams,
Icd10SearchResponse,
IcdSearchRequestParams,
IcdSearchResponse,
InstructionType,
INVENTORY_MEDICATION_TYPE_CODE,
Expand Down Expand Up @@ -512,33 +511,75 @@ export function useFinalizeUnsolicitedResultMatch(): UseMutationResult<void, Err
});
}

export const useGetIcd10Search = ({
export const useGetCPTHCPCSSearch = ({
search,
sabs,
type,
radiologyOnly,
}: IcdSearchRequestParams): UseQueryResult<IcdSearchResponse | undefined, APIError> => {
const apiClient = useOystehrAPIClient();
}: CPTSearchRequestParams): UseQueryResult<IcdSearchResponse | undefined, APIError> => {
const { oystehr } = useApiClients();

const queryResult = useQuery({
queryKey: ['icd-search', search, sabs, radiologyOnly],
queryKey: ['hcpcs-search', search, radiologyOnly],

queryFn: async () => {
return apiClient?.icdSearch({ search, sabs, radiologyOnly });
switch (type) {
case 'cpt': {
const terminologyResponse = await oystehr?.terminology.searchCpt({
query: search,
searchType: 'all',
limit: 100,
});
if (!terminologyResponse) {
throw new Error('could not get terminology results');
}
if (radiologyOnly) {
terminologyResponse.codes = terminologyResponse!.codes.filter((code) => code.code.startsWith('7'));
}
terminologyResponse.codes = terminologyResponse.codes.sort((a, b) => a.code.localeCompare(b.code));
return terminologyResponse;
}
case 'hcpcs': {
const terminologyResponse = await oystehr?.terminology.searchHcpcs({
query: search,
searchType: 'all',
limit: 100,
});
if (!terminologyResponse) {
throw new Error('could not get terminology results');
}
terminologyResponse.codes = terminologyResponse.codes.sort((a, b) => a.code.localeCompare(b.code));
return terminologyResponse;
}
case 'both': {
const [cptResponse, hcpcsResponse] = await Promise.all([
oystehr?.terminology.searchCpt({
query: search,
searchType: 'all',
limit: 100,
}),
oystehr?.terminology.searchHcpcs({
query: search,
searchType: 'all',
limit: 100,
}),
]);
if (!cptResponse || !hcpcsResponse) {
throw new Error('could not get terminology results');
}
let combinedCodes = [...cptResponse.codes, ...hcpcsResponse.codes].filter(
(codeValues, index, self) => index === self.findIndex((t) => t.code === codeValues.code)
);
combinedCodes = combinedCodes.sort((a, b) => a.code.localeCompare(b.code));
return { codes: combinedCodes };
}
}
},

enabled: Boolean(apiClient && search),
enabled: Boolean(oystehr && search),
placeholderData: keepPreviousData,
staleTime: QUERY_STALE_TIME,
});

useEffect(() => {
if (queryResult.error && (queryResult.error as APIError)?.code !== APIErrorCode.MISSING_NLM_API_KEY_ERROR) {
enqueueSnackbar('An error occurred during the search. Please try again in a moment.', {
variant: 'error',
});
}
}, [queryResult.error]);

return queryResult;
};

Expand Down
25 changes: 25 additions & 0 deletions config/oystehr/roles.json
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@
"resource": ["Zambda:Function:*"],
"action": ["Zambda:InvokeFunction"],
"effect": "Allow"
},
{
"resource": ["Terminology:Code:*"],
"action": ["Terminology:SearchCodes"],
"effect": "Allow"
}
]
},
Expand Down Expand Up @@ -332,6 +337,11 @@
"FHIR:Patient",
"FHIR:RelatedPerson"
]
},
{
"resource": ["Terminology:Code:*"],
"action": ["Terminology:SearchCodes"],
"effect": "Allow"
}
]
},
Expand Down Expand Up @@ -443,6 +453,11 @@
"action": ["eRx:SearchMedication"],
"resource": ["eRx:Medication"],
"effect": "Allow"
},
{
"resource": ["Terminology:Code:*"],
"action": ["Terminology:SearchCodes"],
"effect": "Allow"
}
]
},
Expand Down Expand Up @@ -512,6 +527,11 @@
"action": ["FHIR:History"],
"effect": "Allow",
"resource": ["FHIR:Patient", "FHIR:Appointment"]
},
{
"resource": ["Terminology:Code:*"],
"action": ["Terminology:SearchCodes"],
"effect": "Allow"
}
]
},
Expand Down Expand Up @@ -621,6 +641,11 @@
"FHIR:Patient",
"FHIR:RelatedPerson"
]
},
{
"resource": ["Terminology:Code:*"],
"action": ["Terminology:SearchCodes"],
"effect": "Allow"
}
]
},
Expand Down
7 changes: 0 additions & 7 deletions config/oystehr/zambdas.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,6 @@
"src": "src/ehr/sync-user/index",
"zip": ".dist/zips/sync-user.zip"
},
"ICD-SEARCH": {
"name": "icd-search",
"type": "http_auth",
"runtime": "nodejs22.x",
"src": "src/ehr/icd-search/index",
"zip": ".dist/zips/icd-search.zip"
},
"ICD-10-SEARCH": {
"name": "icd-10-search",
"type": "http_auth",
Expand Down
24 changes: 4 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
"@mui/material": "^5.14.18",
"@mui/system": "^5.10.16",
"@mui/x-date-pickers": "^6.18.6",
"@oystehr/sdk": "4.1.8",
"@oystehr/sdk": "4.2.4",
"@pdf-lib/fontkit": "^1.1.1",
"@sendgrid/mail": "^8.1.6",
"@sentry/aws-serverless": "^8.26.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/utils/lib/types/api/icd-search/icd-search.types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Coding } from 'fhir/r4b';

export interface IcdSearchRequestParams {
export interface CPTSearchRequestParams {
search: string;
sabs: 'ICD10CM' | 'CPT';
type: 'cpt' | 'hcpcs' | 'both';
radiologyOnly?: boolean;
}

Expand Down
Loading
Loading