Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 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
33 changes: 21 additions & 12 deletions apps/ehr/src/components/AppointmentTableRow.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { progressNoteIcon, startIntakeIcon } from '@ehrTheme/icons';
import CallSplitIcon from '@mui/icons-material/CallSplit';
import ChatOutlineIcon from '@mui/icons-material/ChatOutlined';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
Expand Down Expand Up @@ -30,6 +31,7 @@ import { enqueueSnackbar } from 'notistack';
import React, { ReactElement, useCallback, useEffect, useMemo, useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { FEATURE_FLAGS } from 'src/constants/feature-flags';
import { getInPersonUrlByAppointmentType } from 'src/features/visits/in-person/routing/helpers';
import { ROUTER_PATH } from 'src/features/visits/in-person/routing/routesInPerson';
import { VitalsIconTooltip } from 'src/features/visits/shared/components/VitalsIconTooltip';
import { TrackingBoardTableButton } from 'src/features/visits/telemed/components/tracking-board/TrackingBoardTableButton';
Expand Down Expand Up @@ -578,7 +580,7 @@ export default function AppointmentTableRow({
},
oystehrZambda
);
navigate(`/in-person/${appointment.id}/patient-info`);
navigate(getInPersonUrlByAppointmentType(appointment, 'patient-info'));
} catch (error) {
console.error(error);
enqueueSnackbar('An error occurred. Please try again.', { variant: 'error' });
Expand Down Expand Up @@ -634,7 +636,7 @@ export default function AppointmentTableRow({
if (isVirtual(appointment)) {
navigate(getTelemedAppointmentUrl(appointment.id));
} else {
navigate(`/in-person/${appointment.id}/${ROUTER_PATH.REVIEW_AND_SIGN}`);
navigate(getInPersonUrlByAppointmentType(appointment, ROUTER_PATH.REVIEW_AND_SIGN));
}
} catch (error) {
console.error(error);
Expand Down Expand Up @@ -898,15 +900,22 @@ export default function AppointmentTableRow({
</TableCell>
<TableCell sx={{ verticalAlign: 'center', wordWrap: 'break-word' }}>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
<Link
to={`/patient/${appointment.patient.id}`}
style={{ textDecoration: 'none' }}
data-testid={dataTestIds.dashboard.patientName}
>
<Typography variant="subtitle2" sx={{ fontSize: '16px', color: '#000' }}>
{patientName}
</Typography>
</Link>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
<Link
to={`/patient/${appointment.patient.id}`}
style={{ textDecoration: 'none' }}
data-testid={dataTestIds.dashboard.patientName}
>
<Typography variant="subtitle2" sx={{ fontSize: '16px', color: '#000' }}>
{patientName}
</Typography>
</Link>
{appointment.isFollowUp && (
<Tooltip title="Follow-up visit">
<CallSplitIcon sx={{ fontSize: 16, color: 'text.secondary', transform: 'rotate(180deg)' }} />
</Tooltip>
)}
</Box>
{appointment.needsDOBConfirmation ? (
<GenericToolTip title="Date of birth for returning patient was not confirmed" customWidth="170px">
<Box sx={{ display: 'flex', gap: 0.75, alignItems: 'center', flexWrap: 'nowrap' }}>
Expand Down Expand Up @@ -1055,7 +1064,7 @@ export default function AppointmentTableRow({
<Stack direction={'row'} spacing={1} alignItems="center">
<GoToButton
text="Visit Details"
onClick={() => navigate(`/visit/${appointment.id}`)}
onClick={() => navigate(getInPersonUrlByAppointmentType(appointment, 'review-and-sign'))}
dataTestId={dataTestIds.dashboard.visitDetailsButton}
>
<MedicalInformationIcon />
Expand Down
3 changes: 2 additions & 1 deletion apps/ehr/src/components/AppointmentTableRowMobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Box, capitalize, Grid, Modal, TableCell, TableRow, Typography } from '@
import { CSSProperties, ReactElement, useState } from 'react';
import { Link } from 'react-router-dom';
import { RecordAudioContainer } from 'src/features/visits/in-person/components/progress-note/RecordAudioContainer';
import { getInPersonUrlByAppointmentType } from 'src/features/visits/in-person/routing/helpers';
import { InPersonAppointmentInformation } from 'utils';
import { MOBILE_MODAL_STYLE } from '../constants';
import { ApptTab } from './AppointmentTabs';
Expand Down Expand Up @@ -50,7 +51,7 @@ export default function AppointmentTableRowMobile({
}}
>
<TableCell colSpan={9}>
<Link to={`/visit/${appointment.id}`} style={linkStyle}>
<Link to={getInPersonUrlByAppointmentType(appointment)} style={linkStyle}>
<Grid container spacing={1}>
<Grid item xs={12} justifyContent="space-between">
<Grid
Expand Down
24 changes: 16 additions & 8 deletions apps/ehr/src/components/PatientEncountersGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { Patient } from 'fhir/r4b';
import { DateTime } from 'luxon';
import React, { FC, ReactElement, useMemo, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { getInPersonUrlByAppointmentType } from 'src/features/visits/in-person/routing/helpers';
import { ROUTER_PATH } from 'src/features/visits/in-person/routing/routesInPerson';
import { getTelemedVisitDetailsUrl } from 'src/features/visits/telemed/utils/routing';
import { getVisitTypeLabelForTypeAndServiceMode } from 'src/shared/utils';
Expand All @@ -38,6 +39,8 @@ import {
BOOKING_CONFIG,
FollowUpVisitHistoryRow,
formatMinutes,
getAnnotationFollowupStatusLabel,
getFollowUpProgressNotePathSegment,
getServiceCategoryAbbreviation,
PatientVisitListResponse,
ServiceMode,
Expand Down Expand Up @@ -255,16 +258,21 @@ export const PatientEncountersGrid: FC<PatientEncountersGridProps> = (props) =>
return encounter.office ? encounter.office : '-';
case 'status': {
if (!encounter.status) return null;
const statusVal = encounter.status === 'in-progress' ? 'OPEN' : 'RESOLVED';
return getFollowupStatusChip(statusVal);
// Scheduled follow-ups use encounter status directly (planned, arrived, etc.)
// Annotation follow-ups use OPEN/RESOLVED
if (encounter.followupSubtype === 'scheduled') {
Comment thread
bxr1nG marked this conversation as resolved.
return <Typography variant="body2">{encounter.status}</Typography>;
}
return getFollowupStatusChip(getAnnotationFollowupStatusLabel(encounter.status));
}
case 'note': {
const { encounterId, originalAppointmentId } = encounter;
if (!originalAppointmentId) return '-';
const to = `/in-person/${originalAppointmentId}/follow-up-note${
encounterId ? `?encounterId=${encounterId}` : ''
}`;

const { encounterId, originalAppointmentId, followupSubtype } = encounter;
const pathSegment = getFollowUpProgressNotePathSegment(followupSubtype, encounter.status);
if (!pathSegment || !originalAppointmentId) return '-';
const to = getInPersonUrlByAppointmentType(
{ id: originalAppointmentId, encounterId, isFollowUp: true },
pathSegment
);
return <RoundedButton to={to}>Progress Note</RoundedButton>;
}
default:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { FC, useMemo } from 'react';
import { useParams } from 'react-router-dom';
import { BaseBreadcrumbs } from 'src/components/BaseBreadcrumbs';
import { useAppointmentData } from 'src/features/visits/shared/stores/appointment/appointment.store';

interface LabBreadcrumbsProps {
sectionName: string;
children: React.ReactNode;
}

export const LabBreadcrumbs: FC<LabBreadcrumbsProps> = ({ sectionName, children }) => {
const { appointment } = useAppointmentData();
const { id: appointmentIdFromUrl } = useParams();

const baseCrumb = useMemo(
() => ({
label: 'External Labs',
path: appointment?.id ? `/in-person/${appointment.id}/external-lab-orders` : null,
path: appointmentIdFromUrl ? `/in-person/${appointmentIdFromUrl}/external-lab-orders` : null,
}),
[appointment?.id]
[appointmentIdFromUrl]
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
import Oystehr from '@oystehr/sdk';
import { enqueueSnackbar } from 'notistack';
import React, { ReactElement, useEffect, useMemo, useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { ActionsList } from 'src/components/ActionsList';
import { DeleteIconButton } from 'src/components/DeleteIconButton';
import DetailPageContainer from 'src/features/common/DetailPageContainer';
Expand Down Expand Up @@ -65,16 +65,11 @@ export const CreateExternalLabOrder: React.FC<CreateExternalLabOrdersProps> = ()
const theme = useTheme();
const { oystehrZambda } = useApiClients();
const navigate = useNavigate();
const { id: appointmentIdFromUrl } = useParams();
const [error, setError] = useState<(string | ReactElement)[] | undefined>(undefined);
const [submitting, setSubmitting] = useState<boolean>(false);
const apiClient = useOystehrAPIClient();
const {
encounter,
appointment,
patient,
location: apptLocation,
followUpOriginEncounter: mainEncounter,
} = useAppointmentData();
const { encounter, patient, location: apptLocation, followUpOriginEncounter: mainEncounter } = useAppointmentData();
const { chartData, setPartialChartData } = useChartData();
const { mutate: saveCPTChartData } = useSaveChartData();
const { visitType } = useGetAppointmentAccessibility();
Expand Down Expand Up @@ -212,7 +207,7 @@ export const CreateExternalLabOrder: React.FC<CreateExternalLabOrdersProps> = ()
selectedPaymentMethod: selectedPaymentMethod,
clinicalInfoNoteByUser: clinicalInfoNotes,
});
navigate(`/in-person/${appointment?.id}/external-lab-orders`);
navigate(`/in-person/${appointmentIdFromUrl}/external-lab-orders`);
} catch (e) {
const sdkError = e as Oystehr.OystehrSdkError;
console.log('error creating external lab order', sdkError.code, sdkError.message);
Expand All @@ -221,7 +216,7 @@ export const CreateExternalLabOrder: React.FC<CreateExternalLabOrdersProps> = ()
setError([
<>
Information necessary to submit labs is missing. Please navigate to{' '}
<Link to={`/visit/${appointment?.id}`}>visit details</Link> and complete all Worker's Compensation
<Link to={`/visit/${appointmentIdFromUrl}`}>visit details</Link> and complete all Worker's Compensation
Information.
</>,
]);
Expand Down Expand Up @@ -611,7 +606,7 @@ export const CreateExternalLabOrder: React.FC<CreateExternalLabOrdersProps> = ()
variant="outlined"
sx={{ borderRadius: '50px', textTransform: 'none', fontWeight: 600 }}
onClick={() => {
navigate(`/in-person/${appointment?.id}/external-lab-orders`);
navigate(`/in-person/${appointmentIdFromUrl}/external-lab-orders`);
}}
>
Cancel
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { useMemo } from 'react';
import { useParams } from 'react-router-dom';
import { BaseBreadcrumbs } from 'src/components/BaseBreadcrumbs';
import { getInHouseLabsUrl } from 'src/features/visits/in-person/routing/helpers';
import { useAppointmentData } from 'src/features/visits/shared/stores/appointment/appointment.store';

export const InHouseLabsBreadcrumbs: React.FC<{ children: React.ReactNode; pageName: string }> = ({
children,
pageName,
}) => {
const { appointment } = useAppointmentData();
const appointmentId = appointment?.id;
const { id: appointmentIdFromUrl } = useParams();

const baseCrumb = useMemo(() => {
return {
label: 'In-House Labs',
path: appointmentId ? getInHouseLabsUrl(appointmentId) : null,
path: appointmentIdFromUrl ? getInHouseLabsUrl(appointmentIdFromUrl) : null,
};
}, [appointmentId]);
}, [appointmentIdFromUrl]);

return (
<BaseBreadcrumbs sectionName={pageName} baseCrumb={baseCrumb}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
import Oystehr from '@oystehr/sdk';
import { enqueueSnackbar } from 'notistack';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { useLocation, useNavigate, useParams } from 'react-router-dom';
import { ActionsList } from 'src/components/ActionsList';
import { DeleteIconButton } from 'src/components/DeleteIconButton';
import { dataTestIds } from 'src/constants/data-test-ids';
Expand Down Expand Up @@ -59,6 +59,7 @@ export const InHouseLabOrderCreatePage: React.FC = () => {
const theme = useTheme();
const { oystehrZambda } = useApiClients();
const navigate = useNavigate();
const { id: appointmentIdFromUrl } = useParams();
const location = useLocation();
const [loading, setLoading] = useState(false);
const [selectedTests, setSelectedTests] = useState<DataEntryTestItem[]>([]);
Expand All @@ -73,7 +74,7 @@ export const InHouseLabOrderCreatePage: React.FC = () => {
type?: 'repeat' | 'reflex';
};

const { encounter, appointment } = useAppointmentData();
const { encounter } = useAppointmentData();
const { chartData, setPartialChartData } = useChartData();
const didPrimaryDiagnosisInit = useRef(false);
const didPrefillInit = useRef(false);
Expand Down Expand Up @@ -220,9 +221,9 @@ export const InHouseLabOrderCreatePage: React.FC = () => {

if (res.serviceRequestIds.length === 1) {
// we will only nav forward if one test was created, else we will direct the user back to the table
navigate(`/in-person/${appointment?.id}/in-house-lab-orders/${res.serviceRequestIds[0]}/order-details`);
navigate(`/in-person/${appointmentIdFromUrl}/in-house-lab-orders/${res.serviceRequestIds[0]}/order-details`);
} else {
navigate(`/in-person/${appointment?.id}/in-house-lab-orders`);
navigate(`/in-person/${appointmentIdFromUrl}/in-house-lab-orders`);
}
} catch (e) {
const sdkError = e as Oystehr.OystehrSdkError;
Expand Down
7 changes: 4 additions & 3 deletions apps/ehr/src/features/in-house-labs/pages/InHouseLabsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Box, Stack } from '@mui/material';
import React, { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { useNavigate, useParams } from 'react-router-dom';
import ListViewContainer from 'src/features/common/ListViewContainer';
import { getInHouseLabOrderCreateUrl } from 'src/features/visits/in-person/routing/helpers';
import { useGetAppointmentAccessibility } from 'src/features/visits/shared/hooks/useGetAppointmentAccessibility';
Expand All @@ -14,8 +14,9 @@ const inHouseLabsColumns: InHouseLabsTableColumn[] = ['testType', 'orderAdded',

export const InHouseLabsPage: React.FC = () => {
const navigate = useNavigate();
const { appointment, encounter } = useAppointmentData();
const appointmentId = appointment?.id;
const { id: appointmentIdFromUrl } = useParams();
const { encounter } = useAppointmentData();
const appointmentId = appointmentIdFromUrl;
const encounterId = encounter?.id;
const { isAppointmentReadOnly: isReadOnly } = useGetAppointmentAccessibility();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { FC } from 'react';
import { useParams } from 'react-router-dom';
import CustomBreadcrumbs from 'src/components/CustomBreadcrumbs';
import { useAppointmentData } from 'src/features/visits/shared/stores/appointment/appointment.store';

export const BreadCrumbs: FC = () => {
const { appointment } = useAppointmentData();
const { id: appointmentIdFromUrl } = useParams();

return (
<CustomBreadcrumbs
chain={[
{ link: `/in-person/${appointment?.id}/nursing-orders`, children: 'Orders' },
{ link: `/in-person/${appointmentIdFromUrl}/nursing-orders`, children: 'Orders' },
{ link: '#', children: 'Nursing Order' },
]}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Box, Stack } from '@mui/material';
import React, { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { useNavigate, useParams } from 'react-router-dom';
import { dataTestIds } from 'src/constants/data-test-ids';
import { getNursingOrderCreateUrl } from 'src/features/visits/in-person/routing/helpers';
import { useGetAppointmentAccessibility } from 'src/features/visits/shared/hooks/useGetAppointmentAccessibility';
Expand All @@ -13,8 +13,9 @@ const nursingOrdersColumns: NursingOrdersTableColumn[] = ['order', 'orderAdded',

export const NursingOrdersPage: React.FC = () => {
const navigate = useNavigate();
const { appointment, encounter } = useAppointmentData();
const appointmentId = appointment?.id;
const { id: appointmentIdFromUrl } = useParams();
const { encounter } = useAppointmentData();
const appointmentId = appointmentIdFromUrl;
const encounterId = encounter?.id;
const { isAppointmentReadOnly: isReadOnly } = useGetAppointmentAccessibility();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Box, Link as MuiLink, Typography } from '@mui/material';
import { styled } from '@mui/material/styles';
import { FC } from 'react';
import { Link } from 'react-router-dom';
import { Link, useParams } from 'react-router-dom';
import { getRadiologyUrl } from 'src/features/visits/in-person/routing/helpers';
import { useAppointmentData } from 'src/features/visits/shared/stores/appointment/appointment.store';

interface RadiologyBreadcrumbsProps {
sectionName: string;
Expand Down Expand Up @@ -35,13 +34,13 @@ export const WithRadiologyBreadcrumbs: FC<RadiologyBreadcrumbsProps> = ({
disableLabsLink = false,
children,
}) => {
const { appointment } = useAppointmentData();
const { id: appointmentIdFromUrl } = useParams();

return (
<PageWrapper>
<BreadcrumbsContainer>
{!disableLabsLink && appointment?.id ? (
<MuiLink component={Link} to={getRadiologyUrl(appointment.id)} color="text.primary">
{!disableLabsLink && appointmentIdFromUrl ? (
<MuiLink component={Link} to={getRadiologyUrl(appointmentIdFromUrl)} color="text.primary">
Radiology
</MuiLink>
) : (
Expand Down
Loading
Loading