diff --git a/apps/ehr/src/constants/data-test-ids.ts b/apps/ehr/src/constants/data-test-ids.ts index 8cd7842045..3a90c12ec5 100644 --- a/apps/ehr/src/constants/data-test-ids.ts +++ b/apps/ehr/src/constants/data-test-ids.ts @@ -468,6 +468,8 @@ export const dataTestIds = { procedureType: 'procedure-type', cptCodeInput: 'cpt-code-input', cptCode: 'cpt-code', + recommendedCptCode: (code: string) => `recommended-cpt-code-${code}`, + cptCodeQuickAddButton: (code: string) => `cpt-code-quick-add-${code}`, diagnosis: 'diagnosis', diagnosisItem: 'diagnosis-item', diagnosisDeleteButton: 'diagnosis-delete-button', diff --git a/apps/ehr/src/features/visits/in-person/components/AiSuggestion.tsx b/apps/ehr/src/features/visits/in-person/components/AiSuggestion.tsx index 8b3e1c674b..c5d5e9d825 100644 --- a/apps/ehr/src/features/visits/in-person/components/AiSuggestion.tsx +++ b/apps/ehr/src/features/visits/in-person/components/AiSuggestion.tsx @@ -1,4 +1,4 @@ -import { AddCircleOutline, CheckCircle, InfoOutlined } from '@mui/icons-material'; +import { AddCircleOutline, CheckCircle } from '@mui/icons-material'; import { Box, Checkbox, @@ -32,7 +32,6 @@ import { MedicalConditionDTO, MedicationDTO, ObservationTextFieldDTO, - ProcedureSuggestion, } from 'utils'; interface SearchResult { @@ -290,7 +289,6 @@ export interface AiSuggestionProps { title: string; chartData?: GetChartDataResponse | undefined; content?: ObservationTextFieldDTO[]; - procedureSuggestions?: ProcedureSuggestion[]; loading?: boolean; hideHeader?: boolean; onAppendToNote?: (text: string, resourceId?: string) => void; @@ -301,7 +299,6 @@ export default function AiSuggestion({ title, chartData, content, - procedureSuggestions, loading, hideHeader, onAppendToNote, @@ -505,24 +502,6 @@ export default function AiSuggestion({ } function SuggestionsItem(): React.ReactElement { - if (procedureSuggestions) { - return ( - <> - {procedureSuggestions.map((code) => ( - <> - - {code.code} – {code.description} - - - - - - - - ))} - - ); - } return ( <> {content diff --git a/apps/ehr/src/features/visits/in-person/pages/ProceduresNew.tsx b/apps/ehr/src/features/visits/in-person/pages/ProceduresNew.tsx index d89096c731..8875d2f0b4 100644 --- a/apps/ehr/src/features/visits/in-person/pages/ProceduresNew.tsx +++ b/apps/ehr/src/features/visits/in-person/pages/ProceduresNew.tsx @@ -1,3 +1,4 @@ +import { AddCircleOutline, CheckCircle, InfoOutlined } from '@mui/icons-material'; import { Autocomplete, Backdrop, @@ -14,12 +15,14 @@ import { FormControlLabel, FormHelperText, FormLabel, + IconButton, InputLabel, MenuItem, Radio, RadioGroup, Select, TextField, + Tooltip, Typography, } from '@mui/material'; import { Box, Stack, useTheme } from '@mui/system'; @@ -30,7 +33,7 @@ import { keepPreviousData, useQuery, useQueryClient, UseQueryResult } from '@tan import { ValueSet } from 'fhir/r4b'; import { DateTime } from 'luxon'; import { enqueueSnackbar } from 'notistack'; -import { ReactElement, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { ReactElement, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { Link, useNavigate, useParams } from 'react-router-dom'; import { createProcedureQuickPick, getProcedureQuickPicks, updateProcedureQuickPick } from 'src/api/api'; @@ -70,6 +73,7 @@ import { TECHNIQUES_VALUE_SET_URL, TIME_SPENT_VALUE_SET_URL, } from 'utils'; +import { AiSectionContainer } from '../../shared/components/AiSection'; import { DiagnosesField } from '../../shared/components/assessment-tab/DiagnosesField'; import { PageTitle } from '../../shared/components/PageTitle'; import { QuickPicksButton } from '../../shared/components/QuickPicksButton'; @@ -80,7 +84,6 @@ import { useRecommendBillingCodes, } from '../../shared/stores/appointment/appointment.queries'; import { useChartData, useDeleteChartData, useSaveChartData } from '../../shared/stores/appointment/appointment.store'; -import AiSuggestion from '../components/AiSuggestion'; import { InfoAlert } from '../components/InfoAlert'; import { ROUTER_PATH } from '../routing/routesInPerson'; import { @@ -553,6 +556,74 @@ export default function ProceduresNew(): ReactElement { }); }; + const existingCptCodeSet = useMemo(() => new Set(state.cptCodes?.map((cptCode) => cptCode.code)), [state.cptCodes]); + + const addRecommendedCptCode = (suggestion: ProcedureSuggestion): void => + updateState((state) => { + if (!state.cptCodes?.some((cptCode) => cptCode.code === suggestion.code)) { + state.cptCodes = [...(state.cptCodes ?? []), { code: suggestion.code, display: suggestion.description }]; + } + }); + + const renderRecommendedCptActions = (value: ProcedureSuggestion): ReactElement => ( + + + + + + + {existingCptCodeSet.has(value.code) ? ( + + + + ) : ( + + addRecommendedCptCode(value)} + data-testid={dataTestIds.documentProcedurePage.cptCodeQuickAddButton(value.code)} + > + + + + )} + + ); + + const recommendedCptCodesContent = (): ReactNode => { + if (loadingSuggestions) { + return null; + } + + if (!formValues.procedureType) { + return Select a procedure type to see recommended CPT codes; + } + + // Suggestions not fetched yet. + if (!recommendedBillingCodes) { + return null; + } + + if (recommendedBillingCodes.length === 0) { + return No suggestions; + } + + return ( + value.code} + renderItem={(value) => ( + + {value.code} – {value.description} + + )} + renderActions={isReadOnly ? undefined : renderRecommendedCptActions} + divider + /> + ); + }; + const cptWidget = (): ReactElement => { return ( <> @@ -1127,13 +1198,7 @@ export default function ProceduresNew(): ReactElement { CPT Code - {recommendedBillingCodes && ( - - )} + {recommendedCptCodesContent()} {suggestionNote && suggestionNote.suggestions?.[0] !== 'Procedure details are included' && (