Stub error page

This commit is contained in:
Chloe Herd 2025-10-13 14:00:53 -04:00
parent 3d64175744
commit e22f66eb83
9 changed files with 172 additions and 16 deletions

View file

@ -0,0 +1,128 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>
EXCEPTION PAGE
</h1>
<hr />
<h2>
BAILOUT INFO:
</h2>
<div id="bailout-info-container">
</div>
<script>
// Helpers
function getCookieValueByName(name) {
const value = "; " + document.cookie;
const parts = value.split("; " + name + "=");
if (parts.length === 2) {
return parts.pop().split(";").shift();
}
return "";
}
window.onload = () => {
// =============== Check for session info:
const existingVuexDataJSON = window.localStorage.getItem('vuex');
const existingVuexData = existingVuexDataJSON ? JSON.parse(existingVuexDataJSON) : null;
console.log(`================ VUEX DATA`);
console.log(existingVuexData);
// If no info exists, exit.
if(!existingVuexData) {
return;
}
try {
// =============== Collect diagnostic data:
const bailoutInfo = [];
// App & Site Name
bailoutInfo.push({ name: 'App Name', value: 'FixMyGlass' });
bailoutInfo.push({ name: 'Site Name', value: 'SafeliteDotcom' });
// Not included (yet) from heritage:
// - Site ID
// - Code
// - Module
// - Page
bailoutInfo.push({ name: 'Timestamp', value: `${new Date()}` });
// - URL
// - Server
const sessionId = getCookieValueByName('sid');
bailoutInfo.push({ name: 'Session Id', value: sessionId });
const userAgent = window.navigator.userAgent;
bailoutInfo.push({ name: 'User Agent', value: userAgent });
// - IP
// - Session Log Sequence Number
bailoutInfo.push({ name: 'Referral Seq Number', value: existingVuexData.order?.referralSequenceNumber });
bailoutInfo.push({ name: 'Referral Number', value: existingVuexData.order?.referralNumber });
bailoutInfo.push({ name: 'Referral Date', value: existingVuexData.order?.referralDate });
bailoutInfo.push({ name: 'Referral Provider Number', value: existingVuexData.order?.serviceLocation?.provider?.providerNumber });
bailoutInfo.push({ name: 'Referral CTU', value: existingVuexData.order?.serviceLocation?.provider?.address?.zipCodeCtu });
// - Referral Insured Zip
// - Referral Insured Service Zip
bailoutInfo.push({ name: 'Referral CarID', value: existingVuexData.order?.vehicle?.carId });
const vehicle = existingVuexData.order?.vehicle;
const vehicleString = vehicle?.year
? `${vehicle.year} ${vehicle.make} ${vehicle.model} - ${vehicle.style}`
: null;
bailoutInfo.push({ name: 'Referral Vehicle', value: vehicleString });
bailoutInfo.push({ name: 'Work Order Number', value: existingVuexData.order?.workOrderNumber });
bailoutInfo.push({ name: 'Work Order ID', value: existingVuexData.order?.workOrderId });
bailoutInfo.push({ name: 'Parent Account Number', value: existingVuexData.order?.payment?.parentAccountNumber });
// - Parent Account Name
// - Client GUID
// =============== Display diagnostic data:
// Create display nodes
const elements = bailoutInfo.map(
dataPoint => {
const element = document.createElement('li');
element.textContent = `${dataPoint.name}: ${dataPoint.value}`;
return element;
}
);
const fragment = new DocumentFragment();
elements.forEach(
(element) => {
fragment.append(element);
}
);
// Attach nodes to DOM and render
const attachNode = document.getElementById('bailout-info-container');
if(attachNode) {
const ul = attachNode.appendChild(document.createElement('ul'));
ul.append(fragment);
}
} catch(e) {
}
// =============== Clear User Data
// ======== To avoid reproducing the same issue due to invalid states.
window.localStorage.removeItem('vuex');
};
</script>
</body>
</html>

View file

@ -121,7 +121,7 @@ export default {
endpoint: endpoint, endpoint: endpoint,
}; };
router.bailout(errorPayload); router.handleSoftError(errorPayload);
// do not log 404 errors from services because we return NotFound // do not log 404 errors from services because we return NotFound
// when a service doesn't return an object // when a service doesn't return an object

View file

