diff --git a/VAMobile/global.d.ts b/VAMobile/global.d.ts index beff388ee90..84fbcf98898 100644 --- a/VAMobile/global.d.ts +++ b/VAMobile/global.d.ts @@ -19,25 +19,6 @@ declare module 'react-native-keyboard-manager' { export function setEnableAutoToolbar(arg: boolean): void } -// this makes it posible to call the snackbar from outside react components and also types the data object -type ToastOptions = import('react-native-toast-notifications/lib/typescript/toast').ToastOptions -type ToastType = import('react-native-toast-notifications').ToastType - -type modifyToastOptions = Omit & { - data?: { - onActionPressed?: () => void - isError?: boolean - actionBtnText?: string - isUndo?: boolean - } -} - -type modifyToastType = Omit & { - show: (message: string | JSX.Element, toastOptions?: modifyToastOptions | undefined) => string -} - -declare var snackBar: modifyToastType - declare var global: any declare var process: any diff --git a/VAMobile/ios/Podfile.lock b/VAMobile/ios/Podfile.lock index 822cbb93c65..39e1f3a924b 100644 --- a/VAMobile/ios/Podfile.lock +++ b/VAMobile/ios/Podfile.lock @@ -1425,7 +1425,7 @@ PODS: - React-Core - react-native-safe-area-context (4.10.9): - React-Core - - react-native-webview (13.10.4): + - react-native-webview (13.12.3): - DoubleConversion - glog - hermes-engine @@ -1742,7 +1742,7 @@ PODS: - RNFBApp - RNFileViewer (2.1.5): - React-Core - - RNGestureHandler (2.18.1): + - RNGestureHandler (2.21.1): - DoubleConversion - glog - hermes-engine @@ -1763,9 +1763,28 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - RNKeychain (8.2.0): + - RNKeychain (9.1.0): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety - React-Core - - RNLocalize (3.2.1): + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga + - RNLocalize (3.3.0): - React-Core - RNReactNativeHapticFeedback (2.3.3): - DoubleConversion @@ -2121,7 +2140,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 4cb898d0bf20404aab1850c656dcea009429d6c1 - DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953 + DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 FBLazyVector: 7b438dceb9f904bd85ca3c31d64cce32a035472b Firebase: 10c8cb12fb7ad2ae0c09ffc86cd9c1ab392a0031 FirebaseABTesting: d87f56707159bae64e269757a6e963d490f2eebe @@ -2137,7 +2156,7 @@ SPEC CHECKSUMS: FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc FirebaseSharedSwift: 20530f495084b8d840f78a100d8c5ee613375f6e fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120 - glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2 + glog: 69ef571f3de08433d766d614c73a9838a06bf7eb GoogleAppMeasurement: bb3c564c3efb933136af0e94899e0a46167466a8 GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 @@ -2184,7 +2203,7 @@ SPEC CHECKSUMS: react-native-image-picker: 2fbbafdae7a7c6db9d25df2f2b1db4442d2ca2ad react-native-notifications: 4601a5a8db4ced6ae7cfc43b44d35fe437ac50c4 react-native-safe-area-context: ab8f4a3d8180913bd78ae75dd599c94cce3d5e9a - react-native-webview: fbafd1591cd068bd599f0d1afb0ddc19718908fa + react-native-webview: 926d2665cf3196e39c4449a72d136d0a53b9df8a React-nativeconfig: 4a9543185905fe41014c06776bf126083795aed9 React-NativeModulesApple: 0506da59fc40d2e1e6e12a233db5e81c46face27 React-perflogger: 3bbb82f18e9ac29a1a6931568e99d6305ef4403b @@ -2221,17 +2240,17 @@ SPEC CHECKSUMS: RNFBPerf: 9cd7430cb90e4b8aebcd86312f1eb3aae28bd0e7 RNFBRemoteConfig: bfb9f6a04a0269038a352d8386e5c77f4ff98125 RNFileViewer: ce7ca3ac370e18554d35d6355cffd7c30437c592 - RNGestureHandler: 939f21fabf5d45a725c0bf175eb819dd25cf2e70 - RNKeychain: bfe3d12bf4620fe488771c414530bf16e88f3678 - RNLocalize: 4f22418187ecd5ca693231093ff1d912d1b3c9bc + RNGestureHandler: be97a346e113ca17a42658671b80e4f98b5e5d74 + RNKeychain: 958a200b26c2df5036222105550290ac0ed98c90 + RNLocalize: 298e85ce16540a11de40c1a588ead39fc5e9a072 RNReactNativeHapticFeedback: 0d591ea1e150f36cb96d868d4e8d77272243d78a RNScreens: 19719a9c326e925498ac3b2d35c4e50fe87afc06 RNSVG: 963a95f1f5d512a13d11ffd50d351c87fb5c6890 SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3 SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380 SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d - Yoga: 1354c027ab07c7736f99a3bef16172d6f1b12b47 + Yoga: 4ef80d96a5534f0e01b3055f17d1e19a9fc61b63 PODFILE CHECKSUM: 528e5ac3a06c35c8645d8271610e36fdcca33735 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/VAMobile/ios/VAMobile.xcodeproj/project.pbxproj b/VAMobile/ios/VAMobile.xcodeproj/project.pbxproj index f2407c8c94f..3c3265b20ed 100644 --- a/VAMobile/ios/VAMobile.xcodeproj/project.pbxproj +++ b/VAMobile/ios/VAMobile.xcodeproj/project.pbxproj @@ -495,6 +495,7 @@ "${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/react-native-blob-util/ReactNativeBlobUtilPrivacyInfo.bundle", ); name = "[CP] Copy Pods Resources"; @@ -512,6 +513,7 @@ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ReactNativeBlobUtilPrivacyInfo.bundle", ); runOnlyForDeploymentPostprocessing = 0; @@ -552,6 +554,7 @@ "${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/glog/glog_privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/react-native-blob-util/ReactNativeBlobUtilPrivacyInfo.bundle", ); name = "[CP] Copy Pods Resources"; @@ -569,6 +572,7 @@ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/glog_privacy.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ReactNativeBlobUtilPrivacyInfo.bundle", ); runOnlyForDeploymentPostprocessing = 0; diff --git a/VAMobile/jest/testSetup.ts b/VAMobile/jest/testSetup.ts index adaa5e09744..177a9f4c5ba 100644 --- a/VAMobile/jest/testSetup.ts +++ b/VAMobile/jest/testSetup.ts @@ -271,11 +271,6 @@ globalAny.FormData = () => ({ append: jest.fn(), }) -globalAny.snackBar = { - show: jest.fn(), - hideAll: jest.fn(), -} - jest.mock('@react-native-firebase/perf', () => { return jest.fn(() => { return { diff --git a/VAMobile/patches/@department-of-veterans-affairs+mobile-component-library+0.27.1.patch b/VAMobile/patches/@department-of-veterans-affairs+mobile-component-library+0.27.1.patch new file mode 100644 index 00000000000..569e9bd767c --- /dev/null +++ b/VAMobile/patches/@department-of-veterans-affairs+mobile-component-library+0.27.1.patch @@ -0,0 +1,43 @@ +diff --git a/node_modules/@department-of-veterans-affairs/mobile-component-library/src/components/Snackbar/useSnackbar.tsx b/node_modules/@department-of-veterans-affairs/mobile-component-library/src/components/Snackbar/useSnackbar.tsx +index 2e5c464..a696fa9 100644 +--- a/node_modules/@department-of-veterans-affairs/mobile-component-library/src/components/Snackbar/useSnackbar.tsx ++++ b/node_modules/@department-of-veterans-affairs/mobile-component-library/src/components/Snackbar/useSnackbar.tsx +@@ -1,4 +1,4 @@ +-import { useContext } from 'react' ++import { useCallback, useContext, useMemo } from 'react' + + import * as Toast from 'react-native-toast-notifications' + +@@ -22,9 +22,9 @@ export function useSnackbar() { + throw new Error('useSnackbar must be used within a SnackbarProvider') + } + +- const show = (message: string, snackbarOptions?: SnackbarOptions) => { +- const { offset, setOffset } = context ++ const { offset, setOffset } = context + ++ const show = useCallback((message: string, snackbarOptions?: SnackbarOptions) => { + const customOffset = snackbarOptions?.offset + + // Custom offset if provided, else default +@@ -43,11 +43,13 @@ export function useSnackbar() { + + toast.hideAll() + toast.show(message, { data: snackbarOptions, duration }) +- } +- +- return { +- show, +- hide: toast.hideAll, +- isOpen: toast.isOpen, +- } ++ }, [defaultOffset, offset, screenReaderEnabled, setOffset, toast]) ++ ++ return useMemo( ++ () => ({ ++ show, ++ hide: toast.hideAll, ++ isOpen: toast.isOpen, ++ }), [show, toast.hideAll, toast.isOpen] ++ ) + } diff --git a/VAMobile/src/App.tsx b/VAMobile/src/App.tsx index 49801b8d146..21b0b0bc349 100644 --- a/VAMobile/src/App.tsx +++ b/VAMobile/src/App.tsx @@ -6,9 +6,6 @@ import 'react-native-gesture-handler' import KeyboardManager from 'react-native-keyboard-manager' import { SafeAreaProvider } from 'react-native-safe-area-context' import { enableScreens } from 'react-native-screens' -import Toast from 'react-native-toast-notifications' -import ToastContainer from 'react-native-toast-notifications' -import { ToastProps } from 'react-native-toast-notifications/lib/typescript/toast' import { Provider, useSelector } from 'react-redux' import analytics from '@react-native-firebase/analytics' @@ -19,7 +16,11 @@ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native' import { createStackNavigator } from '@react-navigation/stack' -import { useIsScreenReaderEnabled } from '@department-of-veterans-affairs/mobile-component-library' +import { + SnackbarProvider, + useIsScreenReaderEnabled, + useSnackbar, +} from '@department-of-veterans-affairs/mobile-component-library' import { ActionSheetProvider, connectActionSheet } from '@expo/react-native-action-sheet' import { QueryClientProvider } from '@tanstack/react-query' import { ThemeProvider } from 'styled-components' @@ -27,9 +28,7 @@ import { ThemeProvider } from 'styled-components' import queryClient from 'api/queryClient' import { ClaimData } from 'api/types' import { NavigationTabBar } from 'components' -import SnackBar from 'components/SnackBar' -import { CloseSnackbarOnNavigation, EnvironmentTypesConstants } from 'constants/common' -import { SnackBarConstants } from 'constants/common' +import { EnvironmentTypesConstants } from 'constants/common' import { linking } from 'constants/linking' import { NAMESPACE } from 'constants/namespaces' import { FULLSCREEN_SUBTASK_OPTIONS, LARGE_PANEL_OPTIONS } from 'constants/screens' @@ -61,7 +60,6 @@ import { sendUsesScreenReaderAnalytics, } from 'store/slices/accessibilitySlice' import { fetchAndActivateRemoteConfig } from 'store/slices/settingsSlice' -import { SnackBarState } from 'store/slices/snackBarSlice' import { useColorScheme } from 'styles/themes/colorScheme' import theme, { getTheme, setColorScheme } from 'styles/themes/standardTheme' import getEnv from 'utils/env' @@ -187,7 +185,9 @@ function MainApp() { barStyle={theme.mode === 'dark' ? 'light-content' : 'dark-content'} backgroundColor={currentTheme.colors.background.main} /> - + + + @@ -218,7 +218,6 @@ export function AuthGuard() { const { fontScale, isVoiceOverTalkBackRunning } = useSelector( (state) => state.accessibility, ) - const { bottomOffset } = useSelector((state) => state.snackBar) const { firebaseDebugMode } = useSelector((state) => state.analytics) const { t } = useTranslation(NAMESPACE.COMMON) const headerStyles = useHeaderStyles() @@ -229,14 +228,6 @@ export function AuthGuard() { const fontScaleFunction = useFontScale() const sendUsesLargeTextScal = fontScaleFunction(30) - const snackBarProps: Partial = { - duration: SnackBarConstants.duration, - animationDuration: SnackBarConstants.animationDuration, - renderType: { - custom_snackbar: (toast) => , - }, - swipeEnabled: false, - } useEffect(() => { // Listener for the current app state, updates the font scale when app state is active and the font scale has changed const sub = AppState.addEventListener('change', (newState: AppStateStatus): void => @@ -381,16 +372,7 @@ export function AuthGuard() { ) } else if (loggedIn) { - content = ( - <> - - ((global.snackBar as ToastContainer | null) = ref)} - offsetBottom={bottomOffset} - /> - - ) + content = } else { content = ( @@ -428,6 +410,7 @@ export function AppTabs() { } export function AuthedApp() { + const snackbar = useSnackbar() const headerStyles = useHeaderStyles() const { initialUrl } = useNotificationContext() const homeScreens = getHomeScreens() @@ -451,11 +434,11 @@ export function AuthedApp() { screenListeners={{ transitionStart: (e) => { if (e.data.closing) { - CloseSnackbarOnNavigation(e.target) + snackbar.hide() } }, - blur: (e) => { - CloseSnackbarOnNavigation(e.target) + blur: () => { + snackbar.hide() }, }}> = ({ cancelTestID, confirmTestID, }) => { + const snackbar = useSnackbar() const [modalVisible, setModalVisible] = useState(false) const theme = useTheme() const { t } = useTranslation() @@ -121,12 +122,9 @@ const VAModalPicker: FC = ({ if (!disabled) { setIsFocused(true) setModalVisible(true) - if (!snackBar) { - logAnalyticsEvent(Events.vama_snackbar_null('VAModalPicker')) - } - snackBar?.hideAll() + snackbar.hide() } - }, [disabled, labelKey, testID, t]) + }, [disabled, labelKey, snackbar, testID, t]) useEffect(() => { showModalByDefault && showModal() diff --git a/VAMobile/src/components/SnackBar.tsx b/VAMobile/src/components/SnackBar.tsx deleted file mode 100644 index 7bb9178fb23..00000000000 --- a/VAMobile/src/components/SnackBar.tsx +++ /dev/null @@ -1,184 +0,0 @@ -import React, { FC } from 'react' -import { useTranslation } from 'react-i18next' -import { StyleProp, TouchableOpacity, View, ViewStyle, useWindowDimensions } from 'react-native' -import { HapticFeedbackTypes } from 'react-native-haptic-feedback' -import { SafeAreaView } from 'react-native-safe-area-context' -import { ToastProps } from 'react-native-toast-notifications/lib/typescript/toast' - -import { useFocusEffect } from '@react-navigation/native' - -import { Box, TextViewProps, VAScrollView } from 'components' -import { NAMESPACE } from 'constants/namespaces' -import { triggerHaptic } from 'utils/haptics' -import { useAccessibilityFocus, useTheme } from 'utils/hooks' - -import { BoxProps } from './Box' -import TextView from './TextView' -import VAIcon, { VAIconProps } from './VAIcon' - -export type SnackbarMessages = { - successMsg: string - errorMsg: string - undoMsg?: string - undoErrorMsg?: string -} - -/** - * Common snackbar component. This component is wrapped by the react-native-toast-notification library. - */ -const SnackBar: FC = (toast) => { - const { message, data } = toast - const { onActionPressed, isError, actionBtnText, isUndo } = data || {} - const { colors: themeColor } = useTheme() - const [focusRef, setFocus] = useAccessibilityFocus() - const { t } = useTranslation(NAMESPACE.COMMON) - const windowHeight = useWindowDimensions().height - const fontScale = useWindowDimensions().fontScale - - useFocusEffect(setFocus) - - const safeViewStyle: StyleProp = { - flex: 1, - marginBottom: 0, - marginLeft: 10, - marginRight: 10, - } - - const confirmBtnStlye: StyleProp = { - marginLeft: 8, - justifyContent: 'center', - alignContent: 'center', - marginTop: 5, - marginRight: 15, - marginBottom: 5, - } - - const dismissBtnStlye: StyleProp = { - marginLeft: 8, - justifyContent: 'center', - alignContent: 'center', - marginTop: 5, - marginBottom: 5, - } - - const mainContainerProps: BoxProps = { - minWidth: '100%', - p: 15, - backgroundColor: 'snackbar', - borderRadius: 4, - flexDirection: 'row', - flexWrap: 'wrap', - display: 'flex', - style: { - shadowColor: 'black', - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.6, - }, - } - - const messageContainerProps: BoxProps = { - flexDirection: 'row', - mt: 5, - mb: 5, - alignItems: 'center', - } - - const messageProp: TextViewProps = { - variant: 'HelperText', - color: 'snackBar', - } - - // adjust style depending on if there are 1 or 2 buttons - // 1 inline - // 2 its own row align to the right - if (!isUndo) { - // 2 - messageContainerProps.minWidth = '100%' - messageProp.flex = 1 - } else { - // 1 - messageContainerProps.flexWrap = 'wrap' - } - - const btnContainerProps: BoxProps = { - flexDirection: 'row', - justifyContent: 'flex-end', - flexGrow: 1, - flexWrap: fontScale >= 3 ? 'wrap' : undefined, - } - - const onActionPress = () => { - if (onActionPressed && typeof onActionPressed === 'function') { - onActionPressed() - } - toast.onHide() - } - - const onDismissPress = () => { - toast.onHide() - } - - const snackBarIconProps: VAIconProps = { - name: isError ? 'ExclamationTriangle' : 'CircleCheckMark', - fill: themeColor.icon.snackBarIcon, - fill2: 'transparent', - height: 18, - width: 18, - } - - const iconWrapperBoxProps: BoxProps = { - mr: 8, - alignSelf: 'flex-start', - mt: 2, - } - - const vibrate = (): void => { - if (!isUndo) { - triggerHaptic(HapticFeedbackTypes.notificationError) - } else { - triggerHaptic(HapticFeedbackTypes.notificationSuccess) - } - } - - return ( - - - = 3 ? windowHeight * 0.45 : undefined}> - - - - - - - {message} - - - - - - {!isUndo && ( - - - {actionBtnText || isError ? t('tryAgain') : t('snackbar.undo')} - - - )} - - {t('snackbar.dismiss')} - - - - {vibrate()} - - ) -} - -export default SnackBar diff --git a/VAMobile/src/components/Templates/MultiStepSubtask.tsx b/VAMobile/src/components/Templates/MultiStepSubtask.tsx index 68ed0ca52a7..c213751e13d 100644 --- a/VAMobile/src/components/Templates/MultiStepSubtask.tsx +++ b/VAMobile/src/components/Templates/MultiStepSubtask.tsx @@ -3,6 +3,8 @@ import React, { createContext, useCallback, useContext, useState } from 'react' import { ParamListBase, useFocusEffect } from '@react-navigation/native' import { TransitionPresets, createStackNavigator } from '@react-navigation/stack' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' + import { FullScreenSubtask, FullScreenSubtaskProps } from 'components' /** @@ -38,13 +40,27 @@ type MultiStepSubtaskProps = FullScreenSubtaskProps & { } function MultiStepSubtask({ ...props }: MultiStepSubtaskProps) { + const snackbar = useSnackbar() const { children, stackNavigator } = props const [subtaskProps, setSubtaskProps] = useState({}) return ( - {children} + { + if (e.data.closing) { + snackbar.hide() + } + }, + blur: () => { + snackbar.hide() + }, + }}> + {children} + ) diff --git a/VAMobile/src/constants/analytics.ts b/VAMobile/src/constants/analytics.ts index 56bd896faa9..db62f9931bb 100644 --- a/VAMobile/src/constants/analytics.ts +++ b/VAMobile/src/constants/analytics.ts @@ -1157,14 +1157,6 @@ export const Events = { name: 'vama_sm_start', } }, - vama_snackbar_null: (location: string): Event => { - return { - name: 'vama_snackbar_null', - params: { - location, - }, - } - }, vama_sso_cookie_received: (received: boolean): Event => { return { name: 'vama_sso_cookie_received', diff --git a/VAMobile/src/constants/common.ts b/VAMobile/src/constants/common.ts index 31a71876e17..f771d790ecf 100644 --- a/VAMobile/src/constants/common.ts +++ b/VAMobile/src/constants/common.ts @@ -1,7 +1,3 @@ -import { logAnalyticsEvent } from 'utils/analytics' - -import { Events } from './analytics' - export const DEFAULT_PAGE_SIZE = 10 export const LARGE_PAGE_SIZE = 5000 @@ -25,23 +21,6 @@ export const WebProtocolTypesConstants: { export const COVID19 = 'COVID-19' -export const SnackBarConstants: { - animationDuration: number - duration: number -} = { - animationDuration: 100, - duration: 900000, -} - -export const CloseSnackbarOnNavigation = (screenName: string | undefined) => { - if (screenName) { - if (!snackBar) { - logAnalyticsEvent(Events.vama_snackbar_null(`CloseSnackbarOnNavigation - ${screenName.split('-')[0]}`)) - } - snackBar?.hideAll() - } -} - export const DIRECT_DEPOSIT = 'Direct Deposit' export const MAX_DIGITS = 10 diff --git a/VAMobile/src/screens/BenefitsScreen/BenefitsScreen.tsx b/VAMobile/src/screens/BenefitsScreen/BenefitsScreen.tsx index 60fbcfaf95e..f49a503bea8 100644 --- a/VAMobile/src/screens/BenefitsScreen/BenefitsScreen.tsx +++ b/VAMobile/src/screens/BenefitsScreen/BenefitsScreen.tsx @@ -4,10 +4,11 @@ import { useTranslation } from 'react-i18next' import { useIsFocused } from '@react-navigation/native' import { CardStyleInterpolators, StackScreenProps, createStackNavigator } from '@react-navigation/stack' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' + import { useAuthorizedServices } from 'api/authorizedServices/getAuthorizedServices' import { useClaimsAndAppeals } from 'api/claimsAndAppeals' import { Box, CategoryLanding, CategoryLandingAlert, LargeNavButton } from 'components' -import { CloseSnackbarOnNavigation } from 'constants/common' import { NAMESPACE } from 'constants/namespaces' import { FEATURE_LANDING_TEMPLATE_OPTIONS } from 'constants/screens' import ClaimsScreen from 'screens/BenefitsScreen/ClaimsScreen' @@ -101,6 +102,7 @@ const BenefitsScreenStack = createStackNavigator() * Stack screen for the Benefits tab. Screens placed within this stack will appear in the context of the app level tab navigator */ function BenefitsStackScreen() { + const snackbar = useSnackbar() const screenOptions = { headerShown: false, cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, @@ -111,11 +113,11 @@ function BenefitsStackScreen() { screenListeners={{ transitionStart: (e) => { if (e.data.closing) { - CloseSnackbarOnNavigation(e.target) + snackbar.hide() } }, - blur: (e) => { - CloseSnackbarOnNavigation(e.target) + blur: () => { + snackbar.hide() }, }}> diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/AskForClaimDecision/AskForClaimDecision.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/AskForClaimDecision/AskForClaimDecision.tsx index dcc19beb709..910915d8793 100644 --- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/AskForClaimDecision/AskForClaimDecision.tsx +++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/AskForClaimDecision/AskForClaimDecision.tsx @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next' import { StackScreenProps } from '@react-navigation/stack/lib/typescript/src/types' import { Button } from '@department-of-veterans-affairs/mobile-component-library' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { useClaim, useSubmitClaimDecision } from 'api/claimsAndAppeals' import { @@ -27,17 +28,16 @@ import { ScreenIDTypesConstants } from 'store/api/types/Screens' import { a11yLabelVA } from 'utils/a11yLabel' import { logAnalyticsEvent } from 'utils/analytics' import { numberOfItemsNeedingAttentionFromVet } from 'utils/claims' -import { showSnackBar } from 'utils/common' -import { useAppDispatch, useDestructiveActionSheet, useRouteNavigation, useTheme } from 'utils/hooks' +import { useDestructiveActionSheet, useRouteNavigation, useTheme } from 'utils/hooks' import { FileRequestStackParams } from '../FileRequestSubtask' type AskForClaimDecisionProps = StackScreenProps function AskForClaimDecision({ navigation, route }: AskForClaimDecisionProps) { + const snackbar = useSnackbar() const theme = useTheme() const { t } = useTranslation(NAMESPACE.COMMON) - const dispatch = useAppDispatch() const { claimID } = route.params const { data: claim, error: loadingClaimError, refetch: refetchClaim, isFetching: loadingClaim } = useClaim(claimID) const { @@ -102,9 +102,14 @@ function AskForClaimDecision({ navigation, route }: AskForClaimDecisionProps) { const mutateOptions = { onSuccess: () => { setSubmittedDecision(true) - showSnackBar('Request sent', dispatch, undefined, true, false, true) + snackbar.show('Request sent') }, - onError: () => showSnackBar('Request could not be sent', dispatch, () => onSubmit, false, true), + onError: () => + snackbar.show('Request could not be sent', { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => onSubmit, + }), } submitClaimDecision(claimID, mutateOptions) } diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/SelectFile/UploadFile/UploadFile.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/SelectFile/UploadFile/UploadFile.tsx index ddab96776e9..ada1497b8be 100644 --- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/SelectFile/UploadFile/UploadFile.tsx +++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/SelectFile/UploadFile/UploadFile.tsx @@ -7,7 +7,7 @@ import { ScrollView } from 'react-native/types' import { StackActions } from '@react-navigation/native' import { StackScreenProps } from '@react-navigation/stack/lib/typescript/src/types' -import { Button, ButtonVariants } from '@department-of-veterans-affairs/mobile-component-library' +import { Button, ButtonVariants, useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { useUploadFileToClaim } from 'api/claimsAndAppeals' import { ClaimEventData, UploadFileToClaimParamaters } from 'api/types' @@ -22,7 +22,6 @@ import { VAScrollView, } from 'components' import FileList from 'components/FileList' -import { SnackbarMessages } from 'components/SnackBar' import { useSubtaskProps } from 'components/Templates/MultiStepSubtask' import SubtaskTitle from 'components/Templates/SubtaskTitle' import { Events } from 'constants/analytics' @@ -32,9 +31,7 @@ import { NAMESPACE } from 'constants/namespaces' import { DocumentPickerResponse } from 'screens/BenefitsScreen/BenefitsStackScreens' import { logAnalyticsEvent, logNonFatalErrorToFirebase } from 'utils/analytics' import { MAX_TOTAL_FILE_SIZE_IN_BYTES, isValidFileType } from 'utils/claims' -import { showSnackBar } from 'utils/common' import { - useAppDispatch, useBeforeNavBackListener, useDestructiveActionSheet, useRouteNavigation, @@ -48,11 +45,11 @@ import { FileRequestStackParams } from '../../FileRequestSubtask' type UploadFileProps = StackScreenProps function UploadFile({ navigation, route }: UploadFileProps) { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const theme = useTheme() const { claimID, request: originalRequest, fileUploaded } = route.params const [filesUploadedSuccess, setFilesUploadedSuccess] = useState(false) - const dispatch = useAppDispatch() const navigateTo = useRouteNavigation() const [filesList, setFilesList] = useState([fileUploaded]) const { mutate: uploadFileToClaim, isPending: loadingFileUpload } = useUploadFileToClaim( @@ -62,10 +59,6 @@ function UploadFile({ navigation, route }: UploadFileProps) { ) const confirmAlert = useDestructiveActionSheet() const [request, setRequest] = useState(originalRequest) - const snackbarMessages: SnackbarMessages = { - successMsg: t('fileUpload.submitted'), - errorMsg: t('fileUpload.submitted.error'), - } const [error, setError] = useState('') const [isActionSheetVisible, setIsActionSheetVisible] = useState(false) const [filesEmptyError, setFilesEmptyError] = useState(false) @@ -150,9 +143,14 @@ function UploadFile({ navigation, route }: UploadFileProps) { 'file', ), ) - showSnackBar(snackbarMessages.successMsg, dispatch, undefined, true) + snackbar.show(t('fileUpload.submitted')) }, - onError: () => showSnackBar(snackbarMessages.errorMsg, dispatch, onUploadConfirmed, false, true), + onError: () => + snackbar.show(t('fileUpload.submitted.error'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: onUploadConfirmed, + }), } const params: UploadFileToClaimParamaters = { claimID, documentType: documentType, request, files: filesList } uploadFileToClaim(params, mutateOptions) diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/TakePhotos/UploadOrAddPhotos/UploadOrAddPhotos.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/TakePhotos/UploadOrAddPhotos/UploadOrAddPhotos.tsx index 5e951643bb7..f20a47dfced 100644 --- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/TakePhotos/UploadOrAddPhotos/UploadOrAddPhotos.tsx +++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimDetailsScreen/ClaimStatus/ClaimFileUpload/TakePhotos/UploadOrAddPhotos/UploadOrAddPhotos.tsx @@ -6,7 +6,7 @@ import { Asset, ImagePickerResponse } from 'react-native-image-picker/src/types' import { StackActions } from '@react-navigation/native' import { StackScreenProps } from '@react-navigation/stack/lib/typescript/src/types' -import { Button } from '@department-of-veterans-affairs/mobile-component-library' +import { Button, useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import _ from 'underscore' import { useUploadFileToClaim } from 'api/claimsAndAppeals' @@ -23,7 +23,6 @@ import { TextView, VAScrollView, } from 'components' -import { SnackbarMessages } from 'components/SnackBar' import { useSubtaskProps } from 'components/Templates/MultiStepSubtask' import SubtaskTitle from 'components/Templates/SubtaskTitle' import { Events } from 'constants/analytics' @@ -33,9 +32,7 @@ import { NAMESPACE } from 'constants/namespaces' import { logAnalyticsEvent } from 'utils/analytics' import { deletePhoto, onAddPhotos } from 'utils/claims' import { bytesToFinalSizeDisplay, bytesToFinalSizeDisplayA11y } from 'utils/common' -import { showSnackBar } from 'utils/common' import { - useAppDispatch, useBeforeNavBackListener, useDestructiveActionSheet, useOrientation, @@ -50,12 +47,12 @@ import { FileRequestStackParams } from '../../FileRequestSubtask' type UploadOrAddPhotosProps = StackScreenProps function UploadOrAddPhotos({ navigation, route }: UploadOrAddPhotosProps) { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const theme = useTheme() const showActionSheetWithOptions = useShowActionSheet() const { claimID, request: originalRequest, firstImageResponse } = route.params const [filesUploadedSuccess, setFilesUploadedSuccess] = useState(false) - const dispatch = useAppDispatch() const isPortrait = useOrientation() const [imagesList, setImagesList] = useState(firstImageResponse.assets) const { mutate: uploadFileToClaim, isPending: loadingFileUpload } = useUploadFileToClaim( @@ -71,10 +68,6 @@ function UploadOrAddPhotos({ navigation, route }: UploadOrAddPhotosProps) { const navigateTo = useRouteNavigation() const [request, setRequest] = useState(originalRequest) const scrollViewRef = useRef(null) - const snackbarMessages: SnackbarMessages = { - successMsg: t('fileUpload.submitted'), - errorMsg: t('fileUpload.submitted.error'), - } const [imagesEmptyError, setImagesEmptyError] = useState(false) const waygate = getWaygateToggles().WG_UploadOrAddPhotos @@ -153,9 +146,14 @@ function UploadOrAddPhotos({ navigation, route }: UploadOrAddPhotosProps) { 'photo', ), ) - showSnackBar(snackbarMessages.successMsg, dispatch, undefined, true) + snackbar.show(t('fileUpload.submitted')) }, - onError: () => showSnackBar(snackbarMessages.errorMsg, dispatch, onUploadConfirmed, false, true), + onError: () => + snackbar.show(t('fileUpload.submitted.error'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: onUploadConfirmed, + }), } const params: UploadFileToClaimParamaters = { claimID, @@ -309,10 +307,7 @@ function UploadOrAddPhotos({ navigation, route }: UploadOrAddPhotosProps) { } const callbackIfUri = (response: ImagePickerResponse): void => { - if (!snackBar) { - logAnalyticsEvent(Events.vama_snackbar_null('Claim add photos')) - } - snackBar?.hideAll() + snackbar.hide() if (response && response.assets && response.assets.length + (imagesList?.length || 0) > MAX_NUM_PHOTOS) { setErrorMessage(t('fileUpload.tooManyPhotosError')) } else { diff --git a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimLettersScreen/ClaimLettersScreen.tsx b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimLettersScreen/ClaimLettersScreen.tsx index f97a6583a39..0bd0a17c7a7 100644 --- a/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimLettersScreen/ClaimLettersScreen.tsx +++ b/VAMobile/src/screens/BenefitsScreen/ClaimsScreen/ClaimLettersScreen/ClaimLettersScreen.tsx @@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next' import { useNavigationState } from '@react-navigation/native' import { StackScreenProps } from '@react-navigation/stack' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { useQueryClient } from '@tanstack/react-query' import { useDecisionLetters, useDownloadDecisionLetter } from 'api/decisionLetters' @@ -23,7 +24,7 @@ import { BenefitsStackParamList } from 'screens/BenefitsScreen/BenefitsStackScre import { DowntimeFeatureTypeConstants, ScreenIDTypesConstants } from 'store/api/types' import { VATypographyThemeVariants } from 'styles/theme' import { logAnalyticsEvent } from 'utils/analytics' -import { getA11yLabelText, isErrorObject, showSnackBar } from 'utils/common' +import { getA11yLabelText, isErrorObject } from 'utils/common' import { formatDateMMMMDDYYYY } from 'utils/formattingUtils' import { useAppDispatch, useDowntime, useTheme } from 'utils/hooks' import { screenContentAllowed } from 'utils/waygateConfig' @@ -33,6 +34,7 @@ import NoClaimLettersScreen from './NoClaimLettersScreen/NoClaimLettersScreen' type ClaimLettersScreenProps = StackScreenProps const ClaimLettersScreen = ({ navigation }: ClaimLettersScreenProps) => { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const theme = useTheme() const dispatch = useAppDispatch() @@ -61,13 +63,9 @@ const ClaimLettersScreen = ({ navigation }: ClaimLettersScreenProps) => { useEffect(() => { if (downloadLetterErrorDetails && isErrorObject(downloadLetterErrorDetails)) { - if (!snackBar) { - logAnalyticsEvent(Events.vama_snackbar_null('ClaimLetters view letter')) - } - snackBar?.hideAll() - showSnackBar(t('claimLetters.download.error'), dispatch, refetchLetter, false, true, true) + snackbar.show(t('claimLetters.download.error'), { isError: true, onActionPressed: refetchLetter }) } - }, [downloadLetterErrorDetails, queryClient, dispatch, t, refetchLetter]) + }, [downloadLetterErrorDetails, queryClient, dispatch, t, refetchLetter, snackbar]) const letterButtons = decisionLetters.map((letter, index) => { const { typeDescription, receivedAt } = letter.attributes diff --git a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/AppointmentCancelReschedule.tsx b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/AppointmentCancelReschedule.tsx index 01ef5df9e66..53e8d6c006a 100644 --- a/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/AppointmentCancelReschedule.tsx +++ b/VAMobile/src/screens/HealthScreen/Appointments/AppointmentTypeComponents/SharedComponents/AppointmentCancelReschedule.tsx @@ -2,6 +2,7 @@ import React from 'react' import { useTranslation } from 'react-i18next' import { Button, ButtonVariants } from '@department-of-veterans-affairs/mobile-component-library' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { UseMutateFunction } from '@tanstack/react-query' import { TFunction } from 'i18next' @@ -9,7 +10,6 @@ import { AppointmentAttributes, AppointmentLocation } from 'api/types' import { Box, BoxProps, ClickToCallPhoneNumber, LinkWithAnalytics, TextView } from 'components' import { Events } from 'constants/analytics' import { NAMESPACE } from 'constants/namespaces' -import { AppDispatch } from 'store' import { VATheme } from 'styles/theme' import { a11yLabelVA } from 'utils/a11yLabel' import { logAnalyticsEvent } from 'utils/analytics' @@ -21,9 +21,8 @@ import { getAppointmentAnalyticsDays, getAppointmentAnalyticsStatus, } from 'utils/appointments' -import { showSnackBar } from 'utils/common' import getEnv from 'utils/env' -import { useAppDispatch, useDestructiveActionSheet, useDestructiveActionSheetProps, useTheme } from 'utils/hooks' +import { useDestructiveActionSheet, useDestructiveActionSheetProps, useTheme } from 'utils/hooks' const { LINK_URL_VA_SCHEDULING, WEBVIEW_URL_FACILITY_LOCATOR } = getEnv() @@ -57,7 +56,7 @@ const cancelButton = ( goBack: () => void, t: TFunction, theme: VATheme, - dispatch: AppDispatch, + snackbar: ReturnType, confirmAlert: (props: useDestructiveActionSheetProps) => void, cancelId?: string, cancelAppointment?: UseMutateFunction, @@ -76,14 +75,7 @@ const cancelButton = ( const mutateOptions = { onSuccess: () => { goBack() - showSnackBar( - pendingAppointment ? t('appointments.requestCanceled') : t('appointments.appointmentCanceled'), - dispatch, - undefined, - true, - false, - true, - ) + snackbar.show(pendingAppointment ? t('appointments.requestCanceled') : t('appointments.appointmentCanceled')) logAnalyticsEvent( Events.vama_appt_cancel( pendingAppointment, @@ -95,15 +87,9 @@ const cancelButton = ( ) }, onError: () => { - showSnackBar( + snackbar.show( pendingAppointment ? t('appointments.requestNotCanceled') : t('appointments.appointmentNotCanceled'), - dispatch, - () => { - cancelAppointment(cancelId, mutateOptions) - }, - false, - true, - true, + { isError: true, onActionPressed: () => cancelAppointment(cancelId, mutateOptions) }, ) }, } @@ -296,9 +282,9 @@ function AppointmentCancelReschedule({ goBack, cancelAppointment, }: AppointmentCancelRescheduleProps) { + const snackbar = useSnackbar() const theme = useTheme() const { t } = useTranslation(NAMESPACE.COMMON) - const dispatch = useAppDispatch() const confirmAlert = useDestructiveActionSheet() const { location, cancelId } = attributes || ({} as AppointmentAttributes) @@ -320,7 +306,7 @@ function AppointmentCancelReschedule({ goBack, t, theme, - dispatch, + snackbar, confirmAlert, cancelId, cancelAppointment, @@ -366,7 +352,7 @@ function AppointmentCancelReschedule({ goBack, t, theme, - dispatch, + snackbar, confirmAlert, cancelId, cancelAppointment, diff --git a/VAMobile/src/screens/HealthScreen/HealthScreen.tsx b/VAMobile/src/screens/HealthScreen/HealthScreen.tsx index 2e5c64dc43d..afbc5830edb 100644 --- a/VAMobile/src/screens/HealthScreen/HealthScreen.tsx +++ b/VAMobile/src/screens/HealthScreen/HealthScreen.tsx @@ -6,6 +6,8 @@ import AsyncStorage from '@react-native-async-storage/async-storage' import { useIsFocused } from '@react-navigation/native' import { CardStyleInterpolators, StackScreenProps, createStackNavigator } from '@react-navigation/stack' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' + import { useAppointments } from 'api/appointments' import { useAuthorizedServices } from 'api/authorizedServices/getAuthorizedServices' import { useFacilitiesInfo } from 'api/facilities/getFacilitiesInfo' @@ -13,7 +15,6 @@ import { usePrescriptions } from 'api/prescriptions' import { useFolders } from 'api/secureMessaging' import { AnnouncementBanner, Box, CategoryLanding, CategoryLandingAlert, LargeNavButton, TextView } from 'components' import { TimeFrameTypeConstants } from 'constants/appointments' -import { CloseSnackbarOnNavigation } from 'constants/common' import { NAMESPACE } from 'constants/namespaces' import { FEATURE_LANDING_TEMPLATE_OPTIONS } from 'constants/screens' import { DowntimeFeatureTypeConstants } from 'store/api/types' @@ -200,6 +201,7 @@ const HealthScreenStack = createStackNavigator() * Stack screen for the Health tab. Screens placed within this stack will appear in the context of the app level tab navigator */ function HealthStackScreen({}: HealthStackScreenProps) { + const snackbar = useSnackbar() const screenOptions = { headerShown: false, cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, @@ -210,11 +212,11 @@ function HealthStackScreen({}: HealthStackScreenProps) { screenListeners={{ transitionStart: (e) => { if (e.data.closing) { - CloseSnackbarOnNavigation(e.target) + snackbar.hide() } }, - blur: (e) => { - CloseSnackbarOnNavigation(e.target) + blur: () => { + snackbar.hide() }, }}> diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/CancelConfirmations/ComposeCancelConfirmation.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/CancelConfirmations/ComposeCancelConfirmation.tsx index 73a8bbf40d2..ca72d21f09b 100644 --- a/VAMobile/src/screens/HealthScreen/SecureMessaging/CancelConfirmations/ComposeCancelConfirmation.tsx +++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/CancelConfirmations/ComposeCancelConfirmation.tsx @@ -1,17 +1,16 @@ import { useState } from 'react' import { useTranslation } from 'react-i18next' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { useQueryClient } from '@tanstack/react-query' import { secureMessagingKeys, useSaveDraft } from 'api/secureMessaging' import { SaveDraftParameters, SecureMessagingFormData, SecureMessagingSystemFolderIdConstants } from 'api/types' -import { SnackbarMessages } from 'components/SnackBar' import { Events } from 'constants/analytics' import { NAMESPACE } from 'constants/namespaces' import { FolderNameTypeConstants, FormHeaderType, FormHeaderTypeConstants } from 'constants/secureMessaging' import { logAnalyticsEvent } from 'utils/analytics' -import { showSnackBar } from 'utils/common' -import { useAppDispatch, useDestructiveActionSheet, useRouteNavigation } from 'utils/hooks' +import { useDestructiveActionSheet, useRouteNavigation, useTheme } from 'utils/hooks' type ComposeCancelConfirmationProps = { /** Contents of the message */ @@ -30,18 +29,15 @@ export function useComposeCancelConfirmation(): [ isDiscarded: boolean, composeCancelConfirmation: (props: ComposeCancelConfirmationProps) => void, ] { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) - const dispatch = useAppDispatch() + const theme = useTheme() const navigateTo = useRouteNavigation() const confirmationAlert = useDestructiveActionSheet() const goToDrafts = useGoToDrafts() const queryClient = useQueryClient() const [isDiscarded, setIsDiscarded] = useState(false) const { mutate: saveDraft } = useSaveDraft() - const snackbarMessages: SnackbarMessages = { - successMsg: t('secureMessaging.draft.saved'), - errorMsg: t('secureMessaging.draft.saved.error'), - } return [ isDiscarded, @@ -70,7 +66,7 @@ export function useComposeCancelConfirmation(): [ const params: SaveDraftParameters = { messageData: message, replyID: replyToID, messageID: draftMessageID } const mutateOptions = { onSuccess: () => { - showSnackBar(snackbarMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(t('secureMessaging.draft.saved')) logAnalyticsEvent(Events.vama_sm_save_draft(messageData.category)) queryClient.invalidateQueries({ queryKey: [secureMessagingKeys.folderMessages, SecureMessagingSystemFolderIdConstants.DRAFTS], @@ -85,7 +81,11 @@ export function useComposeCancelConfirmation(): [ }) }, onError: () => { - showSnackBar(snackbarMessages.errorMsg, dispatch, () => saveDraft(params, mutateOptions), false, true) + snackbar.show(t('secureMessaging.draft.saved.error'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => saveDraft(params, mutateOptions), + }) }, } saveDraft(params, mutateOptions) diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/EditDraft/EditDraft.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/EditDraft/EditDraft.tsx index ac68fa5c401..e98b6c29f54 100644 --- a/VAMobile/src/screens/HealthScreen/SecureMessaging/EditDraft/EditDraft.tsx +++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/EditDraft/EditDraft.tsx @@ -4,7 +4,7 @@ import { ScrollView } from 'react-native' import { StackScreenProps } from '@react-navigation/stack' -import { Button } from '@department-of-veterans-affairs/mobile-component-library' +import { Button, useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { useQueryClient } from '@tanstack/react-query' import { DateTime } from 'luxon' import _ from 'underscore' @@ -45,7 +45,6 @@ import { TextView, } from 'components' import { MenuViewActionsType } from 'components/Menu' -import { SnackbarMessages } from 'components/SnackBar' import { Events } from 'constants/analytics' import { SecureMessagingErrorCodesConstants } from 'constants/errors' import { NAMESPACE } from 'constants/namespaces' @@ -54,10 +53,9 @@ import { HealthStackParamList } from 'screens/HealthScreen/HealthStackScreens' import { ScreenIDTypesConstants } from 'store/api/types' import { a11yLabelVA } from 'utils/a11yLabel' import { logAnalyticsEvent } from 'utils/analytics' -import { isErrorObject, showSnackBar } from 'utils/common' +import { isErrorObject } from 'utils/common' import { hasErrorCode } from 'utils/errors' import { - useAppDispatch, useAttachments, useBeforeNavBackListener, useDestructiveActionSheet, @@ -78,26 +76,12 @@ import { renderMessages } from '../ViewMessage/ViewMessageScreen' type EditDraftProps = StackScreenProps function EditDraft({ navigation, route }: EditDraftProps) { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const theme = useTheme() - const dispatch = useAppDispatch() const goToDrafts = useGoToDrafts() const navigateTo = useRouteNavigation() const queryClient = useQueryClient() - const snackbarMessages: SnackbarMessages = { - successMsg: t('secureMessaging.deleteDraft.snackBarMessage'), - errorMsg: t('secureMessaging.deleteDraft.snackBarErrorMessage'), - } - const saveSnackbarMessages: SnackbarMessages = { - successMsg: t('secureMessaging.draft.saved'), - errorMsg: t('secureMessaging.draft.saved.error'), - } - - const snackbarSentMessages: SnackbarMessages = { - successMsg: t('secureMessaging.startNewMessage.sent'), - errorMsg: t('secureMessaging.startNewMessage.sent.error'), - } - const { data: recipients, isFetched: hasLoadedRecipients, @@ -197,21 +181,25 @@ function EditDraft({ navigation, route }: EditDraftProps) { : { recipient_id: parseInt(to, 10), category, body, subject, draft_id: messageID } const mutateOptions = { onSuccess: () => { - showSnackBar(snackbarSentMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(t('secureMessaging.startNewMessage.sent')) logAnalyticsEvent(Events.vama_sm_send_message(messageData.category, undefined)) navigateTo('SecureMessaging', { activeTab: 1 }) }, } const params: SendMessageParameters = { messageData: messageData, uploads: attachmentsList } - showSnackBar(snackbarSentMessages.errorMsg, dispatch, () => sendMessage(params, mutateOptions), false, true) + snackbar.show(t('secureMessaging.startNewMessage.sent.error'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => sendMessage(params, mutateOptions), + }) } } }, [ - dispatch, + snackbar, + t, + theme, sendMessageError, sendMessageErrorDetails, - snackbarSentMessages.successMsg, - snackbarSentMessages.errorMsg, attachmentsList, category, messageID, @@ -271,7 +259,7 @@ function EditDraft({ navigation, route }: EditDraftProps) { const params: DeleteMessageParameters = { messageID: messageID } const mutateOptions = { onSuccess: () => { - showSnackBar(snackbarMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(t('secureMessaging.deleteDraft.snackBarMessage')) queryClient.invalidateQueries({ queryKey: [secureMessagingKeys.folderMessages, SecureMessagingSystemFolderIdConstants.DRAFTS], }) @@ -283,7 +271,11 @@ function EditDraft({ navigation, route }: EditDraftProps) { goToDraftFolder(false) }, onError: () => { - showSnackBar(snackbarMessages.errorMsg, dispatch, () => deleteDraft(params, mutateOptions), false, true) + snackbar.show(t('secureMessaging.deleteDraft.snackBarErrorMessage'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => deleteDraft(params, mutateOptions), + }) }, } deleteDraft(params, mutateOptions) @@ -476,7 +468,7 @@ function EditDraft({ navigation, route }: EditDraftProps) { const params: SaveDraftParameters = { messageData: messageData, messageID: messageID, replyID: replyToID } const mutateOptions = { onSuccess: () => { - showSnackBar(saveSnackbarMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(t('secureMessaging.draft.saved')) logAnalyticsEvent(Events.vama_sm_save_draft(messageData.category)) queryClient.invalidateQueries({ queryKey: [secureMessagingKeys.message, messageID], @@ -487,7 +479,11 @@ function EditDraft({ navigation, route }: EditDraftProps) { goToDraftFolder(true) }, onError: () => { - showSnackBar(saveSnackbarMessages.errorMsg, dispatch, () => saveDraft(params, mutateOptions), false, true) + snackbar.show(t('secureMessaging.draft.saved.error'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => saveDraft(params, mutateOptions), + }) }, } saveDraft(params, mutateOptions) @@ -495,7 +491,7 @@ function EditDraft({ navigation, route }: EditDraftProps) { } else { const mutateOptions = { onSuccess: () => { - showSnackBar(snackbarSentMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(t('secureMessaging.startNewMessage.sent')) logAnalyticsEvent(Events.vama_sm_send_message(messageData.category, undefined)) queryClient.invalidateQueries({ queryKey: [secureMessagingKeys.folderMessages, SecureMessagingSystemFolderIdConstants.DRAFTS], diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyMessage/ReplyMessage.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyMessage/ReplyMessage.tsx index 893a9ff49c1..a0d43aa9d5c 100644 --- a/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyMessage/ReplyMessage.tsx +++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/ReplyMessage/ReplyMessage.tsx @@ -4,7 +4,7 @@ import { ScrollView } from 'react-native' import { StackScreenProps } from '@react-navigation/stack' -import { Button } from '@department-of-veterans-affairs/mobile-component-library' +import { Button, useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { useQueryClient } from '@tanstack/react-query' import _ from 'underscore' @@ -37,17 +37,15 @@ import { TextArea, TextView, } from 'components' -import { SnackbarMessages } from 'components/SnackBar' import { Events } from 'constants/analytics' import { SecureMessagingErrorCodesConstants } from 'constants/errors' import { NAMESPACE } from 'constants/namespaces' import { FolderNameTypeConstants, FormHeaderTypeConstants, PREPOPULATE_SIGNATURE } from 'constants/secureMessaging' import { HealthStackParamList } from 'screens/HealthScreen/HealthStackScreens' import { logAnalyticsEvent } from 'utils/analytics' -import { isErrorObject, showSnackBar } from 'utils/common' +import { isErrorObject } from 'utils/common' import { hasErrorCode } from 'utils/errors' import { - useAppDispatch, useAttachments, useBeforeNavBackListener, useDestructiveActionSheet, @@ -64,9 +62,9 @@ import { renderMessages } from '../ViewMessage/ViewMessageScreen' type ReplyMessageProps = StackScreenProps function ReplyMessage({ navigation, route }: ReplyMessageProps) { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const theme = useTheme() - const dispatch = useAppDispatch() const draftAttachmentAlert = useDestructiveActionSheet() const navigateTo = useRouteNavigation() const queryClient = useQueryClient() @@ -125,16 +123,6 @@ function ReplyMessage({ navigation, route }: ReplyMessageProps) { const messageDataRef = useRef(messageData) messageDataRef.current = messageData - const snackbarMessages: SnackbarMessages = { - successMsg: t('secureMessaging.draft.saved'), - errorMsg: t('secureMessaging.draft.saved.error'), - } - - const snackbarSentMessages: SnackbarMessages = { - successMsg: t('secureMessaging.startNewMessage.sent'), - errorMsg: t('secureMessaging.startNewMessage.sent.error'), - } - const goToCancel = () => { replyCancelConfirmation({ origin: FormHeaderTypeConstants.reply, @@ -216,7 +204,7 @@ function ReplyMessage({ navigation, route }: ReplyMessageProps) { const params: SaveDraftParameters = { messageData: reducedMessageData, replyID: message.messageId } const mutateOptions = { onSuccess: () => { - showSnackBar(snackbarMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(t('secureMessaging.draft.saved')) logAnalyticsEvent(Events.vama_sm_save_draft(reducedMessageData.category)) queryClient.invalidateQueries({ queryKey: [secureMessagingKeys.folderMessages, SecureMessagingSystemFolderIdConstants.DRAFTS], @@ -229,13 +217,13 @@ function ReplyMessage({ navigation, route }: ReplyMessageProps) { }) }, onError: () => { - showSnackBar( - snackbarMessages.errorMsg, - dispatch, - // passing messageDataRef to ensure we have the latest messageData - () => + snackbar.show(t('secureMessaging.draft.saved.error'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => saveDraft( { + // passing messageDataRef to ensure we have the latest messageData messageData: { body: messageDataRef.current.body, category: messageDataRef.current.category, @@ -244,9 +232,7 @@ function ReplyMessage({ navigation, route }: ReplyMessageProps) { }, mutateOptions, ), - false, - true, - ) + }) }, } saveDraft(params, mutateOptions) @@ -254,7 +240,7 @@ function ReplyMessage({ navigation, route }: ReplyMessageProps) { } else { const mutateOptions = { onSuccess: () => { - showSnackBar(snackbarSentMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(t('secureMessaging.startNewMessage.sent')) logAnalyticsEvent(Events.vama_sm_send_message(messageData.category, undefined)) navigateTo('SecureMessaging', { activeTab: 0 }) }, @@ -266,22 +252,20 @@ function ReplyMessage({ navigation, route }: ReplyMessageProps) { ) { setReplyTriageError(true) } else { - showSnackBar( - snackbarSentMessages.errorMsg, - dispatch, - // passing messageDataRef to ensure we have the latest messageData - () => + snackbar.show(t('secureMessaging.startNewMessage.sent.error'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => sendMessage( { + // passing messageDataRef to ensure we have the latest messageData messageData: messageDataRef.current, uploads: attachmentsList, replyToID: message.messageId, }, mutateOptions, ), - false, - true, - ) + }) } }, } diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/SecureMessaging.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/SecureMessaging.tsx index 0fb8a036d43..a36a0ac555e 100644 --- a/VAMobile/src/screens/HealthScreen/SecureMessaging/SecureMessaging.tsx +++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/SecureMessaging.tsx @@ -5,7 +5,7 @@ import { ScrollView } from 'react-native' import { useFocusEffect, useIsFocused } from '@react-navigation/native' import { StackScreenProps } from '@react-navigation/stack' -import { Button, SegmentedControl } from '@department-of-veterans-affairs/mobile-component-library' +import { Button, SegmentedControl, useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import _ from 'underscore' import { useAuthorizedServices } from 'api/authorizedServices/getAuthorizedServices' @@ -35,6 +35,7 @@ import TermsAndConditions from './TermsAndConditions/TermsAndConditions' type SecureMessagingScreen = StackScreenProps function SecureMessaging({ navigation, route }: SecureMessagingScreen) { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const theme = useTheme() const navigateTo = useRouteNavigation() @@ -113,10 +114,7 @@ function SecureMessaging({ navigation, route }: SecureMessagingScreen) { } }) } - if (!snackBar) { - logAnalyticsEvent(Events.vama_snackbar_null('SecureMessaging tab change')) - } - snackBar?.hideAll() + snackbar.hide() setSecureMessagingTab(index) } } diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/StartNewMessage.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/StartNewMessage.tsx index bc5b464dfa7..fba27a2702d 100644 --- a/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/StartNewMessage.tsx +++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/StartNewMessage/StartNewMessage.tsx @@ -4,7 +4,7 @@ import { ScrollView } from 'react-native' import { StackScreenProps } from '@react-navigation/stack' -import { Button } from '@department-of-veterans-affairs/mobile-component-library' +import { Button, useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { useQueryClient } from '@tanstack/react-query' import _ from 'underscore' @@ -37,7 +37,6 @@ import { PickerItem, TextArea, } from 'components' -import { SnackbarMessages } from 'components/SnackBar' import { Events } from 'constants/analytics' import { SecureMessagingErrorCodesConstants } from 'constants/errors' import { NAMESPACE } from 'constants/namespaces' @@ -46,10 +45,9 @@ import { HealthStackParamList } from 'screens/HealthScreen/HealthStackScreens' import { ScreenIDTypesConstants } from 'store/api/types' import { a11yLabelVA } from 'utils/a11yLabel' import { logAnalyticsEvent } from 'utils/analytics' -import { isErrorObject, showSnackBar } from 'utils/common' +import { isErrorObject } from 'utils/common' import { hasErrorCode } from 'utils/errors' import { - useAppDispatch, useAttachments, useBeforeNavBackListener, useDestructiveActionSheet, @@ -70,23 +68,12 @@ import { useComposeCancelConfirmation } from '../CancelConfirmations/ComposeCanc type StartNewMessageProps = StackScreenProps function StartNewMessage({ navigation, route }: StartNewMessageProps) { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const theme = useTheme() - const dispatch = useAppDispatch() const draftAttachmentAlert = useDestructiveActionSheet() const navigateTo = useRouteNavigation() const queryClient = useQueryClient() - - const snackbarMessages: SnackbarMessages = { - successMsg: t('secureMessaging.draft.saved'), - errorMsg: t('secureMessaging.draft.saved.error'), - } - - const snackbarSentMessages: SnackbarMessages = { - successMsg: t('secureMessaging.startNewMessage.sent'), - errorMsg: t('secureMessaging.startNewMessage.sent.error'), - } - const { mutate: saveDraft, isPending: savingDraft } = useSaveDraft() const { mutate: sendMessage, @@ -304,7 +291,7 @@ function StartNewMessage({ navigation, route }: StartNewMessageProps) { const params: SaveDraftParameters = { messageData: messageData } const mutateOptions = { onSuccess: () => { - showSnackBar(snackbarMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(t('secureMessaging.draft.saved')) logAnalyticsEvent(Events.vama_sm_save_draft(messageData.category)) queryClient.invalidateQueries({ queryKey: [secureMessagingKeys.folderMessages, SecureMessagingSystemFolderIdConstants.DRAFTS], @@ -317,14 +304,14 @@ function StartNewMessage({ navigation, route }: StartNewMessageProps) { }) }, onError: () => { - showSnackBar( - snackbarMessages.errorMsg, - dispatch, - // passing messageDataRef to ensure we have the latest messageData - () => saveDraft({ messageData: messageDataRef.current }, mutateOptions), - false, - true, - ) + snackbar.show(t('secureMessaging.draft.saved.error'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => { + // passing messageDataRef to ensure we have the latest messageData + saveDraft({ messageData: messageDataRef.current }, mutateOptions) + }, + }) }, } saveDraft(params, mutateOptions) @@ -332,7 +319,7 @@ function StartNewMessage({ navigation, route }: StartNewMessageProps) { } else { const mutateOptions = { onSuccess: () => { - showSnackBar(snackbarSentMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(t('secureMessaging.startNewMessage.sent')) logAnalyticsEvent(Events.vama_sm_send_message(messageData.category, undefined)) navigateTo('SecureMessaging', { activeTab: 0 }) }, @@ -344,14 +331,14 @@ function StartNewMessage({ navigation, route }: StartNewMessageProps) { ) { setReplyTriageError(true) } else { - showSnackBar( - snackbarSentMessages.errorMsg, - dispatch, - // passing messageDataRef to ensure we have the latest messageData - () => sendMessage({ messageData: messageDataRef.current, uploads: attachmentsList }, mutateOptions), - false, - true, - ) + snackbar.show(t('secureMessaging.startNewMessage.sent.error'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => { + // passing messageDataRef to ensure we have the latest messageData + sendMessage({ messageData: messageDataRef.current, uploads: attachmentsList }, mutateOptions) + }, + }) } }, } diff --git a/VAMobile/src/screens/HealthScreen/SecureMessaging/ViewMessage/ViewMessageScreen.tsx b/VAMobile/src/screens/HealthScreen/SecureMessaging/ViewMessage/ViewMessageScreen.tsx index 48b252029ae..69134118fc9 100644 --- a/VAMobile/src/screens/HealthScreen/SecureMessaging/ViewMessage/ViewMessageScreen.tsx +++ b/VAMobile/src/screens/HealthScreen/SecureMessaging/ViewMessage/ViewMessageScreen.tsx @@ -4,6 +4,7 @@ import { useSelector } from 'react-redux' import { StackScreenProps } from '@react-navigation/stack/lib/typescript/src/types' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { IconProps } from '@department-of-veterans-affairs/mobile-component-library/src/components/Icon/Icon' import { useQueryClient } from '@tanstack/react-query' import { DateTime } from 'luxon' @@ -40,7 +41,6 @@ import { VAIconProps, VAModalPicker, } from 'components' -import { SnackbarMessages } from 'components/SnackBar' import { Events, UserAnalytics } from 'constants/analytics' import { NAMESPACE } from 'constants/namespaces' import { FolderNameTypeConstants, READ, REPLY_WINDOW_IN_DAYS } from 'constants/secureMessaging' @@ -50,8 +50,7 @@ import { ScreenIDTypesConstants } from 'store/api/types/Screens' import { DemoState } from 'store/slices/demoSlice' import { GenerateFolderMessage } from 'translations/en/functions' import { logAnalyticsEvent, setAnalyticsUserProperty } from 'utils/analytics' -import { showSnackBar } from 'utils/common' -import { useAppDispatch, useDowntimeByScreenID, useTheme } from 'utils/hooks' +import { useDowntimeByScreenID, useTheme } from 'utils/hooks' import { useReviewEvent } from 'utils/inAppReviews' import { getfolderName } from 'utils/secureMessaging' import { screenContentAllowed } from 'utils/waygateConfig' @@ -105,9 +104,9 @@ function ViewMessageScreen({ route, navigation }: ViewMessageScreenProps) { const folderWhereMessageIs = useRef(currentFolderIdParam.toString()) const folderWhereMessagePreviousewas = useRef(folderWhereMessageIs.current) + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const theme = useTheme() - const dispatch = useAppDispatch() const registerReviewEvent = useReviewEvent(true) const queryClient = useQueryClient() @@ -272,12 +271,6 @@ function ViewMessageScreen({ route, navigation }: ViewMessageScreenProps) { const currentFolder = Number(folderWhereMessageIs.current) folderWhereMessagePreviousewas.current = currentFolder.toString() const newFolder = Number(value) - const snackbarMessages: SnackbarMessages = { - successMsg: GenerateFolderMessage(t, newFolder, folders, false, false), - errorMsg: GenerateFolderMessage(t, newFolder, folders, false, true), - undoMsg: GenerateFolderMessage(t, currentFolder, folders, true, false), - undoErrorMsg: GenerateFolderMessage(t, currentFolder, folders, true, true), - } if (folderWhereMessageIs.current !== value) { setNewCurrentFolderID(value) folderWhereMessageIs.current = value @@ -300,10 +293,8 @@ function ViewMessageScreen({ route, navigation }: ViewMessageScreenProps) { queryClient.invalidateQueries({ queryKey: [secureMessagingKeys.message, messageID] }) queryClient.invalidateQueries({ queryKey: [secureMessagingKeys.folderMessages, currentFolderIdParam] }) logAnalyticsEvent(Events.vama_sm_move_outcome(folder())) - showSnackBar( - snackbarMessages.successMsg, - dispatch, - () => { + snackbar.show(GenerateFolderMessage(t, newFolder, folders, false, false), { + onActionPressed: () => { const undoParams: MoveMessageParameters = { messageID: messageID, newFolderID: currentFolder } const undoMutateOptions = { onSuccess: () => { @@ -312,46 +303,28 @@ function ViewMessageScreen({ route, navigation }: ViewMessageScreenProps) { queryKey: [secureMessagingKeys.folderMessages, currentFolderIdParam], }) logAnalyticsEvent(Events.vama_sm_move_outcome(folder())) - showSnackBar( - snackbarMessages.undoMsg ? snackbarMessages.undoMsg : snackbarMessages.successMsg, - dispatch, - undefined, - true, - false, - true, - ) + snackbar.show(GenerateFolderMessage(t, currentFolder, folders, true, false)) setNewCurrentFolderID(folderWhereMessagePreviousewas.current) folderWhereMessageIs.current = folderWhereMessagePreviousewas.current }, onError: () => { - showSnackBar( - snackbarMessages.undoErrorMsg ? snackbarMessages.undoErrorMsg : snackbarMessages.errorMsg, - dispatch, - () => moveMessage(undoParams, undoMutateOptions), - false, - true, - true, - ) + snackbar.show(GenerateFolderMessage(t, currentFolder, folders, true, true), { + isError: true, + onActionPressed: () => moveMessage(undoParams, undoMutateOptions), + }) setNewCurrentFolderID(folderWhereMessagePreviousewas.current) folderWhereMessageIs.current = folderWhereMessagePreviousewas.current }, } moveMessage(undoParams, undoMutateOptions) }, - false, - false, - true, - ) + }) }, onError: () => { - showSnackBar( - snackbarMessages.undoErrorMsg ? snackbarMessages.undoErrorMsg : snackbarMessages.errorMsg, - dispatch, - () => moveMessage(params, mutateOptions), - false, - true, - true, - ) + snackbar.show(GenerateFolderMessage(t, currentFolder, folders, true, true), { + isError: true, + onActionPressed: () => moveMessage(params, mutateOptions), + }) setNewCurrentFolderID(folderWhereMessagePreviousewas.current) folderWhereMessageIs.current = folderWhereMessagePreviousewas.current }, diff --git a/VAMobile/src/screens/HomeScreen/HomeScreen.tsx b/VAMobile/src/screens/HomeScreen/HomeScreen.tsx index 54512751724..163b70aff24 100644 --- a/VAMobile/src/screens/HomeScreen/HomeScreen.tsx +++ b/VAMobile/src/screens/HomeScreen/HomeScreen.tsx @@ -8,6 +8,7 @@ import { useIsFocused } from '@react-navigation/native' import { CardStyleInterpolators, createStackNavigator } from '@react-navigation/stack' import { StackScreenProps } from '@react-navigation/stack/lib/typescript/src/types' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { Icon, IconProps } from '@department-of-veterans-affairs/mobile-component-library/src/components/Icon/Icon' import { colors as DSColors } from '@department-of-veterans-affairs/mobile-tokens' import { DateTime } from 'luxon' @@ -41,7 +42,6 @@ import { } from 'components' import { Events } from 'constants/analytics' import { TimeFrameTypeConstants } from 'constants/appointments' -import { CloseSnackbarOnNavigation } from 'constants/common' import { NAMESPACE } from 'constants/namespaces' import { FEATURE_LANDING_TEMPLATE_OPTIONS } from 'constants/screens' import { FolderNameTypeConstants } from 'constants/secureMessaging' @@ -534,6 +534,7 @@ const HomeScreenStack = createStackNavigator() * Stack screen for the Home tab. Screens placed within this stack will appear in the context of the app level tab navigator */ function HomeStackScreen({}: HomeStackScreenProps) { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const screenOptions = { headerShown: false, @@ -547,11 +548,11 @@ function HomeStackScreen({}: HomeStackScreenProps) { screenListeners={{ transitionStart: (e) => { if (e.data.closing) { - CloseSnackbarOnNavigation(e.target) + snackbar.hide() } }, - blur: (e) => { - CloseSnackbarOnNavigation(e.target) + blur: () => { + snackbar.hide() }, }}> diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/AddressValidation/AddressValidation.test.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/AddressValidation/AddressValidation.test.tsx index 16a395fa533..496a2bc80f6 100644 --- a/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/AddressValidation/AddressValidation.test.tsx +++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/AddressValidation/AddressValidation.test.tsx @@ -4,9 +4,9 @@ import { fireEvent, screen } from '@testing-library/react-native' import { t } from 'i18next' import { AddressData, ValidateAddressData } from 'api/types' -import { SnackbarMessages } from 'components/SnackBar' import { render } from 'testUtils' +import { profileAddressOptions } from '../AddressSummary' import AddressValidation from './AddressValidation' const mockAddress: AddressData = { @@ -20,11 +20,6 @@ const mockAddress: AddressData = { zipCode: '95403', } -const snackbarMessages: SnackbarMessages = { - successMsg: 'Address saved', - errorMsg: 'Address could not be saved', -} - const validationData: ValidateAddressData = { confirmedSuggestedAddresses: [ { @@ -76,7 +71,7 @@ describe('AddressValidation', () => { setShowAddressValidation: (shouldShow: boolean) => void @@ -33,12 +34,12 @@ export type AddressValidationProps = { function AddressValidation({ addressEntered, addressId, - snackbarMessages, + addressType, validationData, saveAddress, setShowAddressValidation, }: AddressValidationProps) { - const dispatch = useAppDispatch() + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const navigation = useNavigation() const theme = useTheme() @@ -109,8 +110,13 @@ function AddressValidation({ const save = () => { const mutateOptions = { - onSuccess: () => showSnackBar(snackbarMessages.successMsg, dispatch, undefined, true, false, true), - onError: () => showSnackBar(snackbarMessages.errorMsg, dispatch, () => save, false, true), + onSuccess: () => snackbar.show(GenerateAddressMessage(t, addressType, false)), + onError: () => + snackbar.show(GenerateAddressMessage(t, addressType, true), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => save, + }), } saveAddress({ addressData, revalidate }, mutateOptions) } diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/EditAddressScreen/EditAddressScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/EditAddressScreen/EditAddressScreen.tsx index 0cc8459b7ef..786dad1e1c1 100644 --- a/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/EditAddressScreen/EditAddressScreen.tsx +++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/EditAddressScreen/EditAddressScreen.tsx @@ -4,7 +4,7 @@ import { ScrollView, TextInput } from 'react-native' import { StackScreenProps } from '@react-navigation/stack/lib/typescript/src/types' -import { Button, ButtonVariants } from '@department-of-veterans-affairs/mobile-component-library' +import { Button, ButtonVariants, useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { RootNavStackParamList } from 'App' import { useContactInformation } from 'api/contactInformation' @@ -22,15 +22,13 @@ import { VATextInputTypes, ValidationFunctionItems, } from 'components' -import { SnackbarMessages } from 'components/SnackBar' import { Countries } from 'constants/countries' import { MilitaryPostOffices } from 'constants/militaryPostOffices' import { MilitaryStates } from 'constants/militaryStates' import { NAMESPACE } from 'constants/namespaces' import { States } from 'constants/states' -import { GenerateAddressMessages } from 'translations/en/functions' -import { showSnackBar } from 'utils/common' -import { useAlert, useAppDispatch, useBeforeNavBackListener, useDestructiveActionSheet, useTheme } from 'utils/hooks' +import { GenerateAddressMessage } from 'translations/en/functions' +import { useAlert, useBeforeNavBackListener, useDestructiveActionSheet, useTheme } from 'utils/hooks' import { getAddressDataPayload } from 'utils/personalInformation' import { profileAddressOptions } from '../AddressSummary' @@ -79,9 +77,9 @@ export type AddressDataEditedFields = type IEditAddressScreen = StackScreenProps function EditAddressScreen({ navigation, route }: IEditAddressScreen) { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const theme = useTheme() - const dispatch = useAppDispatch() const { displayTitle, addressType } = route.params const { data: contactInformation } = useContactInformation() const { mutate: deleteAddress, isPending: deletingAddress, isSuccess: addressDeleted } = useDeleteAddress() @@ -97,13 +95,6 @@ function EditAddressScreen({ navigation, route }: IEditAddressScreen) { const zipCodeRef = useRef(null) const cityRef = useRef(null) - const snackbarMessages: SnackbarMessages = GenerateAddressMessages(t, addressType) - - const removalSnackbarMessages: SnackbarMessages = { - successMsg: t('contactInformation.residentialAddress.removed'), - errorMsg: t('contactInformation.residentialAddress.removed.error'), - } - const getInitialState = (itemToGet: AddressDataEditedFields): string => { const item = contactInformation?.[addressType]?.[itemToGet] return item ? item : '' @@ -220,15 +211,13 @@ function EditAddressScreen({ navigation, route }: IEditAddressScreen) { } const mutateOptions = { - onSuccess: () => showSnackBar(removalSnackbarMessages.successMsg, dispatch, undefined, true, false, true), + onSuccess: () => snackbar.show(t('contactInformation.residentialAddress.removed')), onError: () => - showSnackBar( - removalSnackbarMessages.errorMsg, - dispatch, - () => deleteAddress(currentAddressData, mutateOptions), - false, - true, - ), + snackbar.show(t('contactInformation.residentialAddress.removed.error'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => deleteAddress, + }), } deleteAddress(currentAddressData, mutateOptions) } @@ -282,10 +271,15 @@ function EditAddressScreen({ navigation, route }: IEditAddressScreen) { setShowAddressValidation(true) } else { setAddressValidated(true) - showSnackBar(snackbarMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(GenerateAddressMessage(t, addressType, false)) } }, - onError: () => showSnackBar(snackbarMessages.errorMsg, dispatch, () => save, false, true), + onError: () => + snackbar.show(GenerateAddressMessage(t, addressType, true), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => save, + }), }, ) } @@ -578,7 +572,7 @@ function EditAddressScreen({ navigation, route }: IEditAddressScreen) { @@ -30,7 +29,7 @@ type EditEmailScreenProps = StackScreenProps * Screen for editing a users email in the personal info section */ function EditEmailScreen({ navigation }: EditEmailScreenProps) { - const dispatch = useAppDispatch() + const snackbar = useSnackbar() const theme = useTheme() const { t } = useTranslation(NAMESPACE.COMMON) const { data: contactInformation } = useContactInformation() @@ -56,11 +55,6 @@ function EditEmailScreen({ navigation }: EditEmailScreenProps) { setSaveDisabled(formContainsError) }, [formContainsError]) - const saveSnackbarMessages: SnackbarMessages = { - successMsg: t('contactInformation.emailAddress.saved'), - errorMsg: t('contactInformation.emailAddress.not.saved'), - } - useBeforeNavBackListener(navigation, (e) => { if (noPageChanges()) { return @@ -100,20 +94,21 @@ function EditEmailScreen({ navigation }: EditEmailScreenProps) { const mutateOptions = { onSuccess: () => { - showSnackBar(saveSnackbarMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(t('contactInformation.emailAddress.saved')) }, onError: (error: unknown) => { if (isErrorObject(error)) { if (error.status === 400) { - showSnackBar(saveSnackbarMessages.errorMsg, dispatch, undefined, true, true) + snackbar.show(t('contactInformation.emailAddress.not.saved'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + }) } else { - showSnackBar( - saveSnackbarMessages.errorMsg, - dispatch, - () => saveEmail(emailData, mutateOptions), - false, - true, - ) + snackbar.show(t('contactInformation.emailAddress.not.saved'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => saveEmail(emailData, mutateOptions), + }) } } }, @@ -121,11 +116,6 @@ function EditEmailScreen({ navigation }: EditEmailScreenProps) { saveEmail(emailData, mutateOptions) } - const removeSnackbarMessages: SnackbarMessages = { - successMsg: t('contactInformation.emailAddress.removed'), - errorMsg: t('contactInformation.emailAddress.not.removed'), - } - const onDelete = (): void => { const originalEmail = contactInformation?.contactEmail?.emailAddress @@ -140,15 +130,13 @@ function EditEmailScreen({ navigation }: EditEmailScreenProps) { } const mutateOptions = { - onSuccess: () => showSnackBar(removeSnackbarMessages.successMsg, dispatch, undefined, true, false, true), + onSuccess: () => snackbar.show(t('contactInformation.emailAddress.removed')), onError: () => - showSnackBar( - removeSnackbarMessages.errorMsg, - dispatch, - () => deleteEmail(emailData, mutateOptions), - false, - true, - ), + snackbar.show(t('contactInformation.emailAddress.not.removed'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => deleteEmail(emailData, mutateOptions), + }), } deleteEmail(emailData, mutateOptions) } diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/EditPhoneNumberScreen/EditPhoneNumberScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/EditPhoneNumberScreen/EditPhoneNumberScreen.tsx index 99c72e77d9c..bc3cb21e1e8 100644 --- a/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/EditPhoneNumberScreen/EditPhoneNumberScreen.tsx +++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/ContactInformationScreen/EditPhoneNumberScreen/EditPhoneNumberScreen.tsx @@ -4,7 +4,7 @@ import { ScrollView } from 'react-native' import { StackScreenProps } from '@react-navigation/stack' -import { Button, ButtonVariants } from '@department-of-veterans-affairs/mobile-component-library' +import { Button, ButtonVariants, useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { useDeletePhoneNumber, useSavePhoneNumber } from 'api/contactInformation' import { useContactInformation } from 'api/contactInformation/getContactInformation' @@ -18,18 +18,17 @@ import { FullScreenSubtask, LoadingComponent, } from 'components' -import { SnackbarMessages } from 'components/SnackBar' import { MAX_DIGITS, MAX_DIGITS_AFTER_FORMAT } from 'constants/common' import { NAMESPACE } from 'constants/namespaces' import { HomeStackParamList } from 'screens/HomeScreen/HomeStackScreens' -import { getFormattedPhoneNumber, isErrorObject, showSnackBar } from 'utils/common' +import { getFormattedPhoneNumber, isErrorObject } from 'utils/common' import { formatPhoneNumber, getNumbersFromString } from 'utils/formattingUtils' -import { useAlert, useAppDispatch, useBeforeNavBackListener, useDestructiveActionSheet, useTheme } from 'utils/hooks' +import { useAlert, useBeforeNavBackListener, useDestructiveActionSheet, useTheme } from 'utils/hooks' type IEditPhoneNumberScreen = StackScreenProps function EditPhoneNumberScreen({ navigation, route }: IEditPhoneNumberScreen) { - const dispatch = useAppDispatch() + const snackbar = useSnackbar() const theme = useTheme() const { t } = useTranslation(NAMESPACE.COMMON) const { displayTitle, phoneType, phoneData } = route.params @@ -55,11 +54,6 @@ function EditPhoneNumberScreen({ navigation, route }: IEditPhoneNumberScreen) { } }, [phoneNumberDeleted, phoneNumberSaved, navigation]) - const saveSnackbarMessages: SnackbarMessages = { - successMsg: t('contactInformation.phoneNumber.saved', { type: displayTitle }), - errorMsg: t('contactInformation.phoneNumber.not.saved', { type: displayTitle }), - } - useBeforeNavBackListener(navigation, (e) => { if (noPageChanges()) { return @@ -130,10 +124,15 @@ function EditPhoneNumberScreen({ navigation, route }: IEditPhoneNumberScreen) { const save = (): void => { const mutateOptions = { onSuccess: () => { - showSnackBar(saveSnackbarMessages.successMsg, dispatch, undefined, true, false, true) + snackbar.show(t('contactInformation.phoneNumber.saved', { type: displayTitle })) }, onError: (error: unknown) => - isErrorObject(error) && showSnackBar(saveSnackbarMessages.errorMsg, dispatch, save, false, true, true), + isErrorObject(error) && + snackbar.show(t('contactInformation.phoneNumber.not.saved', { type: displayTitle }), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: save, + }), } savePhoneNumber(phoneDataPayload, mutateOptions) } @@ -141,25 +140,17 @@ function EditPhoneNumberScreen({ navigation, route }: IEditPhoneNumberScreen) { save() } - const removeSnackbarMessages: SnackbarMessages = { - successMsg: t('contactInformation.phoneNumber.removed', { type: displayTitle }), - errorMsg: t('contactInformation.phoneNumber.not.removed', { type: displayTitle }), - } - const onDelete = (): void => { if (phoneData) { const mutateOptions = { - onSuccess: () => showSnackBar(removeSnackbarMessages.successMsg, dispatch, undefined, true, false, true), + onSuccess: () => snackbar.show(t('contactInformation.phoneNumber.removed', { type: displayTitle })), onError: (error: unknown) => isErrorObject(error) && - showSnackBar( - removeSnackbarMessages.errorMsg, - dispatch, - () => deletePhoneNumber(phoneData, mutateOptions), - false, - true, - true, - ), + snackbar.show(t('contactInformation.phoneNumber.not.removed', { type: displayTitle }), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: () => deletePhoneNumber(phoneData, mutateOptions), + }), } deletePhoneNumber(phoneData, mutateOptions) } diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/GenderIdentityScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/GenderIdentityScreen.tsx index 2362cc268ca..f6bfdcf69d3 100644 --- a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/GenderIdentityScreen.tsx +++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/GenderIdentityScreen/GenderIdentityScreen.tsx @@ -4,6 +4,8 @@ import { Pressable } from 'react-native' import { StackScreenProps } from '@react-navigation/stack/lib/typescript/src/types' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' + import { useDemographics } from 'api/demographics/getDemographics' import { useGenderIdentityOptions } from 'api/demographics/getGenderIdentityOptions' import { useUpdateGenderIdentity } from 'api/demographics/updateGenderIdentity' @@ -17,15 +19,12 @@ import { TextView, radioOption, } from 'components' -import { SnackbarMessages } from 'components/SnackBar' import { Events } from 'constants/analytics' import { NAMESPACE } from 'constants/namespaces' import { HomeStackParamList } from 'screens/HomeScreen/HomeStackScreens' import { ScreenIDTypesConstants } from 'store/api/types/Screens' import { logAnalyticsEvent } from 'utils/analytics' -import { showSnackBar } from 'utils/common' import { - useAppDispatch, useBeforeNavBackListener, useDestructiveActionSheet, useDowntimeByScreenID, @@ -51,10 +50,10 @@ function GenderIdentityScreen({ navigation }: GenderIdentityScreenProps) { error: getGenderIdentityOptionsError, refetch: refetchGenderIdentityOptions, } = useGenderIdentityOptions() + const snackbar = useSnackbar() const genderIdentityMutation = useUpdateGenderIdentity() const theme = useTheme() const { t } = useTranslation(NAMESPACE.COMMON) - const dispatch = useAppDispatch() const navigateTo = useRouteNavigation() const confirmAlert = useDestructiveActionSheet() const genderIdentityInDowntime = useDowntimeByScreenID(ScreenIDTypesConstants.GENDER_IDENTITY_SCREEN_ID) @@ -62,11 +61,6 @@ function GenderIdentityScreen({ navigation }: GenderIdentityScreenProps) { const [error, setError] = useState('') const [genderIdentity, setGenderIdentity] = useState(demographics?.genderIdentity) - const snackbarMessages: SnackbarMessages = { - successMsg: t('personalInformation.genderIdentity.saved'), - errorMsg: t('personalInformation.genderIdentity.not.saved'), - } - useEffect(() => { if (genderIdentityMutation.isSuccess) { navigation.goBack() @@ -103,8 +97,13 @@ function GenderIdentityScreen({ navigation }: GenderIdentityScreenProps) { const updateGenderIdentity = () => { if (genderIdentity) { const mutateOptions = { - onSuccess: () => showSnackBar(snackbarMessages.successMsg, dispatch, undefined, true, false, true), - onError: () => showSnackBar(snackbarMessages.errorMsg, dispatch, updateGenderIdentity, false, true, true), + onSuccess: () => snackbar.show(t('personalInformation.genderIdentity.saved')), + onError: () => + snackbar.show(t('personalInformation.genderIdentity.not.saved'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: updateGenderIdentity, + }), } genderIdentityMutation.mutate(genderIdentity, mutateOptions) } diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PreferredNameScreen/PreferredNameScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PreferredNameScreen/PreferredNameScreen.tsx index ac10720d395..0c89a4a90b6 100644 --- a/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PreferredNameScreen/PreferredNameScreen.tsx +++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/PersonalInformationScreen/PreferredNameScreen/PreferredNameScreen.tsx @@ -3,25 +3,25 @@ import { useTranslation } from 'react-i18next' import { StackScreenProps } from '@react-navigation/stack/lib/typescript/src/types' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' + import { useDemographics } from 'api/demographics/getDemographics' import { useUpdatePreferredName } from 'api/demographics/updatePreferredName' import { Box, FieldType, FormFieldType, FormWrapper, FullScreenSubtask, LoadingComponent } from 'components' -import { SnackbarMessages } from 'components/SnackBar' import { NAMESPACE } from 'constants/namespaces' import { HomeStackParamList } from 'screens/HomeScreen/HomeStackScreens' -import { showSnackBar } from 'utils/common' import { stringToTitleCase } from 'utils/formattingUtils' -import { useAppDispatch, useDestructiveActionSheet, useTheme } from 'utils/hooks' +import { useDestructiveActionSheet, useTheme } from 'utils/hooks' type PreferredNameScreenProps = StackScreenProps const MAX_NAME_LENGTH = 25 function PreferredNameScreen({ navigation }: PreferredNameScreenProps) { + const snackbar = useSnackbar() const { data: demographics } = useDemographics() const preferredNameMutation = useUpdatePreferredName() const { t } = useTranslation(NAMESPACE.COMMON) - const dispatch = useAppDispatch() const theme = useTheme() const confirmAlert = useDestructiveActionSheet() @@ -34,11 +34,6 @@ function PreferredNameScreen({ navigation }: PreferredNameScreenProps) { const [onSaveClicked, setOnSaveClicked] = useState(false) const [resetErrors, setResetErrors] = useState(false) - const snackbarMessages: SnackbarMessages = { - successMsg: t('personalInformation.preferredName.saved'), - errorMsg: t('personalInformation.preferredName.notSaved'), - } - const onConfirmCancel = (): void => { if (preferredName !== getInitialState()) { confirmAlert({ @@ -68,10 +63,15 @@ function PreferredNameScreen({ navigation }: PreferredNameScreenProps) { const updatePreferredName = () => { const mutateOptions = { onSuccess: () => { - showSnackBar(snackbarMessages.successMsg, dispatch, undefined, true, false) + snackbar.show(t('personalInformation.preferredName.saved')) navigation.goBack() }, - onError: () => showSnackBar(snackbarMessages.errorMsg, dispatch, updatePreferredName, false, true, true), + onError: () => + snackbar.show(t('personalInformation.preferredName.notSaved'), { + isError: true, + offset: theme.dimensions.snackBarBottomOffset, + onActionPressed: updatePreferredName, + }), } preferredNameMutation.mutate(preferredName, mutateOptions) } diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/DeveloperScreen/DeveloperScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/DeveloperScreen/DeveloperScreen.tsx index 54e919c660f..50916d7196f 100644 --- a/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/DeveloperScreen/DeveloperScreen.tsx +++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/DeveloperScreen/DeveloperScreen.tsx @@ -7,6 +7,7 @@ import { useFocusEffect } from '@react-navigation/native' import { StackScreenProps } from '@react-navigation/stack' import { Button } from '@department-of-veterans-affairs/mobile-component-library' +import { useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { pick } from 'underscore' import { useAuthorizedServices } from 'api/authorizedServices/getAuthorizedServices' @@ -27,7 +28,6 @@ import { RootState } from 'store' import { AnalyticsState } from 'store/slices' import { toggleFirebaseDebugMode } from 'store/slices/analyticsSlice' import { AuthState, debugResetFirstTimeLogin } from 'store/slices/authSlice' -import { showSnackBar } from 'utils/common' import getEnv, { EnvVars } from 'utils/env' import { FeatureConstants, @@ -43,6 +43,7 @@ import { STORAGE_REVIEW_EVENT_KEY, resetReviewActionCount } from 'utils/inAppRev type DeveloperScreenSettingsScreenProps = StackScreenProps function DeveloperScreen({ navigation }: DeveloperScreenSettingsScreenProps) { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const { authCredentials } = useSelector((state) => state.auth) const { data: userAuthorizedServices } = useAuthorizedServices() @@ -152,9 +153,9 @@ function DeveloperScreen({ navigation }: DeveloperScreenSettingsScreenProps) { try { await resetReviewActionCount() getAsyncStoredData(STORAGE_REVIEW_EVENT_KEY, setReviewCount) - showSnackBar('In app review actions reset', dispatch, undefined, true, false, true) + snackbar.show('In app review actions reset') } catch { - showSnackBar('Failed to reset in app review actions', dispatch, resetInAppReview, false, true) + snackbar.show('Failed to reset in app review actions', { isError: true, onActionPressed: resetInAppReview }) } } diff --git a/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/DeveloperScreen/RemoteConfigScreen.tsx b/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/DeveloperScreen/RemoteConfigScreen.tsx index 9043e7bf6c0..e36a89bf5b0 100644 --- a/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/DeveloperScreen/RemoteConfigScreen.tsx +++ b/VAMobile/src/screens/HomeScreen/ProfileScreen/SettingsScreen/DeveloperScreen/RemoteConfigScreen.tsx @@ -5,7 +5,7 @@ import remoteConfig from '@react-native-firebase/remote-config' import { useIsFocused } from '@react-navigation/native' import { StackScreenProps } from '@react-navigation/stack' -import { Button } from '@department-of-veterans-affairs/mobile-component-library' +import { Button, useSnackbar } from '@department-of-veterans-affairs/mobile-component-library' import { forEach } from 'underscore' import { @@ -21,7 +21,6 @@ import { import { NAMESPACE } from 'constants/namespaces' import { HomeStackParamList } from 'screens/HomeScreen/HomeStackScreens' import { logout } from 'store/slices/authSlice' -import { showSnackBar } from 'utils/common' import { useAppDispatch, useRouteNavigation, useTheme } from 'utils/hooks' import { FeatureToggleType, getFeatureToggles, setDebugConfig } from 'utils/remoteConfig' import { getWaygateToggles, setWaygateDebugConfig } from 'utils/waygateConfig' @@ -29,6 +28,7 @@ import { getWaygateToggles, setWaygateDebugConfig } from 'utils/waygateConfig' type RemoteConfigScreenSettingsScreenProps = StackScreenProps function RemoteConfigScreen({ navigation }: RemoteConfigScreenSettingsScreenProps) { + const snackbar = useSnackbar() const { t } = useTranslation(NAMESPACE.COMMON) const theme = useTheme() const dispatch = useAppDispatch() @@ -137,7 +137,7 @@ function RemoteConfigScreen({ navigation }: RemoteConfigScreenSettingsScreenProp