Skip to content

Commit

Permalink
feat: load immunizations
Browse files Browse the repository at this point in the history
  • Loading branch information
mgramigna committed Dec 16, 2023
1 parent 6f43e9f commit 149b4cf
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 33 deletions.
94 changes: 64 additions & 30 deletions apps/expo/src/app/(app)/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import React, { Fragment } from 'react';
import { ActivityIndicator, ScrollView, View } from 'react-native';
import { Link } from 'expo-router';
import { Button } from '@/components/atoms/Button';
import { Skeleton } from '@/components/atoms/Skeleton';
import { Text } from '@/components/atoms/Text';
import { AllergyDetail } from '@/components/molecules/AllergyDetail';
import { ImmunizationDetail } from '@/components/molecules/ImmunizationDetail';
import { MedicationDetail } from '@/components/molecules/MedicationDetail';
import { ScreenView } from '@/components/molecules/ScreenView';
import { HomeAppointmentList } from '@/components/organisms/HomeAppointmentList';
Expand All @@ -12,40 +14,54 @@ import { usePatient } from '@/context/PatientContext';
import { getFirstName } from '@/fhirpath/patient';
import { palette } from '@/theme/colors';
import { api } from '@/utils/api';
import { Ionicons } from '@expo/vector-icons';
import { Ionicons, MaterialCommunityIcons } from '@expo/vector-icons';
import dayjs from 'dayjs';

