-
Notifications
You must be signed in to change notification settings - Fork 211
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
BREAKING: O3-2827: Appointments: Refactor (Part I) #971
Changes from all commits
0125579
f8d30ac
89d1cc7
3db2c57
a09e835
705d1ec
1e69413
56e46bd
bca5b99
594f41f
f04c53d
bb5c993
2b5834b
f79a7a5
0063945
38de348
cc91281
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,14 +18,18 @@ | |
"extract-translations": "turbo extract-translations -- --config ../../tools/i18next-parser.config.js" | ||
}, | ||
"dependencies": { | ||
"@hookform/resolvers": "^3.3.1", | ||
"classnames": "^2.3.2", | ||
"react-hook-form": "^7.46.2", | ||
"swr": "^2.0.1", | ||
"xlsx": "^0.18.5" | ||
"xlsx": "^0.18.5", | ||
"zod": "^3.22.2" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.11.6", | ||
"@carbon/react": "~1.37.0", | ||
"@openmrs/esm-framework": "next", | ||
"@openmrs/esm-patient-common-lib": "next", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this dependency? I don't see it used in any of the code marked as coming from the chart. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I forget why I needed it, but it was because something wasn't working... potentially something I later removed, I will take it out and see if things still work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's used in the appointment-form.component @ibacher
|
||
"@playwright/test": "1.40.1", | ||
"@swc/core": "^1.2.165", | ||
"@swc/jest": "^0.2.29", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,28 +5,28 @@ import utc from 'dayjs/plugin/utc'; | |
import { Button, OverflowMenu, OverflowMenuItem } from '@carbon/react'; | ||
import { TaskComplete } from '@carbon/react/icons'; | ||
import { useTranslation } from 'react-i18next'; | ||
import { launchOverlay } from '../../hooks/useOverlay'; | ||
import { type MappedAppointment } from '../../types'; | ||
import { closeOverlay, launchOverlay } from '../../hooks/useOverlay'; | ||
import { type Appointment } from '../../types'; | ||
import { showModal } from '@openmrs/esm-framework'; | ||
import { useVisits } from '../../hooks/useVisits'; | ||
import AppointmentForm from '../forms/create-edit-form/appointments-form.component'; | ||
import AppointmentForm from '../../form/appointments-form.component'; | ||
import CheckInButton from './checkin-button.component'; | ||
import DefaulterTracingForm from '../forms/defaulter-tracing-form/default-tracing-form.component'; | ||
|
||
dayjs.extend(utc); | ||
dayjs.extend(isToday); | ||
|
||
interface AppointmentActionsProps { | ||
visits: Array<any>; | ||
appointment: MappedAppointment; | ||
appointment: Appointment; | ||
scheduleType: string; | ||
mutate: () => void; | ||
} | ||
|
||
const AppointmentActions: React.FC<AppointmentActionsProps> = ({ visits, appointment, scheduleType }) => { | ||
const AppointmentActions: React.FC<AppointmentActionsProps> = ({ visits, appointment, mutate }) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We seem to be passing The PatientSearchContext is a pretty good example of how this can be used. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it was annoying me that I had to pass this all the way around. I can check out out PatientSearchContext. Another pattern I was seeing was using the useSWR call at multiple levels just to retrieve the mutate function, but that didn't seem correct, and seemed dependent on making sure you were asking for the same/correct key at multiple levels. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the interest of getting this PR merged without continuing to bloat, I will handle this as a separate ticket here: https://openmrs.atlassian.net/browse/O3-2849 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can always create a new hook that does your There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @brandones ! |
||
const { t } = useTranslation(); | ||
const { mutateVisit } = useVisits(); | ||
const patientUuid = appointment.patientUuid; | ||
const visitDate = dayjs(appointment.dateTime); | ||
const patientUuid = appointment.patient.uuid; | ||
const visitDate = dayjs(appointment.startDateTime); | ||
const isFutureAppointment = visitDate.isAfter(dayjs()); | ||
const isTodayAppointment = visitDate.isToday(); | ||
const hasActiveVisit = visits?.some((visit) => visit?.patient?.uuid === patientUuid && visit?.startDatetime); | ||
|
@@ -44,17 +44,12 @@ const AppointmentActions: React.FC<AppointmentActionsProps> = ({ visits, appoint | |
}); | ||
}; | ||
|
||
const handleOpenDefaulterForm = () => { | ||
launchOverlay('CCC Defaulter tracing form', <DefaulterTracingForm patientUuid={appointment.patientUuid} />); | ||
}; | ||
|
||
/** | ||
* Renders the appropriate visit status button based on the current appointment state. | ||
* @returns {JSX.Element} The rendered button. | ||
*/ | ||
const renderVisitStatus = () => { | ||
const checkedOutText = t('checkedOut', 'Checked out'); | ||
const followUpButtonText = t('launchFormUpForm', 'Follow up'); | ||
|
||
switch (true) { | ||
case hasCheckedOut: | ||
|
@@ -70,27 +65,10 @@ const AppointmentActions: React.FC<AppointmentActionsProps> = ({ visits, appoint | |
</Button> | ||
); | ||
case isTodayAppointment: { | ||
const isAfterNoon = new Date().getHours() > 12; | ||
|
||
if (scheduleType === 'Pending' && isAfterNoon) { | ||
return ( | ||
<Button onClick={handleOpenDefaulterForm} size="sm" kind="tertiary"> | ||
{followUpButtonText} | ||
</Button> | ||
); | ||
} | ||
|
||
Comment on lines
-73
to
-82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not in a position to say whether this is right or not, but this does seem to indicate a point where we have implementation needs for extensibility that's not currently provided. |
||
return <CheckInButton patientUuid={patientUuid} appointment={appointment} />; | ||
} | ||
|
||
default: | ||
if (!isFutureAppointment) { | ||
return ( | ||
<Button onClick={handleOpenDefaulterForm} size="sm" kind="tertiary"> | ||
{followUpButtonText} | ||
</Button> | ||
); | ||
} | ||
return null; | ||
} | ||
}; | ||
|
@@ -105,7 +83,12 @@ const AppointmentActions: React.FC<AppointmentActionsProps> = ({ visits, appoint | |
onClick={() => | ||
launchOverlay( | ||
t('editAppointments', 'Edit Appointment'), | ||
<AppointmentForm appointment={appointment} context="editing" />, | ||
<AppointmentForm | ||
appointment={appointment} | ||
context="editing" | ||
closeWorkspace={closeOverlay} | ||
mutate={mutate} | ||
/>, | ||
) | ||
} | ||
/> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,7 +25,7 @@ import { Download } from '@carbon/react/icons'; | |
import { EmptyState } from '../../empty-state/empty-state.component'; | ||
import { downloadAppointmentsAsExcel } from '../../helpers/excel'; | ||
import { launchOverlay } from '../../hooks/useOverlay'; | ||
import { type MappedAppointment } from '../../types'; | ||
import { type Appointment } from '../../types'; | ||
import { getPageSizes, useSearchResults } from '../utils'; | ||
import { type ConfigObject } from '../../config-schema'; | ||
import AppointmentDetails from '../details/appointment-details.component'; | ||
|
@@ -34,10 +34,10 @@ import PatientSearch from '../../patient-search/patient-search.component'; | |
import styles from './appointments-table.scss'; | ||
|
||
interface AppointmentsTableProps { | ||
appointments: Array<MappedAppointment>; | ||
appointments: Array<Appointment>; | ||
isLoading: boolean; | ||
tableHeading: string; | ||
mutate?: () => void; | ||
mutate: () => void; | ||
visits?: Array<any>; | ||
scheduleType?: string; | ||
} | ||
|
@@ -46,6 +46,7 @@ const AppointmentsTable: React.FC<AppointmentsTableProps> = ({ | |
appointments, | ||
isLoading, | ||
tableHeading, | ||
mutate, | ||
visits, | ||
scheduleType, | ||
}) => { | ||
|
@@ -82,16 +83,18 @@ const AppointmentsTable: React.FC<AppointmentsTableProps> = ({ | |
<ConfigurableLink | ||
style={{ textDecoration: 'none', maxWidth: '50%' }} | ||
to={customPatientChartUrl} | ||
templateParams={{ patientUuid: appointment.patientUuid }}> | ||
{appointment.name} | ||
templateParams={{ patientUuid: appointment.patient.uuid }}> | ||
{appointment.patient.name} | ||
</ConfigurableLink> | ||
), | ||
nextAppointmentDate: '--', | ||
identifier: appointment.identifier, | ||
dateTime: formatDatetime(new Date(appointment.dateTime)), | ||
serviceType: appointment.serviceType, | ||
identifier: appointment.patient.identifier, | ||
dateTime: formatDatetime(new Date(appointment.startDateTime)), | ||
serviceType: appointment.service.name, | ||
provider: appointment.provider, | ||
actions: <AppointmentActions visits={visits} appointment={appointment} scheduleType={scheduleType} />, | ||
actions: ( | ||
<AppointmentActions visits={visits} appointment={appointment} scheduleType={scheduleType} mutate={mutate} /> | ||
), | ||
})); | ||
|
||
if (isLoading) { | ||
|
@@ -130,7 +133,9 @@ const AppointmentsTable: React.FC<AppointmentsTableProps> = ({ | |
onClick={() => | ||
downloadAppointmentsAsExcel( | ||
appointments, | ||
`${tableHeading} Appointments ${formatDate(new Date(appointments[0]?.dateTime), { year: true })}`, | ||
`${tableHeading} Appointments ${formatDate(new Date(appointments[0]?.startDateTime), { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FIXME for latter, but this should all be translatable. |
||
year: true, | ||
})}`, | ||
) | ||
}> | ||
{t('download', 'Download')} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this isn't terribly important, it would be preferrable, I think, to keep all dependencies in
devDependencies
. These aren't in any way different from how we handle, e.g.,dayjs
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ibacher ! I thought I was just keeping this consistent with the patient chart, but it looks like they are all devDependencies there, I will correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, so looking again, I see that these dependencies are listed as dependencies, not devDependencies, in patient-chart. However, when I moved them all to devDependencies here things worked. Do we have a best practice regarding this (to be honest, I don't really understand why these are all devdepencies, is the assumption thst they are all bundled with ESM framework anyway)? @ibacher @denniskigen @brandones
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah we are somewhat inconsistent on this because we changed the norm a couple times during the first couple years of O3. I don't think there is a technical difference between
devDependencies
anddependencies
for us, with our current tooling and setup, though at least some monorepo tools installdevDependencies
at the monorepo level anddependencies
at the package level—but I think Yarn 4 just treats them the same.Oddly, my inclination would be the opposite of what @ibacher suggests here—I am inclined to follow the rule that a dependency that gets built/bundled goes in
dependencies
. But I am quite open to being convinced otherwise 🤷