Skip to content

Commit

Permalink
Update appointments (#35)
Browse files Browse the repository at this point in the history
# Update appointments

## ♻️ Current situation & Problem
Updates appointments according to the discussions that emerged on the
meetings.

### Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
arkadiuszbachorski authored Aug 24, 2024
1 parent bdea12a commit 7fc0617
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 69 deletions.
52 changes: 6 additions & 46 deletions app/(dashboard)/patients/[id]/AppointmentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
import { type ComponentProps } from 'react'
import { z } from 'zod'
import { type Appointment } from '@/app/(dashboard)/patients/utils'
import {
FHIRAppointmentStatus,
stringifyAppointmentStatus,
} from '@/modules/firebase/models/medication'
import { Button } from '@/packages/design-system/src/components/Button'
import { DatePicker } from '@/packages/design-system/src/components/DatePicker'
import {
Expand All @@ -21,23 +17,16 @@ import {
DialogHeader,
DialogTitle,
} from '@/packages/design-system/src/components/Dialog'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/packages/design-system/src/components/Select'
import { Input } from '@/packages/design-system/src/components/Input'
import { Textarea } from '@/packages/design-system/src/components/Textarea'
import { Field } from '@/packages/design-system/src/forms/Field'
import { useForm } from '@/packages/design-system/src/forms/useForm'

export const appointmentFormSchema = z.object({
status: z.nativeEnum(FHIRAppointmentStatus),
start: z.date(),
end: z.date(),
comment: z.string().nullable(),
patientInstruction: z.string().nullable(),
providerName: z.string(),
})

export type AppointmentFormSchema = z.infer<typeof appointmentFormSchema>
Expand All @@ -55,11 +44,10 @@ export const AppointmentForm = ({
const form = useForm({
formSchema: appointmentFormSchema,
defaultValues: {
status: appointment?.status,
start: appointment ? new Date(appointment.start) : undefined,
end: appointment ? new Date(appointment.end) : undefined,
comment: appointment?.comment ?? null,
patientInstruction: appointment?.patientInstruction ?? null,
providerName: appointment?.providerName ?? '',
},
})

Expand All @@ -69,25 +57,6 @@ export const AppointmentForm = ({

return (
<form onSubmit={handleSubmit}>
<Field
control={form.control}
name="status"
label="Status"
render={({ field }) => (
<Select onValueChange={field.onChange} {...field}>
<SelectTrigger>
<SelectValue placeholder="Status" />
</SelectTrigger>
<SelectContent>
{Object.values(FHIRAppointmentStatus).map((status) => (
<SelectItem key={status} value={status}>
{stringifyAppointmentStatus(status)}
</SelectItem>
))}
</SelectContent>
</Select>
)}
/>
<Field
control={form.control}
name="start"
Expand All @@ -105,18 +74,9 @@ export const AppointmentForm = ({
/>
<Field
control={form.control}
name="end"
label="End"
render={({ field }) => (
<DatePicker
mode="single"
selected={field.value}
onSelect={(date) => field.onChange(date)}
defaultMonth={field.value}
fromDate={new Date()}
showTimePicker
/>
)}
name="providerName"
label="Provider"
render={({ field }) => <Input {...field} />}
/>
<Field
control={form.control}
Expand Down
11 changes: 3 additions & 8 deletions app/(dashboard)/patients/[id]/Appointments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import type {
AppointmentsData,
Appointment,
} from '@/app/(dashboard)/patients/utils'
import { stringifyAppointmentStatus } from '@/modules/firebase/models/medication'
import { Button } from '@/packages/design-system/src/components/Button'
import {
DataTable,
Expand All @@ -42,18 +41,14 @@ export const Appointments = ({
header: 'Created',
cell: dateColumn,
}),
columnHelper.accessor('status', {
header: 'Status',
cell: (props) => stringifyAppointmentStatus(props.getValue()),
columnHelper.accessor('providerName', {
header: 'Provider name',
cell: (props) => props.getValue(),
}),
columnHelper.accessor('start', {
header: 'Start',
cell: dateTimeColumn,
}),
columnHelper.accessor('end', {
header: 'End',
cell: dateTimeColumn,
}),
columnHelper.display({
id: 'actions',
cell: (props) => (
Expand Down
28 changes: 23 additions & 5 deletions app/(dashboard)/patients/actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@
//
'use server'
import { addDoc, deleteDoc, setDoc } from '@firebase/firestore'
import { addHours } from 'date-fns'
import { revalidatePath } from 'next/cache'
import { type AllergyFormSchema } from '@/app/(dashboard)/patients/[id]/AllergyForm'
import { type AppointmentFormSchema } from '@/app/(dashboard)/patients/[id]/AppointmentForm'
import { type LabFormSchema } from '@/app/(dashboard)/patients/[id]/LabForm'
import { getUnitOfObservationType } from '@/app/(dashboard)/patients/clientUtils'
import { getAuthenticatedOnlyApp } from '@/modules/firebase/guards'
import { AllergyType } from '@/modules/firebase/models/allergy'
import { ExtensionURL } from '@/modules/firebase/models/baseTypes'
import {
FHIRAllergyIntoleranceCriticality,
FHIRAllergyIntoleranceType,
FHIRAppointmentStatus,
FHIRObservationStatus,
} from '@/modules/firebase/models/medication'
import {
Expand Down Expand Up @@ -193,13 +196,28 @@ export const updateAllergy = async (
return 'success'
}

const getAppointmentData = (payload: AppointmentFormSchema) => ({
status: payload.status,
const getAppointmentData = (
payload: AppointmentFormSchema & { userId: string },
) => ({
status: FHIRAppointmentStatus.booked,
start: payload.start.toISOString(),
end: payload.end.toISOString(),
end: addHours(payload.start, 1).toISOString(),
comment: payload.comment,
patientInstruction: payload.patientInstruction,
participant: [],
extension: [
{ url: ExtensionURL.providerName, valueString: payload.providerName },
],
participant: [
{
actor: {
display: null,
type: null,
identifier: null,
reference: `users/${payload.userId}`,
},
type: null,
},
],
})

export const createAppointment = async (
Expand Down Expand Up @@ -238,7 +256,7 @@ export const updateAppointment = async (
appointmentId: payload.appointmentId,
}),
getAppointmentData(payload),
{ mergeFields: ['created'] },
{ merge: true },
)
revalidatePath(routes.patients.patient(payload.userId))
return 'success'
Expand Down
9 changes: 8 additions & 1 deletion app/(dashboard)/patients/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { groupBy } from 'es-toolkit'
import { query, where } from 'firebase/firestore'
import { getAuthenticatedOnlyApp } from '@/modules/firebase/guards'
import { AllergyType } from '@/modules/firebase/models/allergy'
import { ExtensionURL } from '@/modules/firebase/models/baseTypes'
import {
type FHIRAllergyIntolerance,
FHIRAllergyIntoleranceCriticality,
Expand Down Expand Up @@ -205,9 +206,15 @@ export const getAppointmentsData = async ({
resourceType: ResourceType
}) => {
const { refs } = await getAuthenticatedOnlyApp()
const appointments = await getDocsData(
const rawAppointments = await getDocsData(
refs.appointments({ userId, resourceType }),
)
const appointments = rawAppointments.map((appointment) => ({
...appointment,
providerName: appointment.extension?.find(
(extension) => extension.url === (ExtensionURL.providerName as string),
)?.valueString,
}))
return { appointments, userId, resourceType }
}

Expand Down
13 changes: 9 additions & 4 deletions modules/firebase/models/baseTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ export interface FHIRExtension {
valueQuantities?: FHIRSimpleQuantity[]
valueReference?: FHIRReference<unknown>
valueMedicationRequest?: FHIRMedicationRequest
valueString?: string
}

export enum ExtensionURL {
providerName = 'http://engagehf.bdh.stanford.edu/fhir/StructureDefinition/Appointment/extension/providerName',
}

export interface FHIRPeriod {
Expand All @@ -53,10 +58,10 @@ export interface FHIRRatio {
//
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export interface FHIRReference<T> {
reference?: string
type?: string
identifier?: string
display?: string
reference?: string | null
type?: string | null
identifier?: string | null
display?: string | null
}

export interface FHIRSimpleQuantity {
Expand Down
7 changes: 2 additions & 5 deletions modules/firebase/models/medication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
//
// SPDX-License-Identifier: MIT
//

import { startCase } from 'es-toolkit'
import {
type FHIRSimpleQuantity,
type FHIRCodeableConcept,
Expand All @@ -15,6 +13,7 @@ import {
type FHIRReference,
type FHIRPeriod,
type FHIRResource,
type FHIRExtension,
} from './baseTypes.js'

export interface FHIRMedication extends FHIRElement {
Expand Down Expand Up @@ -125,10 +124,8 @@ export enum FHIRAppointmentStatus {
waitlist = 'waitlist',
}

export const stringifyAppointmentStatus = (status: FHIRAppointmentStatus) =>
startCase(status)

export interface FHIRAppointment {
extension?: FHIRExtension[]
status: FHIRAppointmentStatus
created: string
start: string
Expand Down

0 comments on commit 7fc0617

Please sign in to comment.