diff --git a/src/constants/application-config.js b/src/constants/application-config.js index 7799506f..1e5ee6d8 100644 --- a/src/constants/application-config.js +++ b/src/constants/application-config.js @@ -23,7 +23,10 @@ const applicationConfig = Object.freeze({ YAHOO_CALENDAR: 'https://calendar.yahoo.com/?v=60', OUTLOOK_CALENDAR: 'https://outlook.office.com/calendar/deeplink/compose?path=/calendar/action/compose&rru=addevent', - FRONTEND_LOGGER_PATH: "/analytics/api/v1/logging" + FRONTEND_LOGGER_PATH: "/analytics/api/v1/logging", + BAILOUT_ON_APPLICATION_ERROR: true, + BAILOUT_ON_API_ERROR: true, + BAILOUT_ON_ROUTER_ERROR: true }); export default applicationConfig; diff --git a/src/constants/bailoutCode.js b/src/constants/bailoutCode.js index fb1ac071..f108570a 100644 --- a/src/constants/bailoutCode.js +++ b/src/constants/bailoutCode.js @@ -12,7 +12,10 @@ const bailoutCode = Object.freeze({ NoPartsAvailable: 10, PartsServiceError: 11, SafeliteNotTheProvider: 12, - VehicleYMMSLookupError: 13 + VehicleYMMSLookupError: 13, + ApplicationError: 14, + ApiError: 15, + RouterError: 16 }); export default bailoutCode; diff --git a/src/constants/bailoutMessage.js b/src/constants/bailoutMessage.js index 1daa702e..77292a1e 100644 --- a/src/constants/bailoutMessage.js +++ b/src/constants/bailoutMessage.js @@ -17,6 +17,18 @@ const bailoutMessage = Object.freeze({ code: bailoutCode.Unknown, message: `An unknown bailout occurred: ${getItemData(error)}` }), + applicationError: (error) => ({ + code: bailoutCode.ApplicationError, + message: `An application error occurred: ${getItemData(error)}` + }), + apiError: (error) => ({ + code: bailoutCode.ApiError, + message: `An API error occurred: ${getItemData(error)}` + }), + routerError: (error) => ({ + code: bailoutCode.RouterError, + message: `A router error occurred: ${getItemData(error)}` + }), saveSessionError: (error) => ({ code: bailoutCode.SaveSessionError, message: `An error occurred during save session: ${getItemData(error)}` diff --git a/src/global-methods.js b/src/global-methods.js index bf515f6c..280f318d 100644 --- a/src/global-methods.js +++ b/src/global-methods.js @@ -15,10 +15,6 @@ axios.interceptors.response.use( if (typeof error.response === 'undefined') { // The request was not made, could be a bad url, bad connection or a CORS error. rejectionError = { - message: - 'A network error occurred. ' - + 'This could be a CORS issue or a dropped internet connection. ' - + 'It is impossible for us to know.', cause: error, response: error, message: axiosResponseInterceptorMessages.NETWORK_ERROR @@ -51,7 +47,7 @@ axios.interceptors.response.use( ); export default { - callHttpClient({ method, endpoint, payload, logApiCall = true }) { + callHttpClient({ method, endpoint, payload, logApiCall = true, bailoutOnError = true }) { return new Promise((resolve, reject) => { const store = useMainStore(); const cfDistroUrl = applicationConfig.CONSUMER_CF_DISTRO; @@ -66,9 +62,10 @@ export default { [headerKeys.SESSION_SEQUENCE_NUMBER]: sessionKey }; + const url = cfDistroUrl + endpoint; axios({ method, - url: cfDistroUrl + endpoint, + url, data: payloadAndAnalyticsData, crossDomain: true, responseType: 'json', @@ -97,10 +94,11 @@ export default { } if (error.response.status !== 404) { - global.$logger.logError( - `${method}: ${endpoint}: ${error.message}`, - error.response - ); + global.$logger.logError(`${method}: ${endpoint}: ${error.message}`, error.response); + if (bailoutOnError && global.bailoutOnAxiosError !== undefined) + { + global.bailoutOnAxiosError({ url, error }); + } } return reject(error.response); } diff --git a/src/main.js b/src/main.js index e1c788be..243335b9 100644 --- a/src/main.js +++ b/src/main.js @@ -14,6 +14,8 @@ import router from './router'; import App from './App.vue'; import Logger from "@/helpers/logger"; +import bailoutMessage from '@/constants/bailoutMessage'; +import applicationConfig from '@/constants/application-config'; // Instantiate global logging object global.$logger = new Logger(); @@ -46,15 +48,26 @@ function getPageName(vm) { // Vue Error Handling vueApp.config.errorHandler = (err, vm, info) => { const pageName = getPageName(vm); - global.$logger.logError( - `Page Name - ${pageName} - ${info}: ${err.message}\n${err.stack}` - ); + global.$logger.logError(`Page Name - ${pageName} - ${info}: ${err.message}\n${err.stack}`); + if (applicationConfig.BAILOUT_ON_APPLICATION_ERROR) { + router.navigateBailout(bailoutMessage.applicationError(`[${pageName}] ${info}: ${err.message}\n${err.stack}`)); + } }; // Vue Router Error Handling router.onError((err) => { global.$logger.logError(err.message, err.cause); + if (applicationConfig.BAILOUT_ON_ROUTER_ERROR) { + router.navigateBailout(bailoutMessage.routerError(`${err.message}\n${err.stack}`)); + } }); + +global.bailoutOnAxiosError = (error) => { + if (applicationConfig.BAILOUT_ON_API_ERROR) { + router.navigateBailout(bailoutMessage.apiError(error)); + } +} + vueApp.mount('#app'); // define global rules diff --git a/src/router/index.js b/src/router/index.js index b611694f..cd77544f 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -281,7 +281,10 @@ function navigate( } // Match our maps up and navigate if we have a destination. - const matchingScenarioMap = getNavigationMap(scenario, currentRoute); + let matchingScenarioMap = getNavigationMap(scenario, currentRoute); + if (!matchingScenarioMap && scenario === navigationScenarios.BAILOUT) { + matchingScenarioMap = { destinationIssPageValue: issPageValues.BAILOUT_PAGE } + } if (!matchingScenarioMap) { window.console.error('No matching scenario found. Please review the routing table.'); @@ -332,6 +335,18 @@ function navigateToUrl(url, optionalQuery = {}) { window.location.assign(externalUrl); } +router.navigateBailout = (bailoutData = null) => { + if (bailoutData != null && !useMainStore().isBailout) { + useMainStore().setBailout(bailoutData) + } + router.navigate( + navigationScenarios.BAILOUT, + router.currentRoute.value, + {}, + { [routerParams.SKIP_SAVE_SESSION]: true } + ); +} + // Get navigation map depending on the scenario and the current 'page' you're on. function getNavigationMap(scenario, currentRoute) { const issPageValue = currentRoute.query.issPage; diff --git a/src/router/router-constants/navigation-scenarios.js b/src/router/router-constants/navigation-scenarios.js index d6fba845..f0603b96 100644 --- a/src/router/router-constants/navigation-scenarios.js +++ b/src/router/router-constants/navigation-scenarios.js @@ -114,6 +114,7 @@ const navigationScenarios = Object.freeze({ // Bailout CLICKED_FORWARD_WITH_BAILOUT: 'CLICKED_FORWARD_WITH_BAILOUT', CLICKED_NEED_HELP_WITH_BAILOUT: 'CLICKED_NEED_HELP_WITH_BAILOUT', + BAILOUT: 'BAILOUT' }); export default navigationScenarios; diff --git a/src/store/index.js b/src/store/index.js index 34d77533..3e3b8a57 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -879,8 +879,7 @@ export const useMainStore = defineStore({ return globalMethods.callHttpClient({ method: endpoints.GetMobilePremiumFee.method, - endpoint: `${endpoints.GetMobilePremiumFee.url}/${paymentType}/${damageType}`, - logApiCall: true + endpoint: `${endpoints.GetMobilePremiumFee.url}/${paymentType}/${damageType}` }); }, getMobileTimeSlots(startDate, endDate, zipCodeOverride = null) { @@ -935,14 +934,7 @@ export const useMainStore = defineStore({ return globalMethods.callHttpClient({ method: endpoints.GetMobileTimeSlots.method, endpoint: endpoints.GetMobileTimeSlots.url, - payload, - logApiCall: true, - additionalSuccessEventDataHandler: (response) => - getTimeSlotsAdditionalEventData( - response.data.provisionalTriggers, - zipCodeOverride ?? order.serviceLocation.zipCode, - response.data.days?.[0]?.date - ) + payload }); }, getShopTimeSlots(startDate, endDate, shopAppointmentType, providerNumber) { @@ -998,8 +990,7 @@ export const useMainStore = defineStore({ return globalMethods.callHttpClient({ method: endpoints.GetShopTimeSlots.method, endpoint: endpoints.GetShopTimeSlots.url, - payload, - additionalSuccessEventDataHandler: (response) => provisionalTriggersToString(response.data.provisionalTriggers) + payload }); }, async getWipers() { @@ -1553,8 +1544,7 @@ export const useMainStore = defineStore({ method: endpoints.SaveSession.method, endpoint: endpoints.SaveSession.url, payload, - additionalSuccessEventDataHandler: () => - `Email provided: ${customer.emailAddress ? 'true' : 'false'}` + bailoutOnError: false }).then((response) => { if (loadedFromDupeCheck) { this.order.loadedSessionClearedPreviousData = true; @@ -2466,8 +2456,7 @@ export const useMainStore = defineStore({ return globalMethods.callHttpClient({ method: endpoints.GetAlertReasons.method, endpoint: `${endpoints.GetAlertReasons.url}/${ctu}`, - payload: {}, - logApiCall: true + payload: {} }); },