const Home = () => {
const { patientId } = useAuth();
const { patient, isLoading } = usePatient();

const { data: appointmentBundle } = api.appointment.search.useQuery(
{
patient: `Patient/${patientId!}`,
_sort: 'date',
},
{
enabled: !!patientId,
},
);
const { data: appointmentBundle, isLoading: appointmentsLoading } =
api.appointment.search.useQuery(
{
patient: `Patient/${patientId!}`,
_sort: 'date',
date: `ge${dayjs().format('YYYY-MM-DD')}`,
},
{
enabled: !!patientId,
},
);

const { data: allergyBundle, isLoading: allergiesLoading } =
api.allergyintolerance.search.useQuery(
{
patient: patientId!,
},
{
enabled: !!patientId,
},
);

const { data: allergyBundle } = api.allergyintolerance.search.useQuery(
{
patient: patientId!,
},
{
enabled: !!patientId,
},
);
const { data: medicationStatementBundle, isLoading: medicationsLoading } =
api.medicationstatement.search.useQuery(
{
patient: patientId!,
},
{
enabled: !!patientId,
},
);

const { data: medicationStatementBundle } = api.medicationstatement.search.useQuery(
{
patient: patientId!,
},
{
enabled: !!patientId,
},
);
const { data: immunizationsBundle, isLoading: vaccinesLoading } =
api.immunization.search.useQuery(
{
patient: patientId!,
},
{
enabled: !!patientId,
},
);

if (isLoading) {
return (
Expand All @@ -69,9 +85,10 @@ const Home = () => {
<View className="mt-24">
<View className="mb-4 flex flex-row items-center">
<Ionicons name="calendar" size={24} color={palette.purple[300]} />
<Text className="ml-2 text-3xl">Upcoming Appointments</Text>
<Text className="ml-2 text-3xl">My Appointments</Text>
</View>
{(appointmentBundle?.total ?? 0) > 0 ? (
{appointmentsLoading && <Skeleton className="bg-coolGray-400 h-24" />}
{!appointmentsLoading && (appointmentBundle?.total ?? 0) > 0 ? (
<HomeAppointmentList
appointments={appointmentBundle?.entry?.map(({ resource }) => resource) ?? []}
/>
Expand All @@ -86,9 +103,10 @@ const Home = () => {
</View>
<View className="mt-24">
<View className="mb-4 flex flex-row items-center">
<Ionicons name="flower" size={24} color={palette.purple[300]} />
<MaterialCommunityIcons name="allergy" size={24} color={palette.purple[300]} />
<Text className="ml-2 text-3xl">My Allergies</Text>
</View>
{allergiesLoading && <Skeleton className="bg-coolGray-400 h-24" />}
{allergyBundle?.entry?.map(({ resource }) => (
<Fragment key={resource.id}>
<AllergyDetail allergyIntolerance={resource} />
Expand All @@ -100,9 +118,10 @@ const Home = () => {
</View>
<View className="mt-24">
<View className="mb-4 flex flex-row items-center">
<Ionicons name="medkit" size={24} color={palette.purple[300]} />
<MaterialCommunityIcons name="pill" size={24} color={palette.purple[300]} />
<Text className="ml-2 text-3xl">My Medications</Text>
</View>
{medicationsLoading && <Skeleton className="bg-coolGray-400 h-24" />}
{medicationStatementBundle?.entry?.map(({ resource }) => (
<Fragment key={resource.id}>
<MedicationDetail medicationStatement={resource} />
Expand All @@ -112,6 +131,21 @@ const Home = () => {
<Button text="Update Medications" className="mt-4" />
</Link>
</View>
<View className="mt-24">
<View className="mb-4 flex flex-row items-center">
<MaterialCommunityIcons name="needle" size={24} color={palette.purple[300]} />
<Text className="ml-2 text-3xl">My Vaccines</Text>
</View>
{vaccinesLoading && <Skeleton className="bg-coolGray-400 h-24" />}
{immunizationsBundle?.entry?.map(({ resource }) => (
<Fragment key={resource.id}>
<ImmunizationDetail immunization={resource} />
</Fragment>
))}
<Link href="/home/medication" asChild>
<Button text="Update Medications" className="mt-4" />
</Link>
</View>
</ScrollView>
</ScreenView>
) : null;
Expand Down
6 changes: 6 additions & 0 deletions apps/expo/src/components/atoms/Skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { View, type ViewProps } from 'react-native';
import { cn } from '@/utils/cn';

export const Skeleton = ({ className, ...props }: ViewProps) => {
return <View className={cn('bg-muted animate-pulse rounded-md', className)} {...props} />;
};
16 changes: 16 additions & 0 deletions apps/expo/src/components/molecules/ImmunizationDetail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { View } from 'react-native';
import { getVaccineName } from '@/fhirpath/immunization';

import { type Immunization } from '@canvas-challenge/canvas';

import { Text } from '../atoms/Text';

export const ImmunizationDetail = ({ immunization }: { immunization: Immunization }) => {
const vaccineName = getVaccineName(immunization);

return (
<View>
<Text className="text-xl">{vaccineName}</Text>
</View>
);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useCallback } from 'react';
import { ActivityIndicator, Modal, View } from 'react-native';
import { ActivityIndicator, Modal, ScrollView, View } from 'react-native';
import { getLocationAddress } from '@/fhirpath/location';
import { getPractitionerName } from '@/fhirpath/practitioner';
import { usePractitioner } from '@/hooks/usePractitioner';
Expand Down Expand Up @@ -75,7 +75,7 @@ export const ScheduleAppointmentModal = ({
onRequestClose={onClose}
>
<ScreenView>
<View className="flex h-full">
<ScrollView className="flex h-full">
{isLoading ? (
<ActivityIndicator />
) : (
Expand Down Expand Up @@ -160,7 +160,7 @@ export const ScheduleAppointmentModal = ({
</View>
</>
)}
</View>
</ScrollView>
</ScreenView>
</Modal>
);
Expand Down
18 changes: 18 additions & 0 deletions apps/expo/src/fhirpath/immunization.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import fhirpath from 'fhirpath';

import { type Immunization } from '@canvas-challenge/canvas';

export function getVaccineName(immunization: Immunization): string | null {
const [display] = fhirpath.evaluate(
immunization,
'vaccineCode.coding.first().display',
) as string[];

return display ?? null;
}

export function getVaccineDateString(immunization: Immunization): string | null {
const [dateString] = fhirpath.evaluate(immunization, 'occurrenceDateTime') as string[];

return dateString ?? null;
}

0 comments on commit 149b4cf

Please sign in to comment.