Skip to content

Commit

Permalink
Merge pull request #596 from masslight/release/quequechan
Browse files Browse the repository at this point in the history
Release quequechan
  • Loading branch information
GiladSchneider authored Nov 18, 2024
2 parents a41892e + 5be561f commit 43d46cb
Show file tree
Hide file tree
Showing 30 changed files with 124 additions and 66 deletions.
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.16.0",
"version": "0.17.0",
"private": true,
"scripts": {
"test": "pnpm recursive run test",
Expand Down
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.16.0",
"version": "0.17.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.16.0",
"version": "0.17.0",
"main": "lib/main.ts",
"types": "lib/main.ts",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion 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.16.0",
"version": "0.17.0",
"private": true,
"browserslist": {
"production": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default function ProvidersSelect({ providers, practitioners, handleSubmit
practitionerIDToName[practitioner.id] = formatHumanName(practitioner.name[0]);
}
});

return (
<Autocomplete
id="providers"
Expand Down
49 changes: 40 additions & 9 deletions packages/telemed-ehr/app/src/helpers/create-sample-appointments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { DateTime } from 'luxon';
import { FhirClient, SearchParam } from '@zapehr/sdk';
import { PersonSex } from '../../../app/src/types/types';
import { Patient, Practitioner } from 'fhir/r4';
import { getSelectors } from '../shared/store/getSelectors';
import { useTrackingBoardStore } from '../telemed';
import { allLicensesForPractitioner, User } from 'ehr-utils';
import useOttehrUser from '../hooks/useOttehrUser';

type UserType = 'Patient' | 'Parent/Guardian';

Expand Down Expand Up @@ -43,6 +47,7 @@ export const createSampleAppointments = async (
fhirClient: FhirClient | undefined,
authToken: string,
phoneNumber: string,
user: User | undefined,
): Promise<void> => {
try {
if (!fhirClient) {
Expand All @@ -58,7 +63,7 @@ export const createSampleAppointments = async (

for (let i = 0; i < 10; i++) {
const visitService = appointmentTypes[i % 2];
const randomPatientInfo = await generateRandomPatientInfo(fhirClient, visitService, phoneNumber);
const randomPatientInfo = await generateRandomPatientInfo(fhirClient, visitService, user, phoneNumber);
const inputBody = JSON.stringify(randomPatientInfo);

const response = await fetch(`${intakeZambdaUrl}/zambda/${createAppointmentZambdaId}/execute`, {
Expand All @@ -83,18 +88,22 @@ export const createSampleAppointments = async (
const generateRandomPatientInfo = async (
fhirClient: FhirClient,
visitService: 'in-person' | 'telemedicine',
user: User | undefined,
phoneNumber?: string,
): Promise<CreateAppointmentParams> => {
const firstNames = ['Alice', 'Bob', 'Charlie', 'Diana', 'Ethan', 'Fatima', 'Gabriel', 'Hannah', 'Ibrahim', 'Jake'];
const lastNames = ['Smith', 'Johnson', 'Williams', 'Jones', 'Brown', 'Clark', 'Davis', 'Elliott', 'Foster', 'Garcia'];
const sexes: PersonSex[] = [PersonSex.Male, PersonSex.Female, PersonSex.Intersex];

const searchParams: SearchParam[] = [{ name: 'status', value: 'active' }];
const availableLocations: any[] = await fhirClient?.searchResources({

const allOffices: any[] = await fhirClient?.searchResources({
resourceType: 'Location',
searchParams: searchParams,
searchParams: [{ name: '_count', value: '1000' }],
});

const activeOffices = allOffices.filter((item) => item.status === 'active');

const practitionersTemp: Practitioner[] = await fhirClient.searchResources({
resourceType: 'Practitioner',
searchParams: [
Expand All @@ -110,11 +119,26 @@ const generateRandomPatientInfo = async (
.minus({ years: 7 + Math.floor(Math.random() * 16) })
.toISODate();
const randomSex = sexes[Math.floor(Math.random() * sexes.length)];
const randomLocationIndex = Math.floor(Math.random() * availableLocations.length);
const randomLocationId = availableLocations[randomLocationIndex].id;
const randomLocationIndex = Math.floor(Math.random() * activeOffices.length);
const randomLocationId = activeOffices[randomLocationIndex].id;
const randomProviderId = practitionersTemp[Math.floor(Math.random() * practitionersTemp.length)].id;

const selectedLocationID = localStorage.getItem('selectedLocationID');
const selectedInPersonLocationID = localStorage.getItem('selectedLocationID');
const selectedState = localStorage.getItem('selectedState');

const availableStates =
user?.profileResource &&
allLicensesForPractitioner(user.profileResource).map((item) => {
return item.state;
});

const randomState = availableStates?.[Math.floor(Math.random() * availableStates.length)] || '';

const locationId = getLocationIdFromState(selectedState || randomState, allOffices);

const isLocationActive = activeOffices.some((office) => office.id === locationId);

const telemedLocationId = isLocationActive ? locationId : randomLocationId;

if (visitService === 'telemedicine') {
return {
Expand All @@ -126,15 +150,16 @@ const generateRandomPatientInfo = async (
sex: randomSex,
email: randomEmail,
emailUser: 'Patient',
phoneNumber: phoneNumber,
},
scheduleType: 'provider',
scheduleType: 'location',
visitType: 'now',
visitService: visitService,
providerID: randomProviderId,
timezone: 'UTC',
isDemo: true,
phoneNumber: phoneNumber,
locationID: randomLocationId,
locationID: telemedLocationId,
};
}

Expand All @@ -147,6 +172,7 @@ const generateRandomPatientInfo = async (
sex: randomSex,
email: randomEmail,
emailUser: 'Patient',
phoneNumber: phoneNumber,
},
// In fututre we might want to generate future date appointments for the patients
// slot: DateTime.now()
Expand All @@ -155,9 +181,14 @@ const generateRandomPatientInfo = async (
scheduleType: 'location',
visitType: 'now',
visitService: visitService,
locationID: selectedLocationID || randomLocationId,
locationID: selectedInPersonLocationID || randomLocationId,
timezone: 'UTC',
isDemo: true,
phoneNumber: phoneNumber,
};
};

const getLocationIdFromState = (state: string, allLocations: any[]): string | undefined => {
const location = allLocations.find((item) => item.address?.state === state);
return location?.id;
};
2 changes: 0 additions & 2 deletions packages/telemed-ehr/app/src/hooks/useOttehrUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ export default function useOttehrUser(): OttehrUser | undefined {
if (resourceType && resourceId && resourceType === 'Practitioner') {
const practitioner = await client.readResource<Practitioner>({ resourceType, resourceId });
useOttehrUserStore.setState({ profile: practitioner });
console.log('practitioner', practitioner);
}
_profileLoadingState = LoadingState.idle;
} catch (e) {
Expand Down Expand Up @@ -347,7 +346,6 @@ const useGetProfile = () => {
if (resourceType && resourceId && resourceType === 'Practitioner') {
const practitioner = await fhirClient?.readResource<Practitioner>({ resourceType, resourceId });
useOttehrUserStore.setState({ profile: practitioner });
console.log('practitioner', practitioner);
}
} catch (e) {
console.error(`error fetching user's fhir profile: ${JSON.stringify(e)}`);
Expand Down
2 changes: 1 addition & 1 deletion packages/telemed-ehr/app/src/pages/Appointments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ function AppointmentsBody(props: AppointmentsBodyProps): ReactElement {
updateAppointments={updateAppointments}
setEditingComment={setEditingComment}
/>
<CreateDemoVisits />
<CreateDemoVisits schedulePage="in-person" />
</>
</PageContainer>
</form>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ import { useAuth0 } from '@auth0/auth0-react';
import { otherColors } from '../../../CustomThemeProvider';
import { LoadingButton } from '@mui/lab';
import { Box } from '@mui/system';
import useOttehrUser from '../../../hooks/useOttehrUser';

const CreateDemoVisits = (): ReactElement => {
interface CreateDemoVisitsProps {
schedulePage?: 'telemedicine' | 'in-person';
}

const CreateDemoVisits = ({ schedulePage }: CreateDemoVisitsProps): ReactElement => {
const [phoneNumber, setPhoneNumber] = useState('');
const [inputError, setInputError] = useState(false);
const [loading, setLoading] = useState(false);
Expand All @@ -24,6 +29,7 @@ const CreateDemoVisits = (): ReactElement => {
});
const { fhirClient } = useApiClients();
const { getAccessTokenSilently } = useAuth0();
const user = useOttehrUser();

const handleCreateSampleAppointments = async (
event: React.MouseEvent<HTMLButtonElement> | React.FormEvent<HTMLFormElement>,
Expand All @@ -40,12 +46,13 @@ const CreateDemoVisits = (): ReactElement => {
setLoading(true);
setInputError(false);
const authToken = await getAccessTokenSilently();
const response = await createSampleAppointments(fhirClient, authToken, formattedPhoneNumber);
const response = await createSampleAppointments(fhirClient, authToken, formattedPhoneNumber, user);
setSnackbar({
open: true,
message: 'Appointments created successfully!',
severity: 'success',
});
return response;
} catch (error) {
setSnackbar({
open: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ export function StateSelect(): ReactElement {
const { availableStates, state } = getSelectors(useTrackingBoardStore, ['availableStates', 'state']);
const options = [EMPTY_STATE, ...availableStates.map((state) => ({ label: state, value: state }))];

const randomState = availableStates[Math.floor(Math.random() * availableStates.length)];

const handleStateChange = (_e: any, { value }: { label: string | null; value: string | null }): void => {
localStorage.setItem('selectedState', value || '');
useTrackingBoardStore.setState((prevState) => ({ ...prevState, state: value }));
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,10 @@ export const TrackingBoardFilters: FC<{ tab: ApptTab }> = (props) => {
const useDate = tab === ApptTab.complete;
const useUnsigned = tab === ApptTab['not-signed'];
const handleProviderChange = (_e: any, value: string[]): void => {
console.log(10, value);
setProviders(value);
useTrackingBoardStore.setState({ providers: value });
};
const handleGroupChange = (_e: any, value: string[]): void => {
console.log(10, value);
setGroups(value);
useTrackingBoardStore.setState({ groups: value });
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ export function TrackingBoardTable({ tab }: AppointmentTableProps): ReactElement
return {};
}
return filteredAppointments.reduce<Record<string, TelemedAppointmentInformation[]>>((accumulator, appointment) => {
if (appointment.location.locationID) {
if (!accumulator[appointment.location.locationID]) {
accumulator[appointment.location.locationID] = [];
if (appointment.location.state) {
if (!accumulator[appointment.location.state]) {
accumulator[appointment.location.state] = [];
}
accumulator[appointment.location.locationID].push(appointment);
accumulator[appointment.location.state].push(appointment);
return accumulator;
} else if (appointment.provider) {
if (!accumulator[appointment.provider.join(',')]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export function TrackingBoardTabs(): ReactElement {
<TrackingBoardTable tab={value} />
</TabPanel>
</Paper>
<CreateDemoVisits />
<CreateDemoVisits schedulePage="telemedicine" />
</TabContext>
</Box>
);
Expand Down
2 changes: 2 additions & 0 deletions packages/telemed-ehr/app/src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ export const AllStates = [

export type StateType = (typeof AllStates extends readonly (infer TElementType)[] ? TElementType : never)['value'];

export const AllStatesValues: StateType[] = AllStates.map(({ value }) => value);

export const AllStatesToNames: {
[value in StateType]: string;
} = {
Expand Down
2 changes: 1 addition & 1 deletion packages/telemed-ehr/zambdas/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "telemed-ehrzambdas",
"version": "0.16.0",
"version": "0.17.0",
"private": true,
"scripts": {
"start": "npm run start:local",
Expand Down
4 changes: 0 additions & 4 deletions packages/telemed-ehr/zambdas/src/get-appointments/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,6 @@ export const index = async (input: ZambdaInput): Promise<APIGatewayProxyResult>
});
const [activeEncounters, searchResultsForSelectedDate] = await Promise.all([encounterSearch, appointmentSearch]);
console.timeEnd('get_active_encounters + get_appointment_data');
// console.log(searchResultsForSelectedDate);
// console.log(appointmentSearchParams);
// console.log(1, searchResultsForSelectedDate);
const encounterIds: string[] = [];

const tempAppointmentDates = activeEncounters
Expand Down Expand Up @@ -419,7 +416,6 @@ export const index = async (input: ZambdaInput): Promise<APIGatewayProxyResult>
console.time('structure_appointment_data');
let appointments: Appointment[] = [];
if (visitType?.length > 0) {
console.log(1, allAppointments.length);
appointments = allAppointments?.filter((appointment) => {
return visitType?.includes(appointment.appointmentType?.text || '');
});
Expand Down
2 changes: 1 addition & 1 deletion packages/telemed-intake/app/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "telemed-intake-app",
"private": true,
"version": "0.16.0",
"version": "0.17.0",
"type": "module",
"scripts": {
"start:local": "vite",
Expand Down
19 changes: 16 additions & 3 deletions packages/telemed-intake/app/src/components/CancelVisitDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FC } from 'react'; // Import useState for managing the select value
import { FC, useState } from 'react'; // Import useState for managing the select value
import { Typography } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { CustomDialog, PageForm, safelyCaptureException } from 'ottehr-components';
Expand All @@ -19,6 +19,7 @@ export const CancelVisitDialog: FC<CancelVisitDialogProps> = ({ onClose, appoint
const { appointmentID } = getSelectors(useAppointmentStore, ['appointmentID']);

const cancelAppointment = useCancelAppointmentMutation();
const [cancelVisitErrorMessage, setCancelVisitErrorMessage] = useState<string | null>(null);

const onSubmit = async (data: FieldValues): Promise<void> => {
if (!appointmentID) {
Expand All @@ -38,11 +39,18 @@ export const CancelVisitDialog: FC<CancelVisitDialogProps> = ({ onClose, appoint
},
{
onSuccess: () => {
setCancelVisitErrorMessage(null);
navigate(IntakeFlowPageRoute.PatientPortal.path);
handleClose();
},
onError: (error) => {
safelyCaptureException(error);
onError: (error: unknown) => {
if (error instanceof Error) {
safelyCaptureException(error);
setCancelVisitErrorMessage(error.message);
} else {
safelyCaptureException(new Error('An unknown error occurred'));
setCancelVisitErrorMessage('An unknown error occurred');
}
},
},
);
Expand Down Expand Up @@ -78,6 +86,11 @@ export const CancelVisitDialog: FC<CancelVisitDialogProps> = ({ onClose, appoint
}}
onSubmit={onSubmit}
/>
{cancelVisitErrorMessage && (
<Typography color="error" sx={{ mt: 2, textAlign: 'center' }}>
{cancelVisitErrorMessage}
</Typography>
)}
</CustomDialog>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { PromiseReturnType } from 'ottehr-utils';
export const useJoinCall = (
apiClient: ZapEHRAPIClient | null,
onSuccess: (data: PromiseReturnType<ReturnType<ZapEHRAPIClient['joinCall']>>) => void,
setError: (err: Error) => void,
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
) => {
return useQuery(
Expand All @@ -21,7 +22,8 @@ export const useJoinCall = (
},
{
onSuccess,
onError: (err) => {
onError: (err: Error) => {
setError(err);
console.error('Error during executing joinCall: ', err);
},
},
Expand Down
Loading

0 comments on commit 43d46cb

Please sign in to comment.