diff --git a/public/static/assets/Urbanist-Regular.woff b/public/static/assets/Urbanist-Regular.woff
new file mode 100644
index 000000000..7efe9bc42
Binary files /dev/null and b/public/static/assets/Urbanist-Regular.woff differ
diff --git a/public/static/assets/Urbanist-SemiBold.woff b/public/static/assets/Urbanist-SemiBold.woff
new file mode 100644
index 000000000..92949770b
Binary files /dev/null and b/public/static/assets/Urbanist-SemiBold.woff differ
diff --git a/public/static/assets/logo.svg b/public/static/assets/logo.svg
new file mode 100644
index 000000000..8f739ca15
--- /dev/null
+++ b/public/static/assets/logo.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/public/static/error/index.html b/public/static/error/index.html
new file mode 100644
index 000000000..a4c141f85
--- /dev/null
+++ b/public/static/error/index.html
@@ -0,0 +1,299 @@
+
+
+
+
+ Error - Safelite
+
+
+
+
+
+
+
+
+ We encountered an error while processing your appointment. You can return to our site and try scheduling again below.
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/global-methods.js b/src/global-methods.js
index 0bd0549ea..fc0b3cb41 100644
--- a/src/global-methods.js
+++ b/src/global-methods.js
@@ -121,7 +121,7 @@ export default {
endpoint: endpoint,
};
- router.bailout(errorPayload);
+ router.handleSoftError(errorPayload);
// do not log 404 errors from services because we return NotFound
// when a service doesn't return an object
diff --git a/src/global-methods.spec.js b/src/global-methods.spec.js
index c09bf8e97..c8c4d6da9 100644
--- a/src/global-methods.spec.js
+++ b/src/global-methods.spec.js
@@ -38,7 +38,7 @@ it("Global Methods - Call Http Client - Should Reject Promise", () => {
isError: true,
});
analyticsMixIn.methods.pushEventToGA = jest.fn();
- router.bailout = jest.fn();
+ router.handleSoftError = jest.fn();
//Act
globalMethods.callHttpClient(httpArgs).catch((err) => {
diff --git a/src/router/constants/routes.js b/src/router/constants/routes.js
index 5632fe357..98d6c503a 100644
--- a/src/router/constants/routes.js
+++ b/src/router/constants/routes.js
@@ -112,7 +112,6 @@ export const routeData = {
path: "/virtual/auto-route",
virtual: true,
},
- // TODO: RENAME FROM BAILOUT
ERROR: {
name: "error",
path: "/virtual/error",
diff --git a/src/router/index.js b/src/router/index.js
index cd842c5cb..aa07a7a0b 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,7 +1,7 @@
import { routes } from "@/router/methods/routes";
import { afterEach } from "@/router/methods/after-each";
import { beforeEach } from "@/router/methods/before-each";
-import { bailout } from "@/router/methods/error";
+import { handleSoftError, handleHardError } from "@/router/methods/error";
import {
navigateWithoutSaving,
navigateWithSaving,
@@ -32,7 +32,8 @@ router.navigateWithoutSaving = navigateWithoutSaving;
router.navigateWithPageData = navigateWithPageData;
router.navigateAndForceTopLevelNavigation = navigateAndForceTopLevelNavigation;
-router.bailout = bailout;
+router.handleSoftError = handleSoftError;
+router.handleHardError = handleHardError;
router.navigateToExternalUrl = navigateToExternalUrl;
diff --git a/src/router/methods/before-each.js b/src/router/methods/before-each.js
index e742f89ff..67a6ecf84 100644
--- a/src/router/methods/before-each.js
+++ b/src/router/methods/before-each.js
@@ -8,7 +8,7 @@ import analyticsMixin from "@/mixins/analytics-mixin";
import { routeData, FUNNEL_START_PAGE } from "@/router/constants/routes";
import { runExperiments } from "@/router/methods/helpers/run-experiments";
-import { bailout } from "@/router/methods/error";
+import { handleSoftError, handleHardError } from "@/router/methods/error";
import { checkPagePrerequisites } from "@/router/methods/page-prerequisites";
import { checkLogParam } from "@/helpers/debug-log-helper";
import { debugLog } from "@/helpers/debug-log-helper";
@@ -41,7 +41,7 @@ export async function beforeEach(to, from) {
nextPage: to?.name,
};
- bailout(errorPayload, true);
+ handleSoftError(errorPayload, true);
return false;
}
@@ -88,7 +88,7 @@ export async function beforeEach(to, from) {
nextPage: to?.name,
};
- bailout(errorPayload);
+ handleSoftError(errorPayload);
return;
}
@@ -107,7 +107,8 @@ export async function beforeEach(to, from) {
console.log(error);
- bailout(errorPayload);
+ // Eject user from Vue app in this scenario and clear localstorage.
+ await handleHardError(errorPayload);
return;
}
}
diff --git a/src/router/methods/error.js b/src/router/methods/error.js
index 06eea69b0..42807ce04 100644
--- a/src/router/methods/error.js
+++ b/src/router/methods/error.js
@@ -4,8 +4,9 @@ import router from "@/router";
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
+import experimentMixin from "../../mixins/experiment-mixin";
-export async function bailout(errorPayload, forceRestart = false) {
+export async function handleSoftError(errorPayload, forceRestart = false) {
if (forceRestart) {
await store.dispatch(storeActions.RESET_STATE);
deleteFunnelCookie();
@@ -17,3 +18,23 @@ export async function bailout(errorPayload, forceRestart = false) {
name: routeData.ERROR.name,
});
}
+
+export async function handleHardError(errorPayload) {
+ try {
+ const isInStaticErrorExperiment = experimentMixin.methods.hasSettingEqualTo(
+ "UseStaticErrorPage",
+ "true"
+ );
+
+ if (isInStaticErrorExperiment) {
+ analyticsMixin?.methods?.pushPageErrorToDataLayer(errorPayload);
+ window.top.location = "/fmg/static/error";
+ return;
+ } else {
+ await handleSoftError(errorPayload, true);
+ return;
+ }
+ } finally {
+ await handleSoftError(errorPayload, true);
+ }
+}
diff --git a/src/router/methods/helpers/create-route.js b/src/router/methods/helpers/create-route.js
index 32410e3b3..828777603 100644
--- a/src/router/methods/helpers/create-route.js
+++ b/src/router/methods/helpers/create-route.js
@@ -11,7 +11,7 @@ export function createRoute(routeDatum, beforeEnter = async (to, from) => undefi
return await beforeEnter(to, from);
} catch {
return {
- name: routeData.BAILOUT.name,
+ name: routeData.ERROR.name,
replace: true,
};
}
@@ -29,7 +29,7 @@ export function createVirtualRoute(routeDatum, beforeEnter = async (to, from) =>
} catch (error) {
console.log(error);
return {
- name: routeData.BAILOUT.name,
+ name: routeData.ERROR.name,
replace: true,
};
}
diff --git a/src/router/methods/navigate.js b/src/router/methods/navigate.js
index b15c955e9..25c58e7e5 100644
--- a/src/router/methods/navigate.js
+++ b/src/router/methods/navigate.js
@@ -5,7 +5,7 @@ import { savePageData } from "@/router/methods/helpers/save-page-data";
import router from "@/router";
import store from "@/store";
-import { bailout } from "@/router/methods/error";
+import { handleSoftError } from "@/router/methods/error";
async function navigate(scenario, currentPageName, withSaving = false, forceTopLevelNav = false) {
// Check to see if calling page is same as current page.
@@ -30,7 +30,7 @@ async function navigate(scenario, currentPageName, withSaving = false, forceTopL
nextPage: nextPage?.name,
};
- bailout(errorPayload);
+ handleSoftError(errorPayload);
return;
}
diff --git a/src/router/methods/route-logic/error.js b/src/router/methods/route-logic/error.js
index 8707a65d9..573d3cddd 100644
--- a/src/router/methods/route-logic/error.js
+++ b/src/router/methods/route-logic/error.js
@@ -5,15 +5,34 @@ import baseMixin from "@/mixins/base-mixin";
import router from "@/router";
import { routeData, FUNNEL_START_PAGE } from "@/router/constants/routes";
import store from "@/store";
+import { handleHardError } from "@/router/methods/error";
export async function errorBeforeEnter(to, from) {
- // If we've already encountered one error, clear session to avoid more.
- // Otherwise mark that we encoutnered an error here.
- if (store.getters.applicationUser.hasAlreadyTriggeredError) {
- return {
- name: routeData.RESTART.name,
- replace: true,
+ // Check if `hasAlreadyTriggeredErrror` is available.
+ // If we cannot check it (store, getters, or applicationUser is null-ish),
+ // act as if the flag is set, as we are in unstable state.
+ if (!store?.getters?.applicationUser) {
+ const errorPayload = {
+ cause: "Cannot access store during error process.",
+ currentPage: from?.name,
+ nextPage: to?.name,
};
+
+ handleHardError(errorPayload);
+ return;
+ }
+
+ // If we've already encountered one error, clear session to avoid more.
+ // Otherwise mark that we encountered an error here.
+ if (store.getters.applicationUser.hasAlreadyTriggeredError) {
+ const errorPayload = {
+ cause: "Successive errors triggered.",
+ currentPage: from?.name,
+ nextPage: to?.name,
+ };
+
+ handleHardError(errorPayload);
+ return;
} else {
await store.dispatch(storeActions.UPDATE_HAS_TRIGGERED_ERROR, true);
}