From e4832b599b435588091f3ae3cf4670933334b036 Mon Sep 17 00:00:00 2001 From: Stephen Barrs Date: Fri, 22 Nov 2024 16:43:51 -0500 Subject: [PATCH 1/3] Add allergy management features including data fetching and UI components --- VAMobile/src/api/allergies/getAllergies.tsx | 33 ++++ .../src/api/allergies/getAllergyLocation.tsx | 29 +++ VAMobile/src/api/allergies/queryKeys.ts | 4 + VAMobile/src/api/types/AllergyData.ts | 59 ++++++ VAMobile/src/api/types/index.ts | 1 + .../AllergyDetailsScreen.test.tsx | 102 +++++++++++ .../AllergyDetails/AllergyDetailsScreen.tsx | 169 ++++++++++++++++++ .../AllergyList/AllergyListScreen.test.tsx | 96 ++++++++++ .../AllergyList/AllergyListScreen.tsx | 140 +++++++++++++++ .../NoAllergyRecords.test.tsx | 44 +++++ .../NoAllergyRecords/NoAllergyRecords.tsx | 32 ++++ .../src/screens/HealthScreen/HealthScreen.tsx | 13 ++ .../HealthScreen/HealthStackScreens.tsx | 5 + 13 files changed, 727 insertions(+) create mode 100644 VAMobile/src/api/allergies/getAllergies.tsx create mode 100644 VAMobile/src/api/allergies/getAllergyLocation.tsx create mode 100644 VAMobile/src/api/allergies/queryKeys.ts create mode 100644 VAMobile/src/api/types/AllergyData.ts create mode 100644 VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.test.tsx create mode 100644 VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx create mode 100644 VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.test.tsx create mode 100644 VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx create mode 100644 VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.test.tsx create mode 100644 VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.tsx diff --git a/VAMobile/src/api/allergies/getAllergies.tsx b/VAMobile/src/api/allergies/getAllergies.tsx new file mode 100644 index 00000000000..92a0de0ff7a --- /dev/null +++ b/VAMobile/src/api/allergies/getAllergies.tsx @@ -0,0 +1,33 @@ +import { useQuery } from '@tanstack/react-query' + +import { AllergyListPayload } from 'api/types' +import { LARGE_PAGE_SIZE } from 'constants/common' +import { get } from 'store/api' + +import { allergyKeys } from './queryKeys' + +/** + * Fetch user Allergies + */ +const getAllergies = (): Promise => { + return get('/v1/health/immunizations', { + 'page[number]': '1', + 'page[size]': LARGE_PAGE_SIZE.toString(), + sort: 'date', + useCache: 'false', + }) +} + +/** + * Returns a query for user Allergies + */ +export const useAllergies = (options?: { enabled?: boolean }) => { + return useQuery({ + ...options, + queryKey: [allergyKeys.allergies], + queryFn: () => getAllergies(), + meta: { + errorName: 'getAllergies: Service error', + }, + }) +} diff --git a/VAMobile/src/api/allergies/getAllergyLocation.tsx b/VAMobile/src/api/allergies/getAllergyLocation.tsx new file mode 100644 index 00000000000..06fb799b3da --- /dev/null +++ b/VAMobile/src/api/allergies/getAllergyLocation.tsx @@ -0,0 +1,29 @@ +import { useQuery } from '@tanstack/react-query' + +import { VaccineLocationPayload } from 'api/types' +import { get } from 'store/api' + +import { allergyKeys } from './queryKeys' + +/** + * Fetch user Vaccine Location + */ +const getAllergyLocation = async (locationId: string): Promise => { + const response = await get(`/v0/health/locations/${locationId}`) + return response +} + +/** + * Returns a query for user Vaccine Location + */ +export const useAllergyLocation = (locationId: string, options?: { enabled?: boolean }) => { + return useQuery({ + ...options, + queryKey: [allergyKeys.allergyLocations, locationId], + queryFn: () => getAllergyLocation(locationId), + meta: { + errorName: 'getAllergyLocation: Service error', + }, + retry: 0, + }) +} diff --git a/VAMobile/src/api/allergies/queryKeys.ts b/VAMobile/src/api/allergies/queryKeys.ts new file mode 100644 index 00000000000..70303ed4701 --- /dev/null +++ b/VAMobile/src/api/allergies/queryKeys.ts @@ -0,0 +1,4 @@ +export const allergyKeys = { + allergies: ['allergies'] as const, + allergyLocations: ['allergyLocations'] as const, +} diff --git a/VAMobile/src/api/types/AllergyData.ts b/VAMobile/src/api/types/AllergyData.ts new file mode 100644 index 00000000000..a79c23b8667 --- /dev/null +++ b/VAMobile/src/api/types/AllergyData.ts @@ -0,0 +1,59 @@ +export type AllergyListPayload = { + data: Array + links: { + self: string + first: string + prev: string + next: string + last: string + } + meta: { + pagination: { + currentPage: number + perPage: number + totalPages: number + totalEntries: number + } + dataFromStore: boolean + } +} + +export type Allergy = { + id?: string | null + type?: string | null + attributes?: { + cvxCode?: number | null + date?: string | null + doseNumber?: number | string | null + doseSeries?: number | string | null + groupName?: string | null + manufacturer?: string | null + note?: string | null + shortDescription?: string | null + reaction?: string | null + } + relationships?: { + location?: { + data?: { + id?: string | null + type?: string | null + } | null + } + } +} + +export type AllergyLocationPayload = { + data: { + type?: string | null + id?: string | null + attributes: { + name?: string | null + address: { + street?: string | null + city?: string | null + state?: string | null + zipCode?: string | null + } | null + } + } +} diff --git a/VAMobile/src/api/types/index.ts b/VAMobile/src/api/types/index.ts index 6147a71e951..b86a13c056f 100644 --- a/VAMobile/src/api/types/index.ts +++ b/VAMobile/src/api/types/index.ts @@ -18,3 +18,4 @@ export * from './PrescriptionData' export * from './SecureMessagingData' export * from './ServiceHistoryData' export * from './VaccineData' +export * from './AllergyData' diff --git a/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.test.tsx b/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.test.tsx new file mode 100644 index 00000000000..eda30c4838e --- /dev/null +++ b/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.test.tsx @@ -0,0 +1,102 @@ +import React from 'react' + +import { screen } from '@testing-library/react-native' + +import { Vaccine } from 'api/types' +import * as api from 'store/api' +import { context, mockNavProps, render, waitFor, when } from 'testUtils' + +import VaccineDetailsScreen from './VaccineDetailsScreen' + +context('VaccineDetailsScreen', () => { + const defaultVaccine = { + id: 'N7A6Q5AU6W5C6O4O7QEDZ3SJXM000000', + type: 'immunization', + attributes: { + cvxCode: 207, + date: '2020-12-18T12:24:55Z', + doseNumber: 'Series 1', + doseSeries: 1, + groupName: 'COVID-19', + reaction: 'Fever', + manufacturer: 'Janssen', + note: 'Dose #1 of 2 of COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose vaccine administered.', + shortDescription: 'COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose', + }, + } + + const location = { + data: { + id: 'location1', + type: 'location', + attributes: { + name: 'facility 1', + address: { + street: '123 abc street', + city: 'Tiburon', + state: 'CA', + zipCode: '94920', + }, + }, + }, + } + + const hasLocationVaccine = { + id: 'HASLOCATION', + type: 'immunization', + attributes: { + cvxCode: 207, + date: '2020-12-18T12:24:55Z', + doseNumber: null, + doseSeries: null, + groupName: 'COVID-19', + manufacturer: null, + note: null, + shortDescription: 'COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose', + }, + relationships: { + location: location, + }, + } + + const initializeTestInstance = (vaccine: Vaccine = defaultVaccine) => { + const props = mockNavProps(undefined, undefined, { params: { vaccine: vaccine } }) + render() + } + + it('initializes correctly for default vaccine', () => { + initializeTestInstance() + expect(screen.getByText('December 18, 2020')).toBeTruthy() + expect(screen.getByRole('header', { name: 'COVID-19 vaccine' })).toBeTruthy() + expect(screen.getByText('Type and dosage')).toBeTruthy() + expect(screen.getByText('COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose')).toBeTruthy() + expect(screen.getByText('Janssen')).toBeTruthy() + expect(screen.getByText('Series status')).toBeTruthy() + expect(screen.getByText('Series 1 of 1')).toBeTruthy() + expect(screen.getByText('Provider')).toBeTruthy() + expect(screen.getByText('None noted')).toBeTruthy() + expect(screen.getByText('Reaction')).toBeTruthy() + expect(screen.getByText('Notes')).toBeTruthy() + expect( + screen.getByText('Dose #1 of 2 of COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose vaccine administered.'), + ).toBeTruthy() + expect( + screen.getByText( + 'We base this information on your current VA health records. If you have any questions, contact your health care team.', + ), + ).toBeTruthy() + expect(screen.queryByText('facility 1')).toBeFalsy() + expect(screen.queryByText('123 abc street')).toBeFalsy() + expect(screen.queryByText('Tiburon, CA 94920')).toBeFalsy() + }) + + it('initializes correctly for has location vaccine', async () => { + when(api.get as jest.Mock) + .calledWith(`/v0/health/locations/location1`) + .mockResolvedValue({ ...location }) + initializeTestInstance(hasLocationVaccine) + await waitFor(() => expect(screen.getByText('facility 1')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('123 abc street')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Tiburon, CA 94920')).toBeTruthy()) + }) +}) diff --git a/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx b/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx new file mode 100644 index 00000000000..ce155c35dc7 --- /dev/null +++ b/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx @@ -0,0 +1,169 @@ +import React, { useEffect } from 'react' +import { useTranslation } from 'react-i18next' + +import { StackScreenProps } from '@react-navigation/stack' + +import { every } from 'underscore' + +import { useAllergyLocation } from 'api/allergies/getAllergyLocation' +import { Box, FeatureLandingTemplate, LoadingComponent, TextArea, TextView } from 'components' +import { Events } from 'constants/analytics' +import { COVID19 } from 'constants/common' +import { NAMESPACE } from 'constants/namespaces' +import { a11yLabelVA } from 'utils/a11yLabel' +import { logAnalyticsEvent } from 'utils/analytics' +import { formatDateMMMMDDYYYY } from 'utils/formattingUtils' +import { useAppDispatch, useTheme } from 'utils/hooks' +import { screenContentAllowed } from 'utils/waygateConfig' + +import { HealthStackParamList } from '../../HealthStackScreens' + +type AllergyDetailsScreenProps = StackScreenProps + +/** + * Screen providing details on an allergy + */ +function AllergyDetailsScreen({ route, navigation }: AllergyDetailsScreenProps) { + const { allergy } = route.params + const { data: location, isLoading: detailsLoading } = useAllergyLocation( + allergy.relationships?.location?.data?.id || '', + { + enabled: !!allergy.relationships?.location?.data?.id && screenContentAllowed('WG_VaccineDetails'), + }, + ) + + const theme = useTheme() + const { t } = useTranslation(NAMESPACE.COMMON) + const { contentMarginBottom, standardMarginBetween } = theme.dimensions + const dispatch = useAppDispatch() + + const placeHolder = t('noneNoted') + + useEffect(() => { + logAnalyticsEvent(Events.vama_vaccine_details(allergy?.attributes?.groupName || '')) + }, [dispatch, allergy]) + + if (!allergy) { + return <> + } + + const displayDate = allergy.attributes?.date ? formatDateMMMMDDYYYY(allergy.attributes.date) : placeHolder + + const displayName = allergy.attributes?.groupName + ? t('vaccines.vaccineName', { name: allergy.attributes.groupName }) + : placeHolder + + const hasSeries = allergy.attributes?.doseNumber && allergy.attributes?.doseSeries + const displaySeries = hasSeries + ? t('vaccines.details.series.display', { + doseNumber: allergy.attributes?.doseNumber, + seriesDoses: allergy.attributes?.doseSeries, + }) + : placeHolder + + const optionalFields = [hasSeries, allergy.attributes?.note, location?.data, allergy.attributes?.reaction] + const isPartialData = !every(optionalFields) + + // Only show the manufacturer label if the vaccine is COVID-19, any other type should not be displayed + const isCovidVaccine = allergy.attributes?.groupName?.toUpperCase()?.includes(COVID19) + + return ( + + {detailsLoading ? ( + // + + ) : ( + + + {isPartialData && ( + + + {t('vaccines.details.weBaseThis')} + + + )} + + )} + + ) +} + +export default AllergyDetailsScreen diff --git a/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.test.tsx b/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.test.tsx new file mode 100644 index 00000000000..38f0791cfcc --- /dev/null +++ b/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.test.tsx @@ -0,0 +1,96 @@ +import React from 'react' + +import { screen } from '@testing-library/react-native' +import { waitFor } from '@testing-library/react-native' + +import * as api from 'store/api' +import { context, mockNavProps, render, when } from 'testUtils' + +import VaccineListScreen from './VaccineListScreen' + +context('VaccineListScreen', () => { + const vaccineData = [ + { + id: 'I2-A7XD2XUPAZQ5H4Y5D6HJ352GEQ000000', + type: 'immunization', + attributes: { + cvxCode: 140, + date: '2009-03-19T12:24:55Z', + doseNumber: 'Booster', + doseSeries: 1, + groupName: 'FLU', + manufacturer: null, + note: 'Dose #45 of 101 of Influenza seasonal injectable preservative free vaccine administered.', + shortDescription: 'Influenza seasonal injectable preservative free', + }, + }, + { + id: 'I2-N7A6Q5AU6W5C6O4O7QEDZ3SJXM000000', + type: 'immunization', + attributes: { + cvxCode: 207, + date: '2020-12-18T12:24:55Z', + doseNumber: null, + doseSeries: null, + groupName: 'COVID-19', + manufacturer: null, + note: 'Dose #1 of 2 of COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose vaccine administered.', + shortDescription: 'COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose', + }, + }, + ] + + const initializeTestInstance = () => { + render() + } + + it('initializes correctly', async () => { + when(api.get as jest.Mock) + .calledWith('/v1/health/immunizations', expect.anything()) + .mockResolvedValue({ data: vaccineData }) + initializeTestInstance() + await waitFor(() => expect(screen.getByText('FLU vaccine')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('COVID-19 vaccine')).toBeTruthy()) + }) + + describe('when loading is set to true', () => { + it('should show loading screen', () => { + when(api.get as jest.Mock) + .calledWith('/v1/health/immunizations', expect.anything()) + .mockResolvedValue({ data: vaccineData }) + initializeTestInstance() + expect(screen.getByText('Loading your vaccine record...')).toBeTruthy() + }) + }) + + describe('when there are no vaccines', () => { + it('should show no Vaccine Records', async () => { + when(api.get as jest.Mock) + .calledWith('/v1/health/immunizations', expect.anything()) + .mockResolvedValue({ data: [] }) + + initializeTestInstance() + await waitFor(() => + expect( + screen.getByRole('heading', { name: "We couldn't find information about your VA vaccines" }), + ).toBeTruthy(), + ) + await waitFor(() => + expect( + screen.getByText( + "We're sorry. We update your vaccine records every 24 hours, but new records can take up to 36 hours to appear.", + ), + ).toBeTruthy(), + ) + await waitFor(() => + expect( + screen.getByText( + "If you think your vaccine records should be here, call our MyVA411 main information line. We're here 24/7.", + ), + ).toBeTruthy(), + ) + await waitFor(() => expect(screen.getByRole('link', { name: '800-698-2411' })).toBeTruthy()) + await waitFor(() => expect(screen.getByRole('link', { name: 'TTY: 711' })).toBeTruthy()) + }) + }) +}) diff --git a/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx b/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx new file mode 100644 index 00000000000..7d342fac490 --- /dev/null +++ b/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx @@ -0,0 +1,140 @@ +import React, { useEffect, useRef, useState } from 'react' +import { useTranslation } from 'react-i18next' +import { ScrollView } from 'react-native' + +import { StackScreenProps } from '@react-navigation/stack' + +import { map } from 'underscore' + +import { useAllergies } from 'api/allergies/getAllergies' +import { Allergy } from 'api/types' +import { + Box, + DefaultList, + DefaultListItemObj, + ErrorComponent, + FeatureLandingTemplate, + LoadingComponent, + Pagination, + PaginationProps, + TextLine, +} from 'components' +import { VAScrollViewProps } from 'components/VAScrollView' +import { DEFAULT_PAGE_SIZE } from 'constants/common' +import { NAMESPACE } from 'constants/namespaces' +import { ScreenIDTypesConstants } from 'store/api/types/Screens' +import { a11yLabelVA } from 'utils/a11yLabel' +import { getA11yLabelText } from 'utils/common' +import { formatDateMMMMDDYYYY } from 'utils/formattingUtils' +import { useError, useRouteNavigation, useTheme } from 'utils/hooks' +import { screenContentAllowed } from 'utils/waygateConfig' + +import { HealthStackParamList } from '../../HealthStackScreens' +import NoAllergyRecords from '../NoAllergyRecords/NoAllergyRecords' + +type AllergyListScreenProps = StackScreenProps + +/** + * Screen containing a list of allergies on record and a link to their details view + */ +function AllergyListScreen({ navigation }: AllergyListScreenProps) { + const [page, setPage] = useState(1) + // checks for downtime, immunizations downtime constant is having an issue with unit test + const vaccinesInDowntime = useError(ScreenIDTypesConstants.VACCINE_LIST_SCREEN_ID) + const { + data: allergies, + isFetching: loading, + error: vaccineError, + refetch: refetchVaccines, + } = useAllergies({ enabled: screenContentAllowed('WG_VaccineList') && !vaccinesInDowntime }) + const theme = useTheme() + const { t } = useTranslation(NAMESPACE.COMMON) + const navigateTo = useRouteNavigation() + const [AllergiesToShow, setAllergiesToShow] = useState>([]) + + const scrollViewRef = useRef(null) + const scrollViewProps: VAScrollViewProps = { + scrollViewRef: scrollViewRef, + } + + useEffect(() => { + const vaccineList = allergies?.data.slice((page - 1) * DEFAULT_PAGE_SIZE, page * DEFAULT_PAGE_SIZE) + setAllergiesToShow(vaccineList || []) + }, [allergies?.data, page]) + + const allergyButtons: Array = map(AllergiesToShow, (allergy, index) => { + const textLines: Array = [ + { text: t('vaccines.vaccineName', { name: allergy.attributes?.groupName }), variant: 'MobileBodyBold' }, + { text: formatDateMMMMDDYYYY(allergy.attributes?.date || '') }, + ] + + const allergyButton: DefaultListItemObj = { + textLines, + onPress: () => { + navigateTo('AllergyDetails', { allergy: allergy }) + }, + a11yHintText: t('vaccines.list.a11yHint'), + a11yValue: t('listPosition', { position: index + 1, total: allergies?.data.length }), + testId: getA11yLabelText(textLines), + } + + return allergyButton + }) + + // Render pagination for sent and drafts folderMessages only + function renderPagination() { + const paginationProps: PaginationProps = { + onNext: () => { + setPage(page + 1) + scrollViewRef.current?.scrollTo({ x: 0, y: 0, animated: false }) + }, + onPrev: () => { + setPage(page - 1) + scrollViewRef.current?.scrollTo({ x: 0, y: 0, animated: false }) + }, + totalEntries: allergies?.meta?.pagination?.totalEntries || 0, + pageSize: DEFAULT_PAGE_SIZE, + page, + } + + return ( + + + + ) + } + + return ( + + {loading ? ( + + ) : vaccineError || vaccinesInDowntime ? ( + + ) : allergies?.data?.length === 0 ? ( + + ) : ( + <> + + + + {renderPagination()} + + )} + + ) +} + +export default AllergyListScreen diff --git a/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.test.tsx b/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.test.tsx new file mode 100644 index 00000000000..9671b22ee10 --- /dev/null +++ b/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.test.tsx @@ -0,0 +1,44 @@ +import React from 'react' +import { Linking } from 'react-native' + +import { fireEvent, screen } from '@testing-library/react-native' + +import { context, render } from 'testUtils' + +import NoVaccineRecords from './NoVaccineRecords' + +context('NoVaccineRecords', () => { + beforeEach(() => { + render() + }) + + it('initializes correctly', () => { + expect(screen.getByRole('heading', { name: "We couldn't find information about your VA vaccines" })).toBeTruthy() + expect( + screen.getByText( + "We're sorry. We update your vaccine records every 24 hours, but new records can take up to 36 hours to appear.", + ), + ).toBeTruthy() + expect( + screen.getByText( + "If you think your vaccine records should be here, call our MyVA411 main information line. We're here 24/7.", + ), + ).toBeTruthy() + expect(screen.getByRole('link', { name: '800-698-2411' })).toBeTruthy() + expect(screen.getByRole('link', { name: 'TTY: 711' })).toBeTruthy() + }) + + describe('when the My HealtheVet phone number link is clicked', () => { + it('should call Linking open url with the parameter tel:8006982411', () => { + fireEvent.press(screen.getByRole('link', { name: '800-698-2411' })) + expect(Linking.openURL).toBeCalledWith('tel:8006982411') + }) + }) + + describe('when the call TTY phone link is clicked', () => { + it('should call Linking open url with the parameter tel:711', () => { + fireEvent.press(screen.getByRole('link', { name: 'TTY: 711' })) + expect(Linking.openURL).toBeCalledWith('tel:711') + }) + }) +}) diff --git a/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.tsx b/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.tsx new file mode 100644 index 00000000000..84919151f63 --- /dev/null +++ b/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.tsx @@ -0,0 +1,32 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' + +import { AlertWithHaptics, ClickToCallPhoneNumber, TextView, VAScrollView } from 'components' +import { NAMESPACE } from 'constants/namespaces' +import { a11yLabelVA } from 'utils/a11yLabel' +import { displayedTextPhoneNumber } from 'utils/formattingUtils' + +function NoVaccineRecords() { + const { t } = useTranslation(NAMESPACE.COMMON) + + return ( + + + + {t('noVaccineRecords.alert.text.2')} + + + + + ) +} + +export default NoVaccineRecords diff --git a/VAMobile/src/screens/HealthScreen/HealthScreen.tsx b/VAMobile/src/screens/HealthScreen/HealthScreen.tsx index 2e5c64dc43d..7f79ff0f55b 100644 --- a/VAMobile/src/screens/HealthScreen/HealthScreen.tsx +++ b/VAMobile/src/screens/HealthScreen/HealthScreen.tsx @@ -25,6 +25,8 @@ import { useDowntime, useRouteNavigation, useTheme } from 'utils/hooks' import { featureEnabled } from 'utils/remoteConfig' import { screenContentAllowed } from 'utils/waygateConfig' +import AllergyDetailsScreen from './Allergies/AllergyDetails/AllergyDetailsScreen' +import AllergyListScreen from './Allergies/AllergyList/AllergyListScreen' import Appointments from './Appointments' import PastAppointmentDetails from './Appointments/PastAppointments/PastAppointmentDetails' import UpcomingAppointmentDetails from './Appointments/UpcomingAppointments/UpcomingAppointmentDetails' @@ -162,6 +164,7 @@ export function HealthScreen({}: HealthScreenProps) { onPress={() => navigateTo('VaccineList')} testID="toVaccineListID" /> + navigateTo('AllergyList')} testID="toAllergyListID" /> {showAlert && } {cernerExist && ( @@ -259,6 +262,16 @@ function HealthStackScreen({}: HealthStackScreenProps) { component={VaccineListScreen} options={FEATURE_LANDING_TEMPLATE_OPTIONS} /> + + ) diff --git a/VAMobile/src/screens/HealthScreen/HealthStackScreens.tsx b/VAMobile/src/screens/HealthScreen/HealthStackScreens.tsx index 3e25b321365..d74bc4897f1 100644 --- a/VAMobile/src/screens/HealthScreen/HealthStackScreens.tsx +++ b/VAMobile/src/screens/HealthScreen/HealthStackScreens.tsx @@ -4,6 +4,7 @@ import { ImagePickerResponse } from 'react-native-image-picker' import { createStackNavigator } from '@react-navigation/stack' import { + Allergy, AppointmentData, PrescriptionData, RefillRequestSummaryItems, @@ -103,6 +104,10 @@ export type HealthStackParamList = WebviewStackParams & { VaccineDetails: { vaccine: Vaccine } + AllergyList: undefined + AllergyDetails: { + allergy: Allergy + } GeneralHelpScreen: { title: string description: string From e2a96bcf38175d50a6ce62f2726c107af4840eb8 Mon Sep 17 00:00:00 2001 From: Stephen Barrs Date: Wed, 27 Nov 2024 16:40:43 -0500 Subject: [PATCH 2/3] Add allergy management features including data fetching and UI components --- VAMobile/src/api/allergies/getAllergies.tsx | 2 +- VAMobile/src/api/types/AllergyData.ts | 50 ++-- .../AllergyDetails/AllergyDetailsScreen.tsx | 156 ++++++------- .../AllergyList/AllergyListScreen.tsx | 11 +- .../src/screens/HealthScreen/HealthScreen.tsx | 6 +- .../VaccineList/VaccineListScreen.tsx | 3 + VAMobile/src/store/api/demo/allergies.ts | 27 +++ .../src/store/api/demo/mocks/allergies.json | 218 ++++++++++++++++++ VAMobile/src/store/api/demo/store.ts | 9 +- VAMobile/src/translations/en/common.json | 5 + 10 files changed, 371 insertions(+), 116 deletions(-) create mode 100644 VAMobile/src/store/api/demo/allergies.ts create mode 100644 VAMobile/src/store/api/demo/mocks/allergies.json diff --git a/VAMobile/src/api/allergies/getAllergies.tsx b/VAMobile/src/api/allergies/getAllergies.tsx index 92a0de0ff7a..936bf71a2f5 100644 --- a/VAMobile/src/api/allergies/getAllergies.tsx +++ b/VAMobile/src/api/allergies/getAllergies.tsx @@ -10,7 +10,7 @@ import { allergyKeys } from './queryKeys' * Fetch user Allergies */ const getAllergies = (): Promise => { - return get('/v1/health/immunizations', { + return get('/v0/health/allergy-intolerances', { 'page[number]': '1', 'page[size]': LARGE_PAGE_SIZE.toString(), sort: 'date', diff --git a/VAMobile/src/api/types/AllergyData.ts b/VAMobile/src/api/types/AllergyData.ts index a79c23b8667..b240bbc9d99 100644 --- a/VAMobile/src/api/types/AllergyData.ts +++ b/VAMobile/src/api/types/AllergyData.ts @@ -22,38 +22,26 @@ export type Allergy = { id?: string | null type?: string | null attributes?: { - cvxCode?: number | null - date?: string | null - doseNumber?: number | string | null - doseSeries?: number | string | null - groupName?: string | null - manufacturer?: string | null - note?: string | null - shortDescription?: string | null - reaction?: string | null - } - relationships?: { - location?: { - data?: { - id?: string | null - type?: string | null - } | null - } + code?: { + text?: string | null + } | null + category?: string | null + recordedDate?: string | null + notes?: Array | null + recorder?: { + display?: string | null + } | null + reactions?: Array | null } } -export type AllergyLocationPayload = { - data: { - type?: string | null - id?: string | null - attributes: { - name?: string | null - address: { - street?: string | null - city?: string | null - state?: string | null - zipCode?: string | null - } | null - } - } +export type Reaction = { + manifestation: Array | null +} +export type ManifestationText = { + text: string +} + +export type NoteText = { + text: string } diff --git a/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx b/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx index ce155c35dc7..5d3a0dbd240 100644 --- a/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx +++ b/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx @@ -5,6 +5,7 @@ import { StackScreenProps } from '@react-navigation/stack' import { every } from 'underscore' +import { useAllergies } from 'api/allergies/getAllergies' import { useAllergyLocation } from 'api/allergies/getAllergyLocation' import { Box, FeatureLandingTemplate, LoadingComponent, TextArea, TextView } from 'components' import { Events } from 'constants/analytics' @@ -25,12 +26,13 @@ type AllergyDetailsScreenProps = StackScreenProps { - logAnalyticsEvent(Events.vama_vaccine_details(allergy?.attributes?.groupName || '')) - }, [dispatch, allergy]) + // analtyics + // useEffect(() => { + // logAnalyticsEvent(Events.vama_vaccine_details(allergy?.attributes?.groupName || '')) + // }, [dispatch, allergy]) if (!allergy) { return <> } - const displayDate = allergy.attributes?.date ? formatDateMMMMDDYYYY(allergy.attributes.date) : placeHolder - - const displayName = allergy.attributes?.groupName - ? t('vaccines.vaccineName', { name: allergy.attributes.groupName }) + const displayDate = allergy.attributes?.recordedDate + ? formatDateMMMMDDYYYY(allergy.attributes.recordedDate) : placeHolder - const hasSeries = allergy.attributes?.doseNumber && allergy.attributes?.doseSeries - const displaySeries = hasSeries - ? t('vaccines.details.series.display', { - doseNumber: allergy.attributes?.doseNumber, - seriesDoses: allergy.attributes?.doseSeries, - }) + const displayName = allergy.attributes?.code?.text + ? t('allergies.allergyName', { name: allergy.attributes?.code?.text }) : placeHolder - const optionalFields = [hasSeries, allergy.attributes?.note, location?.data, allergy.attributes?.reaction] - const isPartialData = !every(optionalFields) + const hasType = allergy.attributes?.category + // const displayType = hasType ? allergy.attributes?.category : placeHolder - // Only show the manufacturer label if the vaccine is COVID-19, any other type should not be displayed - const isCovidVaccine = allergy.attributes?.groupName?.toUpperCase()?.includes(COVID19) + const optionalFields = [ + hasType, + allergy.attributes?.notes, + // allergy.attributes?.reaction, + allergy.attributes?.recorder, + ] + const isPartialData = !every(optionalFields) return ( {detailsLoading ? ( - // - + ) : ( + // {isPartialData && ( diff --git a/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx b/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx index 7d342fac490..c7eb17fc87e 100644 --- a/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx +++ b/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx @@ -47,6 +47,9 @@ function AllergyListScreen({ navigation }: AllergyListScreenProps) { error: vaccineError, refetch: refetchVaccines, } = useAllergies({ enabled: screenContentAllowed('WG_VaccineList') && !vaccinesInDowntime }) + + // console.log(JSON.stringify(allergies, null, 3)) + const theme = useTheme() const { t } = useTranslation(NAMESPACE.COMMON) const navigateTo = useRouteNavigation() @@ -64,8 +67,8 @@ function AllergyListScreen({ navigation }: AllergyListScreenProps) { const allergyButtons: Array = map(AllergiesToShow, (allergy, index) => { const textLines: Array = [ - { text: t('vaccines.vaccineName', { name: allergy.attributes?.groupName }), variant: 'MobileBodyBold' }, - { text: formatDateMMMMDDYYYY(allergy.attributes?.date || '') }, + { text: allergy.attributes?.code?.text ?? '', variant: 'MobileBodyBold' }, + { text: formatDateMMMMDDYYYY(allergy.attributes?.recordedDate || '') }, ] const allergyButton: DefaultListItemObj = { @@ -113,10 +116,10 @@ function AllergyListScreen({ navigation }: AllergyListScreenProps) { backLabel={t('health.title')} backLabelOnPress={navigation.goBack} title="Allergies" - titleA11y={a11yLabelVA(t('vaVaccines'))} + titleA11y={a11yLabelVA(t('vaAllergies'))} scrollViewProps={scrollViewProps}> {loading ? ( - + ) : vaccineError || vaccinesInDowntime ? ( navigateTo('VaccineList')} testID="toVaccineListID" /> - navigateTo('AllergyList')} testID="toAllergyListID" /> + navigateTo('AllergyList')} + testID="toAllergyListID" + /> {showAlert && } {cernerExist && ( diff --git a/VAMobile/src/screens/HealthScreen/Vaccines/VaccineList/VaccineListScreen.tsx b/VAMobile/src/screens/HealthScreen/Vaccines/VaccineList/VaccineListScreen.tsx index e26ac6ac57c..5a93d25ddb2 100644 --- a/VAMobile/src/screens/HealthScreen/Vaccines/VaccineList/VaccineListScreen.tsx +++ b/VAMobile/src/screens/HealthScreen/Vaccines/VaccineList/VaccineListScreen.tsx @@ -47,6 +47,9 @@ function VaccineListScreen({ navigation }: VaccineListScreenProps) { error: vaccineError, refetch: refetchVaccines, } = useVaccines({ enabled: screenContentAllowed('WG_VaccineList') && !vaccinesInDowntime }) + + console.log(JSON.stringify(vaccines, null, 3)) + const theme = useTheme() const { t } = useTranslation(NAMESPACE.COMMON) const navigateTo = useRouteNavigation() diff --git a/VAMobile/src/store/api/demo/allergies.ts b/VAMobile/src/store/api/demo/allergies.ts new file mode 100644 index 00000000000..7365af86ea7 --- /dev/null +++ b/VAMobile/src/store/api/demo/allergies.ts @@ -0,0 +1,27 @@ +import { AllergyListPayload } from 'api/types/AllergyData' + +import { Params } from '..' +import { DemoStore } from './store' + +type AllergyPageNumber = '1' + +/** + * Type denoting the demo data store + */ +export type AllergyList = { + '/v1/health/allergy-intolerances': { + '1': AllergyListPayload + } +} + +export type AllergyDemoStore = AllergyList + +/** + * Type to define the mock returns to keep type safety + */ +export type AllergyDemoReturnTypes = undefined | AllergyListPayload + +export const getAllergyList = (store: DemoStore, params: Params, endpoint: string): AllergyListPayload => { + const page = params['page[number]'] + return store[endpoint as keyof AllergyList][page as AllergyPageNumber] as AllergyListPayload +} diff --git a/VAMobile/src/store/api/demo/mocks/allergies.json b/VAMobile/src/store/api/demo/mocks/allergies.json new file mode 100644 index 00000000000..95e63c48acf --- /dev/null +++ b/VAMobile/src/store/api/demo/mocks/allergies.json @@ -0,0 +1,218 @@ +{ + "/v1/health/allergy-intolerances": { + "1": { + "data": [ + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000000", + "type": "allergy_intolerance", + "attributes": { + "name": "Latex Allergy", + "type": "allergy", + "clinicalStatus": "active", + "recordedDate": "2021-01-14T09:30:21Z", + "notes": "Latex allergy", + "recorder": "DR. THOMAS359 REYNOLDS206 PHD", + "reaction": "Itchy Watery Eyes" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000001", + "type": "allergy_intolerance", + "attributes": { + "name": "Peanut", + "type": "allergy", + "clinicalStatus": "inactive", + "recordedDate": "2021-02-20T11:45:00Z", + "notes": "Peanut allergy", + "recorder": "DR. JANE DOE", + "reaction": "Hives" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000002", + "type": "allergy_intolerance", + "attributes": { + "name": "Pollen", + "type": "allergy", + "clinicalStatus": "active", + "recordedDate": "2021-03-10T14:20:00Z", + "notes": "Pollen allergy", + "recorder": "DR. JOHN SMITH", + "reaction": "Sneezing" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000003", + "type": "allergy_intolerance", + "attributes": { + "name": "Dust", + "type": "allergy", + "clinicalStatus": "inactive", + "recordedDate": "2021-04-15T09:00:00Z", + "notes": "Dust allergy", + "recorder": "DR. EMILY JOHNSON", + "reaction": "Coughing" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000004", + "type": "allergy_intolerance", + "attributes": { + "name": "Cat", + "type": "allergy", + "clinicalStatus": "active", + "recordedDate": "2021-05-20T10:30:00Z", + "notes": "Cat allergy", + "recorder": "DR. MICHAEL BROWN", + "reaction": "Itchy Skin" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000005", + "type": "allergy_intolerance", + "attributes": { + "name": "Dog", + "type": "allergy", + "clinicalStatus": "inactive", + "recordedDate": "2021-06-25T13:15:00Z", + "notes": "Dog allergy", + "recorder": "DR. LUCY WILLIAMS", + "reaction": "Runny Nose" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000006", + "type": "allergy_intolerance", + "attributes": { + "name": "Shellfish", + "type": "allergy", + "clinicalStatus": "active", + "recordedDate": "2021-07-30T15:45:00Z", + "notes": "Shellfish allergy", + "recorder": "DR. DAVID MARTIN", + "reaction": "Swelling" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000007", + "type": "allergy_intolerance", + "attributes": { + "name": "Milk", + "type": "allergy", + "clinicalStatus": "inactive", + "recordedDate": "2021-08-05T11:00:00Z", + "notes": "Milk allergy", + "recorder": "DR. ROBERT CLARK", + "reaction": "Stomach Pain" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000008", + "type": "allergy_intolerance", + "attributes": { + "name": "Egg", + "type": "allergy", + "clinicalStatus": "active", + "recordedDate": "2021-09-10T09:30:00Z", + "notes": "Egg allergy", + "recorder": "DR. PATRICIA MOORE", + "reaction": "Rash" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000009", + "type": "allergy_intolerance", + "attributes": { + "name": "Wheat", + "type": "allergy", + "clinicalStatus": "inactive", + "recordedDate": "2021-10-15T14:00:00Z", + "notes": "Wheat allergy", + "recorder": "DR. CHRISTOPHER TAYLOR", + "reaction": "Bloating" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000010", + "type": "allergy_intolerance", + "attributes": { + "name": "Soy", + "type": "allergy", + "clinicalStatus": "active", + "recordedDate": "2021-11-20T10:00:00Z", + "notes": "Soy allergy", + "recorder": "DR. MARY ANDERSON", + "reaction": "Nausea" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000011", + "type": "allergy_intolerance", + "attributes": { + "name": "Tree Nut", + "type": "allergy", + "clinicalStatus": "inactive", + "recordedDate": "2021-12-25T12:30:00Z", + "notes": "Tree nut allergy", + "recorder": "DR. JAMES LEE", + "reaction": "Anaphylaxis" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000012", + "type": "allergy_intolerance", + "attributes": { + "name": "Fish", + "type": "allergy", + "clinicalStatus": "active", + "recordedDate": "2022-01-30T09:45:00Z", + "notes": "Fish allergy", + "recorder": "DR. LINDA HARRIS", + "reaction": "Swelling" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000013", + "type": "allergy_intolerance", + "attributes": { + "name": "Insect Sting", + "type": "allergy", + "clinicalStatus": "inactive", + "recordedDate": "2022-02-15T11:15:00Z", + "notes": "Insect sting allergy", + "recorder": "DR. WILLIAM WALKER", + "reaction": "Swelling" + } + }, + { + "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000014", + "type": "allergy_intolerance", + "attributes": { + "name": "Mold", + "type": "allergy", + "clinicalStatus": "active", + "recordedDate": "2022-03-20T13:00:00Z", + "notes": "Mold allergy", + "recorder": "DR. BARBARA SCOTT", + "reaction": "Sneezing" + } + } + ], + "meta": { + "pagination": { + "currentPage": 1, + "perPage": 10, + "totalPages": 2, + "totalEntries": 15 + } + }, + "links": { + "self": "https://staging-api.va.gov/mobile/v1/health/allergy-intolerances?useCache=true&page[size]=10&page[number]=1", + "first": "https://staging-api.va.gov/mobile/v1/health/allergy-intolerances?useCache=true&page[size]=10&page[number]=1", + "prev": null, + "next": "https://staging-api.va.gov/mobile/v1/health/allergy-intolerances?useCache=true&page[size]=10&page[number]=2", + "last": "https://staging-api.va.gov/mobile/v1/health/allergy-intolerances?useCache=true&page[size]=10&page[number]=2" + } + } + } +} diff --git a/VAMobile/src/store/api/demo/store.ts b/VAMobile/src/store/api/demo/store.ts index e6513445cf3..e006869b5c1 100644 --- a/VAMobile/src/store/api/demo/store.ts +++ b/VAMobile/src/store/api/demo/store.ts @@ -10,6 +10,7 @@ import { import { featureEnabled } from 'utils/remoteConfig' import { Params } from '../api' +import { AllergyDemoReturnTypes, AllergyDemoStore, getAllergyList } from './allergies' import { AppointmentDemoReturnTypes, AppointmentsDemoStore, getAppointments } from './appointments' import { ClaimsDemoApiReturnTypes, ClaimsDemoStore, getClaimsAndAppealsOverview } from './claims' import { DecisionLettersDemoApiReturnTypes, DecisionLettersDemoStore } from './decisionLetters' @@ -53,7 +54,8 @@ export type DemoStore = AppointmentsDemoStore & PaymenDemoStore & PrescriptionsDemoStore & NotificationDemoStore & - DemographicsDemoStore + DemographicsDemoStore & + AllergyDemoStore /** * Union type to define the mock returns to keep type safety @@ -71,6 +73,7 @@ type DemoApiReturns = | PrescriptionsDemoReturnTypes | NotificationDemoApiReturnTypes | DemographicsDemoApiReturnTypes + | AllergyDemoReturnTypes let store: DemoStore | undefined @@ -150,6 +153,7 @@ export const initDemoStore = async (): Promise => { : import('./mocks/getFacilitiesInfo.json'), import('./mocks/demographics.json'), import('./mocks/personalInformation.json'), + import('./mocks/allergies.json'), ]) const transformedData = data.map((file) => transformDates(file)) setDemoStore(transformedData.reduce((merged, current) => ({ ...merged, ...current }), {}) as unknown as DemoStore) @@ -224,6 +228,9 @@ const transformGetCall = (endpoint: string, params: Params): DemoApiReturns => { case '/v1/health/immunizations': { return getVaccineList(store, params, endpoint) } + case '/v1/health/allergy-intolerances': { + return getAllergyList(store, params, endpoint) + } case '/v0/payment-history': { return getPaymentsHistory(store, params, endpoint) } diff --git a/VAMobile/src/translations/en/common.json b/VAMobile/src/translations/en/common.json index acfbc355175..8b053d17067 100644 --- a/VAMobile/src/translations/en/common.json +++ b/VAMobile/src/translations/en/common.json @@ -29,6 +29,11 @@ "activity.informationNotIncluded": "Information from My VA Health portal not included.", "activity.loading": "Loading mobile app activity...", "add.preference.btn.title": "Add preference", + "vaAllergies": "VA allergies", + "vaAllergies.buttonTitle": "V\ufeffA allergy records", + "allergies.loading": "Loading your allergy record...", + "allergies.allergyName": "{{name}} allergy", + "allergies.details.loading": "Loading your allergy details...", "and": "and", "appealDetails.agencyJurisdiction": "Agency of Original Jurisdiction", "appealDetails.amaNod": "Board of Veterans’ Appeals received your appeal", From 9949ba58ee16017e9a3497b49cb045c77ffdf168 Mon Sep 17 00:00:00 2001 From: Stephen Barrs Date: Fri, 6 Dec 2024 17:07:14 -0500 Subject: [PATCH 3/3] Refactor allergy-related components and types, remove unused allergy location API, and update error handling for allergy screens --- .../src/api/allergies/getAllergyLocation.tsx | 29 - VAMobile/src/api/allergies/queryKeys.ts | 1 - VAMobile/src/api/types/AllergyData.ts | 2 +- VAMobile/src/constants/analytics.ts | 5 + .../AllergyDetailsScreen.test.tsx | 276 ++++++-- .../AllergyDetails/AllergyDetailsScreen.tsx | 76 +- .../AllergyList/AllergyListScreen.test.tsx | 138 +++- .../AllergyList/AllergyListScreen.tsx | 26 +- .../NoAllergyRecords.test.tsx | 10 +- .../NoAllergyRecords/NoAllergyRecords.tsx | 12 +- .../VaccineDetails/VaccineDetailsScreen.tsx | 10 +- .../VaccineList/VaccineListScreen.tsx | 2 - .../src/store/api/demo/mocks/allergies.json | 666 ++++++++++++------ VAMobile/src/store/api/types/Errors.ts | 5 + VAMobile/src/store/api/types/Screens.ts | 3 + VAMobile/src/translations/en/common.json | 12 +- VAMobile/src/utils/errors.ts | 2 + VAMobile/src/utils/waygateConfig.ts | 6 + 18 files changed, 852 insertions(+), 429 deletions(-) delete mode 100644 VAMobile/src/api/allergies/getAllergyLocation.tsx diff --git a/VAMobile/src/api/allergies/getAllergyLocation.tsx b/VAMobile/src/api/allergies/getAllergyLocation.tsx deleted file mode 100644 index 06fb799b3da..00000000000 --- a/VAMobile/src/api/allergies/getAllergyLocation.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { useQuery } from '@tanstack/react-query' - -import { VaccineLocationPayload } from 'api/types' -import { get } from 'store/api' - -import { allergyKeys } from './queryKeys' - -/** - * Fetch user Vaccine Location - */ -const getAllergyLocation = async (locationId: string): Promise => { - const response = await get(`/v0/health/locations/${locationId}`) - return response -} - -/** - * Returns a query for user Vaccine Location - */ -export const useAllergyLocation = (locationId: string, options?: { enabled?: boolean }) => { - return useQuery({ - ...options, - queryKey: [allergyKeys.allergyLocations, locationId], - queryFn: () => getAllergyLocation(locationId), - meta: { - errorName: 'getAllergyLocation: Service error', - }, - retry: 0, - }) -} diff --git a/VAMobile/src/api/allergies/queryKeys.ts b/VAMobile/src/api/allergies/queryKeys.ts index 70303ed4701..b8a693224a9 100644 --- a/VAMobile/src/api/allergies/queryKeys.ts +++ b/VAMobile/src/api/allergies/queryKeys.ts @@ -1,4 +1,3 @@ export const allergyKeys = { allergies: ['allergies'] as const, - allergyLocations: ['allergyLocations'] as const, } diff --git a/VAMobile/src/api/types/AllergyData.ts b/VAMobile/src/api/types/AllergyData.ts index b240bbc9d99..1df4d49be48 100644 --- a/VAMobile/src/api/types/AllergyData.ts +++ b/VAMobile/src/api/types/AllergyData.ts @@ -25,7 +25,7 @@ export type Allergy = { code?: { text?: string | null } | null - category?: string | null + category?: Array | null recordedDate?: string | null notes?: Array | null recorder?: { diff --git a/VAMobile/src/constants/analytics.ts b/VAMobile/src/constants/analytics.ts index d4da9bea452..089c32a631a 100644 --- a/VAMobile/src/constants/analytics.ts +++ b/VAMobile/src/constants/analytics.ts @@ -29,6 +29,11 @@ export const Events = { name: 'vama_af_updated', } }, + vama_allergy_details: (): Event => { + return { + name: 'vama_allergy_details', + } + }, vama_appt_cancel: ( isPendingAppointment: boolean, apt_id: string | undefined, diff --git a/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.test.tsx b/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.test.tsx index eda30c4838e..5f6785e8374 100644 --- a/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.test.tsx +++ b/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.test.tsx @@ -2,101 +2,225 @@ import React from 'react' import { screen } from '@testing-library/react-native' -import { Vaccine } from 'api/types' -import * as api from 'store/api' +import { Allergy } from 'api/types' +// import * as api from 'store/api' import { context, mockNavProps, render, waitFor, when } from 'testUtils' -import VaccineDetailsScreen from './VaccineDetailsScreen' +import AllergyDetailsScreen from './AllergyDetailsScreen' -context('VaccineDetailsScreen', () => { - const defaultVaccine = { - id: 'N7A6Q5AU6W5C6O4O7QEDZ3SJXM000000', - type: 'immunization', +context('AllergyDetailsScreen', () => { + const defaultAllergy = { + id: '4-1abLZzsevfVnWK', + type: 'allergy_intolerance', attributes: { - cvxCode: 207, - date: '2020-12-18T12:24:55Z', - doseNumber: 'Series 1', - doseSeries: 1, - groupName: 'COVID-19', - reaction: 'Fever', - manufacturer: 'Janssen', - note: 'Dose #1 of 2 of COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose vaccine administered.', - shortDescription: 'COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose', + resourceType: 'AllergyIntolerance', + type: 'allergy', + clinicalStatus: { + coding: [ + { + system: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical', + code: 'active', + }, + ], + }, + category: ['medication'], + code: { + coding: [ + { + system: 'http://hl7.org/fhir/ndfrt', + code: 'N0000008048', + display: 'Sulfonamides', + }, + ], + text: 'Sulfonamides', + }, + recordedDate: '2019-03-12T16:30:00Z', + patient: { + reference: 'https://sandbox-api.va.gov/services/fhir/v0/r4/Patient/1013956965V299908', + display: 'DAMASO SUPNICK', + }, + notes: [ + { + authorReference: { + reference: 'https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Nn79MgdlF9vV', + display: 'Dr. Alicia629 Ureña88 MD', + }, + time: '2019-03-12T16:30:00Z', + text: 'Sulfonamides', + }, + ], + recorder: { + reference: 'https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Nn79MgdlF9vV', + display: 'Dr. Alicia629 Ureña88 MD', + }, + reactions: [], }, } - const location = { - data: { - id: 'location1', - type: 'location', - attributes: { - name: 'facility 1', - address: { - street: '123 abc street', - city: 'Tiburon', - state: 'CA', - zipCode: '94920', + const reactions = [ + { + substance: { + coding: [], + text: null, + }, + manifestation: [ + { + coding: [], + text: 'Urticaria (Hives)', }, + ], + }, + { + substance: { + coding: [], + text: null, }, + manifestation: [ + { + coding: [], + text: 'Anaphylaxis', + }, + ], }, - } + ] - const hasLocationVaccine = { - id: 'HASLOCATION', - type: 'immunization', - attributes: { - cvxCode: 207, - date: '2020-12-18T12:24:55Z', - doseNumber: null, - doseSeries: null, - groupName: 'COVID-19', - manufacturer: null, - note: null, - shortDescription: 'COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose', + const notes = [ + { + authorReference: { + reference: 'https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Nn79MgdlF9vV', + display: 'Dr. Alicia629 Ureña88 MD', + }, + time: '2019-03-12T16:30:00Z', + text: 'Sulfonamides', }, - relationships: { - location: location, + { + authorReference: { + reference: 'https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Nn79MgdlF9vV', + display: 'Dr. Alicia629 Ureña88 MD', + }, + time: '2019-03-13T12:30:00Z', + text: 'Patient has a family history of sulfa allergy', }, - } + { + authorReference: { + reference: 'https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Nn79MgdlF9vV', + display: 'Dr. Alicia629 Ureña88 MD', + }, + time: '2020-03-15T16:30:00Z', + text: 'Additional episode of hives', + }, + ] - const initializeTestInstance = (vaccine: Vaccine = defaultVaccine) => { - const props = mockNavProps(undefined, undefined, { params: { vaccine: vaccine } }) - render() + const initializeTestInstance = (allergy: Allergy = defaultAllergy) => { + const props = mockNavProps(undefined, undefined, { params: { allergy: allergy } }) + render() } - it('initializes correctly for default vaccine', () => { + it('initializes correctly for default allergy', async () => { initializeTestInstance() - expect(screen.getByText('December 18, 2020')).toBeTruthy() - expect(screen.getByRole('header', { name: 'COVID-19 vaccine' })).toBeTruthy() - expect(screen.getByText('Type and dosage')).toBeTruthy() - expect(screen.getByText('COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose')).toBeTruthy() - expect(screen.getByText('Janssen')).toBeTruthy() - expect(screen.getByText('Series status')).toBeTruthy() - expect(screen.getByText('Series 1 of 1')).toBeTruthy() - expect(screen.getByText('Provider')).toBeTruthy() - expect(screen.getByText('None noted')).toBeTruthy() - expect(screen.getByText('Reaction')).toBeTruthy() - expect(screen.getByText('Notes')).toBeTruthy() - expect( - screen.getByText('Dose #1 of 2 of COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose vaccine administered.'), - ).toBeTruthy() - expect( - screen.getByText( + await waitFor(() => expect(screen.getByText('March 12, 2019')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Type')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('medication')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Provider')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Dr. Alicia629 Ureña88 MD')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Reaction')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('None noted')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Notes')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Sulfonamides')).toBeTruthy()) + await waitFor(() => + expect( + screen.getByText( + 'We base this information on your current VA health records. If you have any questions, contact your health care team.', + ), + ).toBeTruthy(), + ) + }) + + it('initializes correctly for allergy with reactions', async () => { + const allergyWithReactions = { + ...defaultAllergy, + attributes: { + ...defaultAllergy.attributes, + reactions: reactions, + }, + } + + initializeTestInstance(allergyWithReactions) + await waitFor(() => expect(screen.getByText('March 12, 2019')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Type')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('medication')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Provider')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Dr. Alicia629 Ureña88 MD')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Reaction')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Urticaria (Hives)')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Notes')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Sulfonamides')).toBeTruthy()) + await waitFor(() => { + const textElement = screen.queryByText( 'We base this information on your current VA health records. If you have any questions, contact your health care team.', - ), - ).toBeTruthy() - expect(screen.queryByText('facility 1')).toBeFalsy() - expect(screen.queryByText('123 abc street')).toBeFalsy() - expect(screen.queryByText('Tiburon, CA 94920')).toBeFalsy() + ) + expect(textElement).toBeNull() + }) }) - it('initializes correctly for has location vaccine', async () => { - when(api.get as jest.Mock) - .calledWith(`/v0/health/locations/location1`) - .mockResolvedValue({ ...location }) - initializeTestInstance(hasLocationVaccine) - await waitFor(() => expect(screen.getByText('facility 1')).toBeTruthy()) - await waitFor(() => expect(screen.getByText('123 abc street')).toBeTruthy()) - await waitFor(() => expect(screen.getByText('Tiburon, CA 94920')).toBeTruthy()) + it('initializes correctly for allergy with multiple categories', async () => { + const allergyWithCategories = { + ...defaultAllergy, + attributes: { + ...defaultAllergy.attributes, + reactions: reactions, + category: ['medication', 'food'], + }, + } + + initializeTestInstance(allergyWithCategories) + await waitFor(() => expect(screen.getByText('March 12, 2019')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Type')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('medication')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('food')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Provider')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Dr. Alicia629 Ureña88 MD')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Reaction')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Urticaria (Hives)')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Notes')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Sulfonamides')).toBeTruthy()) + await waitFor(() => { + const textElement = screen.queryByText( + 'We base this information on your current VA health records. If you have any questions, contact your health care team.', + ) + expect(textElement).toBeNull() + }) + }) + + it('initializes correctly for allergy with multiple notes', async () => { + const allergyWithNotes = { + ...defaultAllergy, + attributes: { + ...defaultAllergy.attributes, + reactions: reactions, + category: ['medication', 'food'], + notes: notes, + }, + } + + initializeTestInstance(allergyWithNotes) + await waitFor(() => expect(screen.getByText('March 12, 2019')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Type')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('medication')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('food')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Provider')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Dr. Alicia629 Ureña88 MD')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Reaction')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Urticaria (Hives)')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Notes')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Sulfonamides')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Patient has a family history of sulfa allergy')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Additional episode of hives')).toBeTruthy()) + await waitFor(() => { + const textElement = screen.queryByText( + 'We base this information on your current VA health records. If you have any questions, contact your health care team.', + ) + expect(textElement).toBeNull() + }) }) }) diff --git a/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx b/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx index 5d3a0dbd240..7c82bbd2285 100644 --- a/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx +++ b/VAMobile/src/screens/HealthScreen/Allergies/AllergyDetails/AllergyDetailsScreen.tsx @@ -6,10 +6,8 @@ import { StackScreenProps } from '@react-navigation/stack' import { every } from 'underscore' import { useAllergies } from 'api/allergies/getAllergies' -import { useAllergyLocation } from 'api/allergies/getAllergyLocation' import { Box, FeatureLandingTemplate, LoadingComponent, TextArea, TextView } from 'components' import { Events } from 'constants/analytics' -import { COVID19 } from 'constants/common' import { NAMESPACE } from 'constants/namespaces' import { a11yLabelVA } from 'utils/a11yLabel' import { logAnalyticsEvent } from 'utils/analytics' @@ -26,13 +24,8 @@ type AllergyDetailsScreenProps = StackScreenProps { - // logAnalyticsEvent(Events.vama_vaccine_details(allergy?.attributes?.groupName || '')) - // }, [dispatch, allergy]) + useEffect(() => { + logAnalyticsEvent(Events.vama_allergy_details()) + }, [dispatch, allergy]) if (!allergy) { return <> @@ -58,13 +51,10 @@ function AllergyDetailsScreen({ route, navigation }: AllergyDetailsScreenProps) ? t('allergies.allergyName', { name: allergy.attributes?.code?.text }) : placeHolder - const hasType = allergy.attributes?.category - // const displayType = hasType ? allergy.attributes?.category : placeHolder - const optionalFields = [ - hasType, - allergy.attributes?.notes, - // allergy.attributes?.reaction, + allergy.attributes?.category?.length, + allergy.attributes?.notes?.length, + allergy.attributes?.reactions?.length, allergy.attributes?.recorder, ] const isPartialData = !every(optionalFields) @@ -79,7 +69,6 @@ function AllergyDetailsScreen({ route, navigation }: AllergyDetailsScreenProps) {detailsLoading ? ( ) : ( - // {isPartialData && ( - - {t('vaccines.details.weBaseThis')} + + {t('health.details.weBaseThis')} )} diff --git a/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.test.tsx b/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.test.tsx index 38f0791cfcc..f34e842a851 100644 --- a/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.test.tsx +++ b/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.test.tsx @@ -6,86 +6,150 @@ import { waitFor } from '@testing-library/react-native' import * as api from 'store/api' import { context, mockNavProps, render, when } from 'testUtils' -import VaccineListScreen from './VaccineListScreen' +import AllergyListScreen from './AllergyListScreen' -context('VaccineListScreen', () => { - const vaccineData = [ +context('AllergyListScreen', () => { + const allergyData = [ { - id: 'I2-A7XD2XUPAZQ5H4Y5D6HJ352GEQ000000', - type: 'immunization', + id: '4-1abLZzsevfVnWK', + type: 'allergy_intolerance', attributes: { - cvxCode: 140, - date: '2009-03-19T12:24:55Z', - doseNumber: 'Booster', - doseSeries: 1, - groupName: 'FLU', - manufacturer: null, - note: 'Dose #45 of 101 of Influenza seasonal injectable preservative free vaccine administered.', - shortDescription: 'Influenza seasonal injectable preservative free', + resourceType: 'AllergyIntolerance', + type: 'allergy', + clinicalStatus: { + coding: [ + { + system: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical', + code: 'active', + }, + ], + }, + category: ['medication'], + code: { + coding: [ + { + system: 'http://hl7.org/fhir/ndfrt', + code: 'N0000008048', + display: 'Sulfonamides', + }, + ], + text: 'Sulfonamides', + }, + recordedDate: '2019-03-12T16:30:00Z', + patient: { + reference: 'https://sandbox-api.va.gov/services/fhir/v0/r4/Patient/1013956965V299908', + display: 'DAMASO SUPNICK', + }, + notes: [ + { + authorReference: { + reference: 'https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Nn79MgdlF9vV', + display: 'Dr. Alicia629 Ureña88 MD', + }, + time: '2019-03-12T16:30:00Z', + text: 'Sulfonamides', + }, + ], + recorder: { + reference: 'https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Nn79MgdlF9vV', + display: 'Dr. Alicia629 Ureña88 MD', + }, + reactions: [], }, }, { - id: 'I2-N7A6Q5AU6W5C6O4O7QEDZ3SJXM000000', - type: 'immunization', + id: '4-1wYbwqxtod74iS', + type: 'allergy_intolerance', attributes: { - cvxCode: 207, - date: '2020-12-18T12:24:55Z', - doseNumber: null, - doseSeries: null, - groupName: 'COVID-19', - manufacturer: null, - note: 'Dose #1 of 2 of COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose vaccine administered.', - shortDescription: 'COVID-19, mRNA, LNP-S, PF, 100 mcg/ 0.5 mL dose', + resourceType: 'AllergyIntolerance', + type: 'allergy', + clinicalStatus: { + coding: [ + { + system: 'http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical', + code: 'active', + }, + ], + }, + category: ['medication'], + code: { + coding: [], + text: 'penicillins', + }, + recordedDate: '2023-01-10T18:26:28Z', + patient: { + reference: 'https://sandbox-api.va.gov/services/fhir/v0/r4/Patient/1013956965V299908', + display: 'SUPNICK, DAMASO', + }, + notes: [], + recorder: { + reference: 'https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-X3BWnhAtrFa0Ko0R', + display: 'Nurse2, VA-HBPC', + }, + reactions: [ + { + substance: { + coding: [], + text: null, + }, + manifestation: [ + { + coding: [], + text: 'Urticaria (Hives)', + }, + ], + }, + ], }, }, ] const initializeTestInstance = () => { - render() + render() } it('initializes correctly', async () => { when(api.get as jest.Mock) - .calledWith('/v1/health/immunizations', expect.anything()) - .mockResolvedValue({ data: vaccineData }) + .calledWith('/v0/health/allergy-intolerances', expect.anything()) + .mockResolvedValue({ data: allergyData }) initializeTestInstance() - await waitFor(() => expect(screen.getByText('FLU vaccine')).toBeTruthy()) - await waitFor(() => expect(screen.getByText('COVID-19 vaccine')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('Sulfonamides allergy')).toBeTruthy()) + await waitFor(() => expect(screen.getByText('penicillins allergy')).toBeTruthy()) }) describe('when loading is set to true', () => { it('should show loading screen', () => { when(api.get as jest.Mock) - .calledWith('/v1/health/immunizations', expect.anything()) - .mockResolvedValue({ data: vaccineData }) + .calledWith('/v0/health/allergy-intolerances', expect.anything()) + .mockResolvedValue({ data: allergyData }) initializeTestInstance() - expect(screen.getByText('Loading your vaccine record...')).toBeTruthy() + expect(screen.getByText('Loading your allergy record...')).toBeTruthy() }) }) - describe('when there are no vaccines', () => { - it('should show no Vaccine Records', async () => { + describe('when there are no allergies', () => { + it('should show no Allergy Records', async () => { when(api.get as jest.Mock) - .calledWith('/v1/health/immunizations', expect.anything()) + .calledWith('/v0/health/allergy-intolerances', expect.anything()) .mockResolvedValue({ data: [] }) initializeTestInstance() await waitFor(() => expect( - screen.getByRole('heading', { name: "We couldn't find information about your VA vaccines" }), + screen.getByRole('heading', { name: "We couldn't find information about your VA allergies" }), ).toBeTruthy(), ) await waitFor(() => expect( screen.getByText( - "We're sorry. We update your vaccine records every 24 hours, but new records can take up to 36 hours to appear.", + "We're sorry. We update your allergy records every 24 hours, but new records can take up to 36 hours to appear.", ), ).toBeTruthy(), ) await waitFor(() => expect( screen.getByText( - "If you think your vaccine records should be here, call our MyVA411 main information line. We're here 24/7.", + "If you think your allergy records should be here, call our MyVA411 main information line. We're here 24/7.", ), ).toBeTruthy(), ) diff --git a/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx b/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx index c7eb17fc87e..ca4708a18da 100644 --- a/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx +++ b/VAMobile/src/screens/HealthScreen/Allergies/AllergyList/AllergyListScreen.tsx @@ -40,15 +40,13 @@ type AllergyListScreenProps = StackScreenProps { - const vaccineList = allergies?.data.slice((page - 1) * DEFAULT_PAGE_SIZE, page * DEFAULT_PAGE_SIZE) - setAllergiesToShow(vaccineList || []) + const allergyList = allergies?.data.slice((page - 1) * DEFAULT_PAGE_SIZE, page * DEFAULT_PAGE_SIZE) + setAllergiesToShow(allergyList || []) }, [allergies?.data, page]) const allergyButtons: Array = map(AllergiesToShow, (allergy, index) => { const textLines: Array = [ - { text: allergy.attributes?.code?.text ?? '', variant: 'MobileBodyBold' }, + { text: t('allergies.allergyName', { name: allergy.attributes?.code?.text }), variant: 'MobileBodyBold' }, { text: formatDateMMMMDDYYYY(allergy.attributes?.recordedDate || '') }, ] @@ -76,7 +74,7 @@ function AllergyListScreen({ navigation }: AllergyListScreenProps) { onPress: () => { navigateTo('AllergyDetails', { allergy: allergy }) }, - a11yHintText: t('vaccines.list.a11yHint'), + a11yHintText: t('allergies.list.a11yHint'), a11yValue: t('listPosition', { position: index + 1, total: allergies?.data.length }), testId: getA11yLabelText(textLines), } @@ -120,11 +118,11 @@ function AllergyListScreen({ navigation }: AllergyListScreenProps) { scrollViewProps={scrollViewProps}> {loading ? ( - ) : vaccineError || vaccinesInDowntime ? ( + ) : allergyError || allergiesInDowntime ? ( ) : allergies?.data?.length === 0 ? ( diff --git a/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.test.tsx b/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.test.tsx index 9671b22ee10..78bce625908 100644 --- a/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.test.tsx +++ b/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.test.tsx @@ -5,23 +5,23 @@ import { fireEvent, screen } from '@testing-library/react-native' import { context, render } from 'testUtils' -import NoVaccineRecords from './NoVaccineRecords' +import NoAllergyRecords from './NoAllergyRecords' context('NoVaccineRecords', () => { beforeEach(() => { - render() + render() }) it('initializes correctly', () => { - expect(screen.getByRole('heading', { name: "We couldn't find information about your VA vaccines" })).toBeTruthy() + expect(screen.getByRole('heading', { name: "We couldn't find information about your VA allergies" })).toBeTruthy() expect( screen.getByText( - "We're sorry. We update your vaccine records every 24 hours, but new records can take up to 36 hours to appear.", + "We're sorry. We update your allergy records every 24 hours, but new records can take up to 36 hours to appear.", ), ).toBeTruthy() expect( screen.getByText( - "If you think your vaccine records should be here, call our MyVA411 main information line. We're here 24/7.", + "If you think your allergy records should be here, call our MyVA411 main information line. We're here 24/7.", ), ).toBeTruthy() expect(screen.getByRole('link', { name: '800-698-2411' })).toBeTruthy() diff --git a/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.tsx b/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.tsx index 84919151f63..d789ade3411 100644 --- a/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.tsx +++ b/VAMobile/src/screens/HealthScreen/Allergies/NoAllergyRecords/NoAllergyRecords.tsx @@ -6,18 +6,18 @@ import { NAMESPACE } from 'constants/namespaces' import { a11yLabelVA } from 'utils/a11yLabel' import { displayedTextPhoneNumber } from 'utils/formattingUtils' -function NoVaccineRecords() { +function NoAllergyRecords() { const { t } = useTranslation(NAMESPACE.COMMON) return ( + header={t('noAllergyRecords.alert.title')} + headerA11yLabel={a11yLabelVA(t('noAllergyRecords.alert.title'))} + description={t('noAllergyRecords.alert.text.1')}> - {t('noVaccineRecords.alert.text.2')} + {t('noAllergyRecords.alert.text.2')} - {t('vaccines.details.provider')} + {t('health.details.provider')} {location && ( <> @@ -138,12 +138,12 @@ function VaccineDetailsScreen({ route, navigation }: VaccineDetailsScreenProps) - {t('vaccines.details.reaction')} + {t('health.details.reaction')} {vaccine.attributes?.reaction || placeHolder} - {t('vaccines.details.notes')} + {t('health.details.notes')} {isPartialData && ( - - {t('vaccines.details.weBaseThis')} + + {t('health.details.weBaseThis')} )} diff --git a/VAMobile/src/screens/HealthScreen/Vaccines/VaccineList/VaccineListScreen.tsx b/VAMobile/src/screens/HealthScreen/Vaccines/VaccineList/VaccineListScreen.tsx index 5a93d25ddb2..6ba0e1b31e3 100644 --- a/VAMobile/src/screens/HealthScreen/Vaccines/VaccineList/VaccineListScreen.tsx +++ b/VAMobile/src/screens/HealthScreen/Vaccines/VaccineList/VaccineListScreen.tsx @@ -48,8 +48,6 @@ function VaccineListScreen({ navigation }: VaccineListScreenProps) { refetch: refetchVaccines, } = useVaccines({ enabled: screenContentAllowed('WG_VaccineList') && !vaccinesInDowntime }) - console.log(JSON.stringify(vaccines, null, 3)) - const theme = useTheme() const { t } = useTranslation(NAMESPACE.COMMON) const navigateTo = useRouteNavigation() diff --git a/VAMobile/src/store/api/demo/mocks/allergies.json b/VAMobile/src/store/api/demo/mocks/allergies.json index 95e63c48acf..b9e9d3d1ca4 100644 --- a/VAMobile/src/store/api/demo/mocks/allergies.json +++ b/VAMobile/src/store/api/demo/mocks/allergies.json @@ -1,218 +1,462 @@ { - "/v1/health/allergy-intolerances": { - "1": { - "data": [ - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000000", - "type": "allergy_intolerance", - "attributes": { - "name": "Latex Allergy", - "type": "allergy", - "clinicalStatus": "active", - "recordedDate": "2021-01-14T09:30:21Z", - "notes": "Latex allergy", - "recorder": "DR. THOMAS359 REYNOLDS206 PHD", - "reaction": "Itchy Watery Eyes" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000001", - "type": "allergy_intolerance", - "attributes": { - "name": "Peanut", - "type": "allergy", - "clinicalStatus": "inactive", - "recordedDate": "2021-02-20T11:45:00Z", - "notes": "Peanut allergy", - "recorder": "DR. JANE DOE", - "reaction": "Hives" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000002", - "type": "allergy_intolerance", - "attributes": { - "name": "Pollen", - "type": "allergy", - "clinicalStatus": "active", - "recordedDate": "2021-03-10T14:20:00Z", - "notes": "Pollen allergy", - "recorder": "DR. JOHN SMITH", - "reaction": "Sneezing" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000003", - "type": "allergy_intolerance", - "attributes": { - "name": "Dust", - "type": "allergy", - "clinicalStatus": "inactive", - "recordedDate": "2021-04-15T09:00:00Z", - "notes": "Dust allergy", - "recorder": "DR. EMILY JOHNSON", - "reaction": "Coughing" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000004", - "type": "allergy_intolerance", - "attributes": { - "name": "Cat", - "type": "allergy", - "clinicalStatus": "active", - "recordedDate": "2021-05-20T10:30:00Z", - "notes": "Cat allergy", - "recorder": "DR. MICHAEL BROWN", - "reaction": "Itchy Skin" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000005", - "type": "allergy_intolerance", - "attributes": { - "name": "Dog", - "type": "allergy", - "clinicalStatus": "inactive", - "recordedDate": "2021-06-25T13:15:00Z", - "notes": "Dog allergy", - "recorder": "DR. LUCY WILLIAMS", - "reaction": "Runny Nose" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000006", - "type": "allergy_intolerance", - "attributes": { - "name": "Shellfish", - "type": "allergy", - "clinicalStatus": "active", - "recordedDate": "2021-07-30T15:45:00Z", - "notes": "Shellfish allergy", - "recorder": "DR. DAVID MARTIN", - "reaction": "Swelling" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000007", - "type": "allergy_intolerance", - "attributes": { - "name": "Milk", - "type": "allergy", - "clinicalStatus": "inactive", - "recordedDate": "2021-08-05T11:00:00Z", - "notes": "Milk allergy", - "recorder": "DR. ROBERT CLARK", - "reaction": "Stomach Pain" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000008", - "type": "allergy_intolerance", - "attributes": { - "name": "Egg", - "type": "allergy", - "clinicalStatus": "active", - "recordedDate": "2021-09-10T09:30:00Z", - "notes": "Egg allergy", - "recorder": "DR. PATRICIA MOORE", - "reaction": "Rash" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000009", - "type": "allergy_intolerance", - "attributes": { - "name": "Wheat", - "type": "allergy", - "clinicalStatus": "inactive", - "recordedDate": "2021-10-15T14:00:00Z", - "notes": "Wheat allergy", - "recorder": "DR. CHRISTOPHER TAYLOR", - "reaction": "Bloating" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000010", - "type": "allergy_intolerance", - "attributes": { - "name": "Soy", - "type": "allergy", - "clinicalStatus": "active", - "recordedDate": "2021-11-20T10:00:00Z", - "notes": "Soy allergy", - "recorder": "DR. MARY ANDERSON", - "reaction": "Nausea" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000011", - "type": "allergy_intolerance", - "attributes": { - "name": "Tree Nut", - "type": "allergy", - "clinicalStatus": "inactive", - "recordedDate": "2021-12-25T12:30:00Z", - "notes": "Tree nut allergy", - "recorder": "DR. JAMES LEE", - "reaction": "Anaphylaxis" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000012", - "type": "allergy_intolerance", - "attributes": { - "name": "Fish", - "type": "allergy", - "clinicalStatus": "active", - "recordedDate": "2022-01-30T09:45:00Z", - "notes": "Fish allergy", - "recorder": "DR. LINDA HARRIS", - "reaction": "Swelling" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000013", - "type": "allergy_intolerance", - "attributes": { - "name": "Insect Sting", - "type": "allergy", - "clinicalStatus": "inactive", - "recordedDate": "2022-02-15T11:15:00Z", - "notes": "Insect sting allergy", - "recorder": "DR. WILLIAM WALKER", - "reaction": "Swelling" - } - }, - { - "id": "I2-FY4N5GUAQ4IZQVQZUPDFN43S4A000014", - "type": "allergy_intolerance", - "attributes": { - "name": "Mold", - "type": "allergy", - "clinicalStatus": "active", - "recordedDate": "2022-03-20T13:00:00Z", - "notes": "Mold allergy", - "recorder": "DR. BARBARA SCOTT", - "reaction": "Sneezing" - } + "/v0/health/allergy-intolerances": { + "data": [ + { + "id": "4-1abLZzsevfVnWK", + "type": "allergy_intolerance", + "attributes": { + "resourceType": "AllergyIntolerance", + "type": "allergy", + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", + "code": "active" + } + ] + }, + "category": ["medication"], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008048", + "display": "Sulfonamides" + } + ], + "text": "Sulfonamides" + }, + "recordedDate": "2019-03-12T16:30:00Z", + "patient": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Patient/1013956965V299908", + "display": "DAMASO SUPNICK" + }, + "notes": [ + { + "authorReference": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Nn79MgdlF9vV", + "display": "Dr. Alicia629 Ureña88 MD" + }, + "time": "2019-03-12T16:30:00Z", + "text": "Sulfonamides" + } + ], + "recorder": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Nn79MgdlF9vV", + "display": "Dr. Alicia629 Ureña88 MD" + }, + "reactions": [] } - ], - "meta": { - "pagination": { - "currentPage": 1, - "perPage": 10, - "totalPages": 2, - "totalEntries": 15 + }, + { + "id": "4-1wYbwqxtod74iS", + "type": "allergy_intolerance", + "attributes": { + "resourceType": "AllergyIntolerance", + "type": "allergy", + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", + "code": "active" + } + ] + }, + "category": ["medication", "biologic"], + "code": { + "coding": [], + "text": "penicillins" + }, + "recordedDate": "2023-01-10T18:26:28Z", + "patient": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Patient/1013956965V299908", + "display": "SUPNICK, DAMASO" + }, + "notes": [], + "recorder": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-X3BWnhAtrFa0Ko0R", + "display": "Nurse2, VA-HBPC" + }, + "reactions": [ + { + "substance": { + "coding": [], + "text": "penicillins" + }, + "manifestation": [ + { + "coding": [], + "text": "Urticaria (Hives)" + } + ] + }, + { + "substance": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008049", + "display": "penicillins" + } + ], + "text": "penicillins" + }, + "manifestation": [ + { + "coding": [], + "text": "Anaphylaxis" + } + ] + } + ] + } + }, + { + "id": "4-2cD3F4G5H6I7J8K", + "type": "allergy_intolerance", + "attributes": { + "resourceType": "AllergyIntolerance", + "type": "allergy", + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", + "code": "active" + } + ] + }, + "category": ["food"], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008049", + "display": "Peanuts" + } + ], + "text": "Peanuts" + }, + "recordedDate": "2022-05-15T10:00:00Z", + "patient": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Patient/1013956965V299908", + "display": "DAMASO SUPNICK" + }, + "notes": [ + { + "authorReference": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Y7Z8X9W0V1U2T3S", + "display": "Dr. John Doe MD" + }, + "time": "2022-05-15T10:00:00Z", + "text": "Peanuts" + } + ], + "recorder": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Y7Z8X9W0V1U2T3S", + "display": "Dr. John Doe MD" + }, + "reactions": [ + { + "substance": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008049", + "display": "Peanuts" + } + ], + "text": "Peanuts" + }, + "manifestation": [ + { + "coding": [], + "text": "Anaphylaxis" + } + ] + } + ] + } + }, + { + "id": "4-3eF5G6H7I8J9K0L", + "type": "allergy_intolerance", + "attributes": { + "resourceType": "AllergyIntolerance", + "type": "allergy", + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", + "code": "active" + } + ] + }, + "category": ["environment"], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008050", + "display": "Pollen" + } + ], + "text": "Pollen" + }, + "recordedDate": "2021-04-10T09:00:00Z", + "patient": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Patient/1013956965V299908", + "display": "DAMASO SUPNICK" + }, + "notes": [ + { + "authorReference": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Z1X2C3V4B5N6M7L", + "display": "Dr. Jane Smith MD" + }, + "time": "2021-04-10T09:00:00Z", + "text": "Pollen" + } + ], + "recorder": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-Z1X2C3V4B5N6M7L", + "display": "Dr. Jane Smith MD" + }, + "reactions": [ + { + "substance": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008050", + "display": "Pollen" + } + ], + "text": "Pollen" + }, + "manifestation": [ + { + "coding": [], + "text": "Sneezing" + } + ] + } + ] } }, - "links": { - "self": "https://staging-api.va.gov/mobile/v1/health/allergy-intolerances?useCache=true&page[size]=10&page[number]=1", - "first": "https://staging-api.va.gov/mobile/v1/health/allergy-intolerances?useCache=true&page[size]=10&page[number]=1", - "prev": null, - "next": "https://staging-api.va.gov/mobile/v1/health/allergy-intolerances?useCache=true&page[size]=10&page[number]=2", - "last": "https://staging-api.va.gov/mobile/v1/health/allergy-intolerances?useCache=true&page[size]=10&page[number]=2" + { + "id": "4-4gH7I8J9K0L1M2N", + "type": "allergy_intolerance", + "attributes": { + "resourceType": "AllergyIntolerance", + "type": "allergy", + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", + "code": "active" + } + ] + }, + "category": ["biologic"], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008051", + "display": "Latex" + } + ], + "text": "Latex" + }, + "recordedDate": "2020-08-20T14:30:00Z", + "patient": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Patient/1013956965V299908", + "display": "DAMASO SUPNICK" + }, + "notes": [ + { + "authorReference": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-A1B2C3D4E5F6G7H", + "display": "Dr. Emily Johnson MD" + }, + "time": "2020-08-20T14:30:00Z", + "text": "Latex" + } + ], + "recorder": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-A1B2C3D4E5F6G7H", + "display": "Dr. Emily Johnson MD" + }, + "reactions": [ + { + "substance": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008051", + "display": "Latex" + } + ], + "text": "Latex" + }, + "manifestation": [ + { + "coding": [], + "text": "Rash" + } + ] + } + ] + } + }, + { + "id": "4-5iJ9K0L1M2N3O4P", + "type": "allergy_intolerance", + "attributes": { + "resourceType": "AllergyIntolerance", + "type": "allergy", + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", + "code": "active" + } + ] + }, + "category": ["food"], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008052", + "display": "Shellfish" + } + ], + "text": "Shellfish" + }, + "recordedDate": "2021-11-05T11:15:00Z", + "patient": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Patient/1013956965V299908", + "display": "DAMASO SUPNICK" + }, + "notes": [ + { + "authorReference": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-I1J2K3L4M5N6O7P", + "display": "Dr. Michael Brown MD" + }, + "time": "2021-11-05T11:15:00Z", + "text": "Shellfish" + } + ], + "recorder": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-I1J2K3L4M5N6O7P", + "display": "Dr. Michael Brown MD" + }, + "reactions": [ + { + "substance": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008052", + "display": "Shellfish" + } + ], + "text": "Shellfish" + }, + "manifestation": [ + { + "coding": [], + "text": "Swelling" + } + ] + } + ] + } + }, + { + "id": "4-6kL1M2N3O4P5Q6R", + "type": "allergy_intolerance", + "attributes": { + "resourceType": "AllergyIntolerance", + "type": "allergy", + "clinicalStatus": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/allergyintolerance-clinical", + "code": "active" + } + ] + }, + "category": ["environment"], + "code": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008053", + "display": "Dust" + } + ], + "text": "Dust" + }, + "recordedDate": "2020-12-12T08:45:00Z", + "patient": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Patient/1013956965V299908", + "display": "DAMASO SUPNICK" + }, + "notes": [ + { + "authorReference": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-K1L2M3N4O5P6Q7R", + "display": "Dr. Sarah Lee MD" + }, + "time": "2020-12-12T08:45:00Z", + "text": "Dust" + }, + { + "authorReference": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-K1L2M3N4O5P6Q7R", + "display": "Dr. Sarah Lee MD" + }, + "time": "2020-12-12T08:45:00Z", + "text": "More Dust" + }, + { + "authorReference": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-K1L2M3N4O5P6Q7R", + "display": "Dr. Sarah Lee MD" + }, + "time": "2020-12-12T08:45:00Z", + "text": "Even More Dust" + } + ], + "recorder": { + "reference": "https://sandbox-api.va.gov/services/fhir/v0/r4/Practitioner/4-K1L2M3N4O5P6Q7R", + "display": "Dr. Sarah Lee MD" + }, + "reactions": [ + { + "substance": { + "coding": [ + { + "system": "http://hl7.org/fhir/ndfrt", + "code": "N0000008053", + "display": "Dust" + } + ], + "text": "Dust" + }, + "manifestation": [ + { + "coding": [], + "text": "Coughing" + } + ] + } + ] + } } - } + ] } } diff --git a/VAMobile/src/store/api/types/Errors.ts b/VAMobile/src/store/api/types/Errors.ts index bc9b4ceb7f3..0452453f04b 100644 --- a/VAMobile/src/store/api/types/Errors.ts +++ b/VAMobile/src/store/api/types/Errors.ts @@ -39,6 +39,7 @@ export type DowntimeFeatureType = | 'direct_deposit_benefits' | 'disability_rating' | 'immunizations' + | 'allergies' | 'letters_and_documents' | 'secure_messaging' | 'appointments' @@ -54,6 +55,7 @@ export const DowntimeFeatureTypeConstants: { directDepositBenefits: DowntimeFeatureType disabilityRating: DowntimeFeatureType immunizations: DowntimeFeatureType + allergies: DowntimeFeatureType letters: DowntimeFeatureType secureMessaging: DowntimeFeatureType appointments: DowntimeFeatureType @@ -68,6 +70,7 @@ export const DowntimeFeatureTypeConstants: { directDepositBenefits: 'direct_deposit_benefits', disabilityRating: 'disability_rating', immunizations: 'immunizations', + allergies: 'allergies', letters: 'letters_and_documents', secureMessaging: 'secure_messaging', appointments: 'appointments', @@ -86,6 +89,7 @@ export const ScreenIDToFeatureName = { [ScreenIDTypesConstants.DIRECT_DEPOSIT_SCREEN_ID]: 'Direct Deposit', [ScreenIDTypesConstants.DISABILITY_RATING_SCREEN_ID]: 'Disability Rating', [ScreenIDTypesConstants.VACCINE_LIST_SCREEN_ID]: 'VA Vaccines', + [ScreenIDTypesConstants.ALLERGY_LIST_SCREEN_ID]: 'VA Allergies', [ScreenIDTypesConstants.MILITARY_INFORMATION_SCREEN_ID]: 'Military Service History', [ScreenIDTypesConstants.PERSONAL_INFORMATION_SCREEN_ID]: 'Personal Information', [ScreenIDTypesConstants.CONTACT_INFORMATION_SCREEN_ID]: 'Personal Information', @@ -106,6 +110,7 @@ export const ScreenIDToDowntimeFeatures = { [ScreenIDTypesConstants.DIRECT_DEPOSIT_SCREEN_ID]: [DowntimeFeatureTypeConstants.directDepositBenefits], [ScreenIDTypesConstants.DISABILITY_RATING_SCREEN_ID]: [DowntimeFeatureTypeConstants.disabilityRating], [ScreenIDTypesConstants.VACCINE_LIST_SCREEN_ID]: [DowntimeFeatureTypeConstants.immunizations], + [ScreenIDTypesConstants.ALLERGY_LIST_SCREEN_ID]: [DowntimeFeatureTypeConstants.allergies], [ScreenIDTypesConstants.MILITARY_INFORMATION_SCREEN_ID]: [DowntimeFeatureTypeConstants.militaryServiceHistory], [ScreenIDTypesConstants.PERSONAL_INFORMATION_SCREEN_ID]: [DowntimeFeatureTypeConstants.userProfileUpdate], [ScreenIDTypesConstants.CONTACT_INFORMATION_SCREEN_ID]: [DowntimeFeatureTypeConstants.userProfileUpdate], diff --git a/VAMobile/src/store/api/types/Screens.ts b/VAMobile/src/store/api/types/Screens.ts index 49fb1487c5c..bb7a28c55ec 100644 --- a/VAMobile/src/store/api/types/Screens.ts +++ b/VAMobile/src/store/api/types/Screens.ts @@ -34,6 +34,7 @@ export const ScreenIDTypesConstants: { HOME_SCREEN_ID: ScreenIDTypes DISABILITY_RATING_SCREEN_ID: ScreenIDTypes VACCINE_LIST_SCREEN_ID: ScreenIDTypes + ALLERGY_LIST_SCREEN_ID: ScreenIDTypes PAYMENTS_SCREEN_ID: ScreenIDTypes APPOINTMENT_REQUEST_TYPE_OF_CARE_SCREEN_ID: ScreenIDTypes APPOINTMENT_REQUEST_SUB_TYPE_OF_CARE_SCREEN_ID: ScreenIDTypes @@ -81,6 +82,7 @@ export const ScreenIDTypesConstants: { HOME_SCREEN_ID: 'HOME_SCREEN_ID', DISABILITY_RATING_SCREEN_ID: 'DISABILITY_RATING_SCREEN_ID', VACCINE_LIST_SCREEN_ID: 'VACCINE_LIST_SCREEN_ID', + ALLERGY_LIST_SCREEN_ID: 'ALLERGY_LIST_SCREEN_ID', PAYMENTS_SCREEN_ID: 'PAYMENTS_SCREEN_ID', APPOINTMENT_REQUEST_TYPE_OF_CARE_SCREEN_ID: 'APPOINTMENT_REQUEST_TYPE_OF_CARE_SCREEN_ID', APPOINTMENT_REQUEST_SUB_TYPE_OF_CARE_SCREEN_ID: 'APPOINTMENT_REQUEST_SUB_TYPE_OF_CARE_SCREEN_ID', @@ -130,6 +132,7 @@ export type ScreenIDTypes = | 'HOME_SCREEN_ID' | 'DISABILITY_RATING_SCREEN_ID' | 'VACCINE_LIST_SCREEN_ID' + | 'ALLERGY_LIST_SCREEN_ID' | 'PAYMENTS_SCREEN_ID' | 'APPOINTMENT_REQUEST_TYPE_OF_CARE_SCREEN_ID' | 'APPOINTMENT_REQUEST_SUB_TYPE_OF_CARE_SCREEN_ID' diff --git a/VAMobile/src/translations/en/common.json b/VAMobile/src/translations/en/common.json index 8b053d17067..bca48256425 100644 --- a/VAMobile/src/translations/en/common.json +++ b/VAMobile/src/translations/en/common.json @@ -34,6 +34,7 @@ "allergies.loading": "Loading your allergy record...", "allergies.allergyName": "{{name}} allergy", "allergies.details.loading": "Loading your allergy details...", + "allergies.list.a11yHint": "Review your V-A allergy record", "and": "and", "appealDetails.agencyJurisdiction": "Agency of Original Jurisdiction", "appealDetails.amaNod": "Board of Veterans’ Appeals received your appeal", @@ -799,6 +800,10 @@ "goToVAGov": "Go to VA.gov", "health.activity.error": "We can't get some of your information right now. Health activity may not be accurate. Check back later.", "health.activity.downtime": "We're working on the mobile app. Health activity may not be accurate. Check back later.", + "health.details.notes": "Notes", + "health.details.provider": "Provider", + "health.details.reaction": "Reaction", + "health.details.weBaseThis": "We base this information on your current VA health records. If you have any questions, contact your health care team.", "health.title": "Health", "help": "Help", "healthHelp.checkFacility": "Check if your care team uses My VA Health", @@ -959,6 +964,9 @@ "next": "Next", "no": "No", "noActivity": "There's no activity to show.", + "noAllergyRecords.alert.text.1": "We're sorry. We update your allergy records every 24 hours, but new records can take up to 36 hours to appear.", + "noAllergyRecords.alert.text.2": "If you think your allergy records should be here, call our MyVA411 main information line. We're here 24/7.", + "noAllergyRecords.alert.title": "We couldn't find information about your VA allergies", "noAppointments.visitVA": "Visit VA.gov", "noAppointments.youCanSchedule": "You can schedule an appointment on VA.gov, or you can call your VA medical center to schedule an appointment.", "noAppointments.youDontHave": "You don’t have any appointments", @@ -1461,13 +1469,9 @@ "vaccines.details.address": "{{city}}, {{state}} {{zip}}", "vaccines.details.loading": "Loading your vaccine details...", "vaccines.details.manufacturer": "Manufacturer", - "vaccines.details.notes": "Notes", - "vaccines.details.provider": "Provider", - "vaccines.details.reaction": "Reaction", "vaccines.details.series": "Series status", "vaccines.details.series.display": "{{doseNumber}} of {{seriesDoses}}", "vaccines.details.typeAndDosage": "Type and dosage", - "vaccines.details.weBaseThis": "We base this information on your current VA health records. If you have any questions, contact your health care team.", "vaccines.list.a11yHint": "Review your V-A vaccine record", "vaccines.loading": "Loading your vaccine record...", "vaccines.vaccineName": "{{name}} vaccine", diff --git a/VAMobile/src/utils/errors.ts b/VAMobile/src/utils/errors.ts index 24a73d2f442..2177c3b83b8 100644 --- a/VAMobile/src/utils/errors.ts +++ b/VAMobile/src/utils/errors.ts @@ -40,6 +40,8 @@ export const getCommonErrorFromAPIError = (error: APIError, screenID?: ScreenIDT return CommonErrorTypesConstants.APP_LEVEL_ERROR_HEALTH_LOAD } else if (screenID === ScreenIDTypesConstants.VACCINE_LIST_SCREEN_ID && error.status && error.status >= 500) { return CommonErrorTypesConstants.APP_LEVEL_ERROR_VACCINE + } else if (screenID === ScreenIDTypesConstants.ALLERGY_LIST_SCREEN_ID && error.status && error.status >= 500) { + return CommonErrorTypesConstants.APP_LEVEL_ERROR_VACCINE } else if (screenID === ScreenIDTypesConstants.DISABILITY_RATING_SCREEN_ID && error.status && error.status >= 500) { return CommonErrorTypesConstants.APP_LEVEL_ERROR_DISABILITY_RATING } else if (screenID === ScreenIDTypesConstants.APPOINTMENTS_SCREEN_ID && error.status && error.status >= 500) { diff --git a/VAMobile/src/utils/waygateConfig.ts b/VAMobile/src/utils/waygateConfig.ts index eeb1a733b96..536a177be69 100644 --- a/VAMobile/src/utils/waygateConfig.ts +++ b/VAMobile/src/utils/waygateConfig.ts @@ -60,6 +60,8 @@ export type WaygateToggleType = | 'WG_UpcomingAppointmentDetails' | 'WG_VaccineDetails' | 'WG_VaccineList' + | 'WG_AllergyDetails' + | 'WG_AllergyList' | 'WG_ViewMessage' | 'WG_PrepareForVideoVisit' | 'WG_StartNewMessage' @@ -142,6 +144,8 @@ type WaygateToggleValues = { WG_UpcomingAppointmentDetails: Waygate WG_VaccineDetails: Waygate WG_VaccineList: Waygate + WG_AllergyDetails: Waygate + WG_AllergyList: Waygate WG_ViewMessage: Waygate WG_PrepareForVideoVisit: Waygate WG_SubmitEvidence: Waygate @@ -233,6 +237,8 @@ export let waygateConfig: WaygateToggleValues = { WG_UpcomingAppointmentDetails: { ...waygateDefault }, WG_VaccineDetails: { ...waygateDefault }, WG_VaccineList: { ...waygateDefault }, + WG_AllergyDetails: { ...waygateDefault }, + WG_AllergyList: { ...waygateDefault }, WG_ViewMessage: { ...waygateDefault }, WG_PrepareForVideoVisit: { ...waygateDefault }, WG_StartNewMessage: { ...waygateDefault },