@ -112,7 +112,6 @@ export const routeData = {
path: "/virtual/auto-route", path: "/virtual/auto-route",
virtual: true, virtual: true,
}, },
// TODO: RENAME FROM BAILOUT
ERROR: { ERROR: {
name: "error", name: "error",
path: "/virtual/error", path: "/virtual/error",

View file

@ -1,7 +1,7 @@
import { routes } from "@/router/methods/routes"; import { routes } from "@/router/methods/routes";
import { afterEach } from "@/router/methods/after-each"; import { afterEach } from "@/router/methods/after-each";
import { beforeEach } from "@/router/methods/before-each"; import { beforeEach } from "@/router/methods/before-each";
import { bailout } from "@/router/methods/error"; import { handleSoftError, handleHardError } from "@/router/methods/error";
import { import {
navigateWithoutSaving, navigateWithoutSaving,
navigateWithSaving, navigateWithSaving,
@ -32,7 +32,8 @@ router.navigateWithoutSaving = navigateWithoutSaving;
router.navigateWithPageData = navigateWithPageData; router.navigateWithPageData = navigateWithPageData;
router.navigateAndForceTopLevelNavigation = navigateAndForceTopLevelNavigation; router.navigateAndForceTopLevelNavigation = navigateAndForceTopLevelNavigation;
router.bailout = bailout; router.handleSoftError = handleSoftError;
router.handleHardError = handleHardError;
router.navigateToExternalUrl = navigateToExternalUrl; router.navigateToExternalUrl = navigateToExternalUrl;

View file

@ -8,7 +8,7 @@ import analyticsMixin from "@/mixins/analytics-mixin";
import { routeData, FUNNEL_START_PAGE } from "@/router/constants/routes"; import { routeData, FUNNEL_START_PAGE } from "@/router/constants/routes";
import { runExperiments } from "@/router/methods/helpers/run-experiments"; 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 { checkPagePrerequisites } from "@/router/methods/page-prerequisites";
import { checkLogParam } from "@/helpers/debug-log-helper"; import { checkLogParam } from "@/helpers/debug-log-helper";
import { debugLog } 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, nextPage: to?.name,
}; };
bailout(errorPayload, true); handleSoftError(errorPayload, true);
return false; return false;
} }
@ -88,7 +88,7 @@ export async function beforeEach(to, from) {
nextPage: to?.name, nextPage: to?.name,
}; };
bailout(errorPayload); handleSoftError(errorPayload);
return; return;
} }
@ -107,7 +107,8 @@ export async function beforeEach(to, from) {
console.log(error); console.log(error);
bailout(errorPayload); // Eject user from Vue app in this scenario and clear localstorage.
handleHardError(errorPayload);
return; return;
} }
} }

View file

@ -5,7 +5,7 @@ import store from "@/store";
import { storeActions } from "@/constants/store-actions"; import { storeActions } from "@/constants/store-actions";
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper"; import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
export async function bailout(errorPayload, forceRestart = false) { export async function handleSoftError(errorPayload, forceRestart = false) {
if (forceRestart) { if (forceRestart) {
await store.dispatch(storeActions.RESET_STATE); await store.dispatch(storeActions.RESET_STATE);
deleteFunnelCookie(); deleteFunnelCookie();
@ -17,3 +17,11 @@ export async function bailout(errorPayload, forceRestart = false) {
name: routeData.ERROR.name, name: routeData.ERROR.name,
}); });
} }
export async function handleHardError(errorPayload) {
try {
analyticsMixin?.methods?.pushPageErrorToDataLayer(errorPayload);
} finally {
window.top.location = "/fmg/static/error/";
}
}

View file

@ -11,7 +11,7 @@ export function createRoute(routeDatum, beforeEnter = async (to, from) => undefi
return await beforeEnter(to, from); return await beforeEnter(to, from);
} catch { } catch {
return { return {
name: routeData.BAILOUT.name, name: routeData.ERROR.name,
replace: true, replace: true,
}; };
} }
@ -29,7 +29,7 @@ export function createVirtualRoute(routeDatum, beforeEnter = async (to, from) =>
} catch (error) { } catch (error) {
console.log(error); console.log(error);
return { return {
name: routeData.BAILOUT.name, name: routeData.ERROR.name,
replace: true, replace: true,
}; };
} }

View file

@ -5,7 +5,7 @@ import { savePageData } from "@/router/methods/helpers/save-page-data";
import router from "@/router"; import router from "@/router";
import store from "@/store"; 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) { async function navigate(scenario, currentPageName, withSaving = false, forceTopLevelNav = false) {
// Check to see if calling page is same as current page. // 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, nextPage: nextPage?.name,
}; };
bailout(errorPayload); handleSoftError(errorPayload);
return; return;
} }

View file

@ -5,15 +5,34 @@ import baseMixin from "@/mixins/base-mixin";
import router from "@/router"; import router from "@/router";
import { routeData, FUNNEL_START_PAGE } from "@/router/constants/routes"; import { routeData, FUNNEL_START_PAGE } from "@/router/constants/routes";
import store from "@/store"; import store from "@/store";
import { handleHardError } from "@/router/methods/error";
export async function errorBeforeEnter(to, from) { export async function errorBeforeEnter(to, from) {
// 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. // If we've already encountered one error, clear session to avoid more.
// Otherwise mark that we encoutnered an error here. // Otherwise mark that we encoutnered an error here.
if (store.getters.applicationUser.hasAlreadyTriggeredError) { if (store.getters.applicationUser.hasAlreadyTriggeredError) {
return { const errorPayload = {
name: routeData.RESTART.name, cause: "Successive errors triggered.",
replace: true, currentPage: from?.name,
nextPage: to?.name,
}; };
handleHardError(errorPayload);
return;
} else { } else {
await store.dispatch(storeActions.UPDATE_HAS_TRIGGERED_ERROR, true); await store.dispatch(storeActions.UPDATE_HAS_TRIGGERED_ERROR, true);
} }