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

Release Ottehr Psel v0.16 #579

Merged
merged 24 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
29b2c33
add has patients element
AykhanAhmadli Nov 4, 2024
6a26f6c
added prescriber policy
rzinger Nov 5, 2024
8f8aff3
add default values to newly created practitioner
rzinger Nov 5, 2024
a1c1aca
issue #509
GiladSchneider Nov 5, 2024
99c4056
issue #544
GiladSchneider Nov 6, 2024
8e01f92
wip: fix provider details form
AykhanAhmadli Nov 6, 2024
427ea4d
Merge pull request #557 from masslight/erx-513
rzinger Nov 6, 2024
73f0def
resolve form submission logic
AykhanAhmadli Nov 7, 2024
0eb2184
revert debug changes
AykhanAhmadli Nov 7, 2024
1ab7b1b
fix for videochat page
AykhanAhmadli Nov 7, 2024
0ceb60a
change error text
AykhanAhmadli Nov 7, 2024
206cedf
revert debugging changes
AykhanAhmadli Nov 8, 2024
588fc3a
Merge pull request #555 from masslight/fix-portal-zero
AykhanAhmadli Nov 8, 2024
d1eda18
Merge pull request #563 from masslight/fix-form-field
AykhanAhmadli Nov 8, 2024
3754c44
Merge pull request #565 from masslight/videochat-page
AykhanAhmadli Nov 8, 2024
4618a3c
reformatted to use useQuery
GiladSchneider Nov 11, 2024
0607fad
Merge pull request #556 from masslight/509/fix-cancellation-issues
GiladSchneider Nov 11, 2024
0b0d612
fixes issues with cancel button
GiladSchneider Nov 11, 2024
42ad0aa
removes console logs
GiladSchneider Nov 11, 2024
4fc2a67
Merge pull request #571 from masslight/544/cancel-button-fixes
GiladSchneider Nov 11, 2024
7687b9e
Revert "Videochat page updates"
GiladSchneider Nov 11, 2024
05fcc44
Merge pull request #573 from masslight/revert-565-videochat-page
GiladSchneider Nov 11, 2024
f8d7c2d
bumps version to 0.16
GiladSchneider Nov 11, 2024
ba7b129
Merge pull request #574 from masslight/0.16-version-bump
GiladSchneider Nov 11, 2024
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ottehr",
"version": "0.15.0",
"version": "0.16.0",
"private": true,
"scripts": {
"test": "pnpm recursive run test",
Expand Down
1 change: 1 addition & 0 deletions packages/ehr-utils/lib/types/user.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export enum RoleType {
Manager = 'Manager',
Staff = 'Staff',
Provider = 'Provider',
Prescriber = 'Prescriber',
FrontDesk = 'Front Desk',
Inactive = 'Inactive',
}
2 changes: 1 addition & 1 deletion packages/ehr-utils/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ehr-utils",
"private": true,
"version": "0.15.0",
"version": "0.16.0",
"main": "lib/main.ts",
"types": "lib/main.ts",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/ottehr-components/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ottehr-components",
"private": true,
"version": "0.15.0",
"version": "0.16.0",
"main": "lib/main.ts",
"types": "lib/main.ts",
"scripts": {
Expand Down
4 changes: 2 additions & 2 deletions packages/telemed-ehr/app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "telemed-ehr-app",
"version": "0.15.0",
"version": "0.16.0",
"private": true,
"browserslist": {
"production": [
Expand Down Expand Up @@ -37,7 +37,7 @@
"@mui/x-data-grid-pro": "^6.3.0",
"@mui/x-date-pickers": "^5.0.20",
"@mui/x-date-pickers-pro": "^5.0.20",
"@photonhealth/elements": "^0.12.7",
"@photonhealth/elements": "^0.13.0",
"@twilio/conversations": "^2.4.1",
"@zapehr/sdk": "1.0.15",
"amazon-chime-sdk-component-library-react": "^3.7.0",
Expand Down
11 changes: 9 additions & 2 deletions packages/telemed-ehr/app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,14 @@ function App(): ReactElement {
const wasEnrolledInERX = useProviderERXStateStore((state) => state.wasEnrolledInERX);

const roleUnknown =
!currentUser || !currentUser.hasRole([RoleType.Administrator, RoleType.Staff, RoleType.Manager, RoleType.Provider]);
!currentUser ||
!currentUser.hasRole([
RoleType.Administrator,
RoleType.Staff,
RoleType.Manager,
RoleType.Provider,
RoleType.Prescriber,
]);

return (
<CustomThemeProvider>
Expand All @@ -73,7 +80,7 @@ function App(): ReactElement {
showWhenAuthenticated={
<>
{isERXEnabled &&
((currentUser?.hasRole([RoleType.Provider]) && currentUser.isPractitionerEnrolledInERX) ||
((currentUser?.hasRole([RoleType.Prescriber]) && currentUser.isPractitionerEnrolledInERX) ||
wasEnrolledInERX) ? (
<photon-client
id={import.meta.env.VITE_APP_PHOTON_CLIENT_ID}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Box } from '@mui/material';
import { ReactElement } from 'react';
import { UCAppointmentInformation } from 'ehr-utils';
import { classifyAppointments } from '../helpers';
import { getAppointmentStatusChip } from './AppointmentTableRow';
import { getInPersonAppointmentStatusChip } from './AppointmentTableRow';

export interface AppointmentChip {
appointments: UCAppointmentInformation[];
Expand Down Expand Up @@ -33,7 +33,7 @@ export const AppointmentsStatusChipsCount = ({ appointments }: AppointmentChip):
ORDER_STATUS.indexOf(statusOne) - ORDER_STATUS.indexOf(statusTwo),
)
.map(([status, count]) => (
<Box key={status}>{getAppointmentStatusChip(status, count)}</Box>
<Box key={status}>{getInPersonAppointmentStatusChip(status, count)}</Box>
))}
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import { Operation } from 'fast-json-patch';
import { getPatchBinary, getStatusFromExtension } from 'ehr-utils';
import { VisitStatus, STATI } from '../helpers/mappingUtils';
import { useApiClients } from '../hooks/useAppClients';
import { getAppointmentStatusChip } from './AppointmentTableRow';
import { Box } from '@mui/system';
import { getInPersonAppointmentStatusChip } from './AppointmentTableRow';

const statuses = STATI;

Expand All @@ -17,6 +16,7 @@ export const switchStatus = async (
appointment: Appointment,
encounter: Encounter,
status: VisitStatus,
onStatusChange: (status: VisitStatus) => void,
): Promise<void> => {
if (status === 'unknown') {
throw new Error(`Invalid status: ${status}`);
Expand Down Expand Up @@ -52,16 +52,20 @@ export const switchStatus = async (
}),
],
});

onStatusChange(status);
};

interface AppointmentStatusSwitcherProps {
appointment: Appointment;
encounter: Encounter;
onStatusChange: (status: VisitStatus) => void;
}

export default function AppointmentStatusSwitcher({
appointment,
encounter,
onStatusChange,
}: AppointmentStatusSwitcherProps): ReactElement {
const { fhirClient } = useApiClients();
const [statusLoading, setStatusLoading] = React.useState<boolean>(false);
Expand All @@ -70,7 +74,7 @@ export default function AppointmentStatusSwitcher({
const handleChange = async (event: SelectChangeEvent): Promise<void> => {
const value = event.target.value;
setStatusLoading(true);
await switchStatus(fhirClient, currentAppointment, encounter, value as VisitStatus);
await switchStatus(fhirClient, currentAppointment, encounter, value as VisitStatus, onStatusChange);
const newAppointment = (await fhirClient?.readResource({
resourceType: 'Appointment',
resourceId: appointment.id || '',
Expand Down Expand Up @@ -100,7 +104,7 @@ export default function AppointmentStatusSwitcher({
labelId="status-select-label"
value={getStatusFromExtension(currentAppointment)}
onChange={async (event) => await handleChange(event)}
renderValue={(selected) => getAppointmentStatusChip(selected)}
renderValue={(selected) => getInPersonAppointmentStatusChip(selected)}
sx={{
boxShadow: 'none',
'.MuiOutlinedInput-notchedOutline': { border: 0 },
Expand All @@ -113,10 +117,10 @@ export default function AppointmentStatusSwitcher({
}}
>
{statuses
.filter((status) => status !== 'unknown')
.filter((status) => status !== 'unknown' && status !== 'cancelled')
.map((status) => (
<MenuItem key={status} value={status}>
{getAppointmentStatusChip(status)}
{getInPersonAppointmentStatusChip(status)}
</MenuItem>
))}
</Select>
Expand Down
10 changes: 5 additions & 5 deletions packages/telemed-ehr/app/src/components/AppointmentTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const FLAGGED_REASONS_FOR_VISIT: string[] = [
'Allergic reaction',
];

export function getAppointmentStatusChip(status: string, count?: number): ReactElement {
export function getInPersonAppointmentStatusChip(status: string, count?: number): ReactElement {
if (!status) {
return <span>todo1</span>;
}
Expand Down Expand Up @@ -444,17 +444,17 @@ export default function AppointmentTableRow({
}}
>
{isLongWaitingTime && longWaitFlag}
{getStatiForVisitTimeCalculation(appointment.visitStatusHistory, appointment.start).map((statusTemp) => {
{getStatiForVisitTimeCalculation(appointment.visitStatusHistory, appointment.start).map((statusTemp, index) => {
return (
<Box sx={{ display: 'flex', gap: 1 }}>
<Box key={index} sx={{ display: 'flex', gap: 1 }}>
<Typography
variant="body2"
color={theme.palette.getContrastText(theme.palette.background.default)}
style={{ display: 'inline', fontWeight: 700, marginTop: 1 }}
>
{formatMinutes(getDurationOfStatus(statusTemp, appointment, appointment.visitStatusHistory, now))} mins
</Typography>
{getAppointmentStatusChip(statusTemp.label as keyof typeof CHIP_STATUS_MAP)}
{getInPersonAppointmentStatusChip(statusTemp.label as keyof typeof CHIP_STATUS_MAP)}
</Box>
);
})}
Expand Down Expand Up @@ -529,7 +529,7 @@ export default function AppointmentTableRow({
&nbsp;&nbsp;<strong>{start}</strong>
</Typography>
</Box>
<Box mt={1}>{getAppointmentStatusChip(appointment.status)}</Box>
<Box mt={1}>{getInPersonAppointmentStatusChip(appointment.status)}</Box>
</Link>
</Box>
</TableCell>
Expand Down
121 changes: 64 additions & 57 deletions packages/telemed-ehr/app/src/components/EmployeeInformationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ const AVAILABLE_ROLES: {
{
value: RoleType.Provider,
label: 'Provider',
hint: `No settings changes; essentially read-only`,
hint: `A clinician, such as a doctor, a PA or an NP`,
},
{
value: RoleType.Prescriber,
label: 'Prescriber',
hint: `A clinician that is allowed to prescribe`,
},
];

Expand All @@ -93,12 +98,12 @@ if (import.meta.env.MODE === 'default' || import.meta.env.MODE === 'development'
},
{
value: RoleType.RegionalTelemedLead,
label: 'Regional Telemed lead',
label: 'Regional Telemed Lead',
hint: 'Todo description',
},
{
value: RoleType.CallCentre,
label: 'Call Centre',
label: 'Call Center',
hint: 'Todo description',
},
{
Expand Down Expand Up @@ -494,61 +499,63 @@ export default function EmployeeInformationForm({
Add New State Qualification
</AccordionSummary>
<AccordionDetails>
<Grid container direction={'row'} spacing={1}>
<Grid item xs={4}>
<Autocomplete
options={displaystates}
getOptionLabel={(option: string) => option}
renderInput={(params) => (
<TextField
{...params}
label="State"
error={errors.state}
required
helperText={errors.state ? 'Please select a state' : null}
/>
)}
value={newLicenseState || null}
onChange={(event, value) => setNewLicenseState(value || undefined)}
/>
</Grid>
<Grid item xs={4}>
<Autocomplete
options={Object.keys(PractitionerQualificationCodesLabels)}
getOptionLabel={(option: string) => option}
renderInput={(params) => (
<TextField
{...params}
label="Qualification"
error={errors.qualification}
required
helperText={errors.qualification ? 'Please select a qualification' : null}
/>
)}
value={newLicenseCode || null}
onChange={(event, value) => setNewLicenseCode(value || undefined)}
/>
</Grid>
<Grid item xs={4} alignContent={'center'}>
<Button
variant="contained"
endIcon={<AddIcon />}
sx={{ textTransform: 'none', fontWeight: 'bold', borderRadius: 28 }}
onClick={handleAddLicense}
fullWidth
>
Add
</Button>
<form>
<Grid container direction={'row'} spacing={1}>
<Grid item xs={4}>
<Autocomplete
options={displaystates}
getOptionLabel={(option: string) => option}
renderInput={(params) => (
<TextField
{...params}
label="State"
error={errors.state}
required
helperText={errors.state ? 'Please select a state' : null}
/>
)}
value={newLicenseState || null}
onChange={(event, value) => setNewLicenseState(value || undefined)}
/>
</Grid>
<Grid item xs={4}>
<Autocomplete
options={Object.keys(PractitionerQualificationCodesLabels)}
getOptionLabel={(option: string) => option}
renderInput={(params) => (
<TextField
{...params}
label="Qualification"
error={errors.qualification}
required
helperText={errors.qualification ? 'Please select a qualification' : null}
/>
)}
value={newLicenseCode || null}
onChange={(event, value) => setNewLicenseCode(value || undefined)}
/>
</Grid>
<Grid item xs={4} alignContent={'center'}>
<Button
variant="contained"
endIcon={<AddIcon />}
sx={{ textTransform: 'none', fontWeight: 'bold', borderRadius: 28 }}
fullWidth
onClick={handleAddLicense}
>
Add
</Button>
</Grid>
{errors.duplicateLicense && (
<Typography
color="error"
variant="body2"
mt={1}
mx={1}
>{`License already exists.`}</Typography>
)}
</Grid>
{errors.duplicateLicense && (
<Typography
color="error"
variant="body2"
mt={1}
mx={1}
>{`License already exists.`}</Typography>
)}
</Grid>
</form>
</AccordionDetails>
</Accordion>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { telemedCancellationReasons, inPersonCancellationReasons } from '../../t

interface CancelVisitDialogProps {
onClose: () => void;
appointmentType: 'telemed' | 'in-person';
appointmentType: 'telemedicine' | 'in-person';
}

const CancelVisitDialog = ({ onClose, appointmentType }: CancelVisitDialogProps): ReactElement => {
Expand All @@ -33,7 +33,8 @@ const CancelVisitDialog = ({ onClose, appointmentType }: CancelVisitDialogProps)
const { id: appointmentID } = useParams();
const navigate = useNavigate();

const cancellationReasons = appointmentType === 'telemed' ? telemedCancellationReasons : inPersonCancellationReasons;
const cancellationReasons =
appointmentType === 'telemedicine' ? telemedCancellationReasons : inPersonCancellationReasons;

const handleReasonChange = (event: SelectChangeEvent<string>): void => {
setReason(event.target.value);
Expand All @@ -56,7 +57,7 @@ const CancelVisitDialog = ({ onClose, appointmentType }: CancelVisitDialogProps)
if (!zambdaIntakeClient) throw new Error('Zambda client not found');
try {
let response;
if (appointmentType === 'telemed') {
if (appointmentType === 'telemedicine') {
console.log('canceling telemed appointment', appointmentID, reason, otherReason);
response = await cancelTelemedAppointment(zambdaIntakeClient, {
appointmentID: appointmentID || '',
Expand All @@ -76,7 +77,7 @@ const CancelVisitDialog = ({ onClose, appointmentType }: CancelVisitDialogProps)
console.error('Failed to cancel appointment', error);
} finally {
setIsCancelling(false);
if (appointmentType === 'telemed') {
if (appointmentType === 'telemedicine') {
navigate('/telemed/appointments');
} else if (appointmentType === 'in-person') {
navigate('/in-person/appointments');
Expand Down
Loading
Loading