This commit is contained in:
Chloe Herd 2025-05-06 11:47:21 -04:00
parent c33b43e9f7
commit 3eae075f6e
52 changed files with 1816 additions and 221 deletions

View file

@ -36,6 +36,9 @@ export default {
loadingModal,
funnelFooter,
},
mounted() {
showFmgLoadingModal(true);
},
};
// Add a global Javascript exception handler for logging exceptions, this handler will log when there is an uncaught exception

View file

@ -15,21 +15,12 @@ const applicationConfig = {
CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER: "87291",
MY_ACCOUNT: process.env.VUE_APP_MY_ACCOUNT,
PIA_RESPONSE_URL:
location.protocol +
"//" +
location.host +
"/fmg/?fmgPage=payment-pia-return&src=concept-funnel",
location.protocol + "//" + location.host + "/fmg/payment-pia-return?src=concept-funnel",
PIA_CANCEL_URL:
location.protocol +
"//" +
location.host +
"/fmg/?fmgPage=payment-method&src=concept-funnel",
location.protocol + "//" + location.host + "/fmg/payment-method?src=concept-funnel",
PIA_ERROR_URL:
location.protocol +
"//" +
location.host +
"/fmg/?fmgPage=payment-pia-return&src=concept-funnel",
CONFIRMATION_URL: location.protocol + "//" + location.host + "/fmg/?fmgPage=confirmation",
location.protocol + "//" + location.host + "/fmg/payment-pia-return?src=concept-funnel",
CONFIRMATION_URL: location.protocol + "//" + location.host + "/fmg/confirmation",
GOOGLE_CALENDAR: "https://www.google.com/calendar/render?action=TEMPLATE",
YAHOO_CALENDAR: "https://calendar.yahoo.com/?v=60",
OUTLOOK_CALENDAR:
@ -38,7 +29,7 @@ const applicationConfig = {
AFFILIATE_COOKIE_CONTAINING_NAME: "_Track",
COOKIE_NAME_LENGTH_MAX_LIMIT: 44,
SESSION_TIMEOUT_MINUTES: process.env.VUE_APP_SESSION_TIMEOUT_MINUTES,
RETURN_USER_PAGE: "/fmg/?fmgPage=return-user",
RETURN_USER_PAGE: "/fmg/return-user",
};
export { applicationConfig };

View file

@ -117,6 +117,7 @@ const storeActions = {
UPDATE_EXTERNAL_PARAMETER_MMS: "updateExternalParameterMMS",
SAVE_LOGGING_OPTION: "saveLoggingOption",
UPDATE_HAS_TRIGGERED_ERROR: "updateHasTriggeredError",
};
export { storeActions };

View file

@ -93,6 +93,7 @@ const storeMutations = {
UPDATE_SAVE_SESSION_PROMISE: "updateSaveSessionPromise",
UPDATE_LAST_PAGE_VISITED: "updateLastPageVisited",
UPDATE_LOGGING_OPTION: "updateLoggingOption",
UPDATE_HAS_TRIGGERED_ERROR: "updateHasTriggeredError",
// EXPERIMENT MUTATIONS
UPDATE_EXPERIMENTS: "updateExperiments",

View file

@ -58,7 +58,7 @@ export default {
getRouterLinkDisplayTextFromCopy,
getExternalLink,
navigateWithScenario(scenarioName) {
this.$router.navigateWithoutSaving(scenarioName, this.$route);
this.$router.navigateWithoutSaving(scenarioName, this.pageName);
},
},
computed: {

View file

@ -17,7 +17,7 @@ export default {
},
methods: {
getProgress() {
var pageName = store.getters.applicationUser.lastPageVisited;
var pageName = this.pageName;
return getProgressBarPercentage(pageName);
},
},

View file

@ -1,7 +1,7 @@
import axios from "axios";
import analyticsMixIn from "@/mixins/analytics-mixin.js";
import baseMixin from "@/mixins/base-mixin.js";
import router from "@/router";
import router from "@/router/a-rewrite";
import store from "@/store";
import { applicationConfig } from "@/constants/application-config.js";
@ -117,7 +117,7 @@ export default {
endpoint: endpoint,
};
router.navigateError(errorPayload);
router.bailout(errorPayload);
// do not log 404 errors from services because we return NotFound
// when a service doesn't return an object

View file

@ -59,25 +59,15 @@ export async function saveSession({
submitAfterSave = false,
createUnscheduledStatusWorkOrderForPIA = false,
}) {
var saveSessionPromise;
if (store.getters.applicationUser.saveSessionPromise) {
// queue newest request after current saveSessionPromise resolves
saveSessionPromise = store.getters.applicationUser.saveSessionPromise.then(() => {
// get a new saveSessionPromise
return saveSessionHelper(
pageNameToLog,
submitAfterSave,
createUnscheduledStatusWorkOrderForPIA
);
});
} else {
// create an initial saveSessionPromise
saveSessionPromise = saveSessionHelper(
// Add next save session to end of queue
const saveSessionPromise = flushSaveSessionQueue().then(() => {
return saveSessionHelper(
pageNameToLog,
submitAfterSave,
createUnscheduledStatusWorkOrderForPIA
);
}
});
store.commit(storeMutations.UPDATE_SAVE_SESSION_PROMISE, saveSessionPromise);
// await here to allow for a caller to await and make the function synchronous
if (!store.getters.applicationUser.savedSessionId || shouldAwaitSaveSessionQueue) {
@ -133,7 +123,7 @@ async function loadSession(
pageNameToLog
) {
// await the saveSessionPromise in the store to make sure we're loading up to date information
await store.getters.applicationUser.saveSessionPromise;
await flushSaveSessionQueue();
const response = await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.LOAD_SESSION,
@ -193,3 +183,7 @@ async function saveSessionHelper(
// Update the cookie with the referral information when saved.
updateOrCreateFunnelCookie();
}
export async function flushSaveSessionQueue() {
return Promise.resolve(store.getters.applicationUser.saveSessionPromise);
}

View file

@ -137,7 +137,7 @@ export default {
mixins: [vinPagesMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle promises and get results
const promiseResultMap = [
@ -193,7 +193,10 @@ export default {
},
backButtonAction() {
// route to move backwards
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
},
attachCustomEvents() {
this.prependActionToMethod(this, this.forwardButtonAction, () => {
@ -442,18 +445,14 @@ export default {
) {
this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
this.pageName
);
} else if (matchingCars.length === 1) {
await this.navigateForwardWithSingleCarMatch();
} else {
this.$router.navigateWithSaving(
this.$router.navigateWithPageData(
this.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
this.$route,
{},
{},
this.pageName,
carsFound
);
}

View file

@ -82,7 +82,7 @@ export default {
mixins: [vinPagesMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle promises and get results
const promiseResultMap = [
@ -166,7 +166,10 @@ export default {
return false;
},
backButtonAction() {
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
},
async forwardButtonAction() {
const vinLookup = await this.dispatchStoreActionWithLogging(
@ -205,9 +208,7 @@ export default {
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
this.pageName
);
} else {
await this.navigateForwardWithSingleCarMatch();

View file

@ -37,7 +37,7 @@ export default {
name: "bailout",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle promises and get results
const promiseResultMap = [

View file

@ -47,7 +47,7 @@ export default {
mixins: [vehicleQuestionsMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle promises and get results
const promiseResultMap = [

View file

@ -123,6 +123,7 @@ import experimentMixin from "@/mixins/experiment-mixin.js";
import { containsRecalParts } from "@/helpers/recal-helper.js";
import donationBlock from "@/experiment-components/donation-block.vue";
import { partNumberStrings } from "@/constants/part-number-strings";
import analyticsMixin from "@/mixins/analytics-mixin";
export default {
name: "confirmation",
@ -179,7 +180,7 @@ export default {
// Call APIs
const submittedOrder = baseMixin.methods.getSubmittedOrder();
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
const wipersPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_WIPERS,
@ -244,6 +245,8 @@ export default {
vm.showDonationSuccess = lineItemsFromSubmittedOrder.supportingItems?.some(
(item) => item.partType === partNumberStrings.DONATION
);
vm.pushAnalytics();
});
},
data() {
@ -556,6 +559,16 @@ export default {
this.$refs.donationBlock.removeLoader();
}
},
pushAnalytics() {
//Push Ecommerce Cart to Data Layer
analyticsMixin.methods.pushECommerceCartToDataLayer();
//Push Product Array to Data Layer
analyticsMixin.methods.pushProductArrayToDataLayer();
//Push Commission Junction Gtm Data To Data Layer
analyticsMixin.methods.pushCommissionJunctionGtmDataToDataLayer();
},
},
components: {
funnelHeader,

View file

@ -84,6 +84,7 @@ import { required, regex } from "@/helpers/validation-rules";
import { Form, defineRule } from "vee-validate";
import store from "@/store";
import { paymentMethods } from "@/constants/payment-method-constants";
import { flushSaveSessionQueue } from "@/helpers/heritage-integration/order-helper";
// DEFINE VALIDATION RULES
defineRule("first-name-required", required(errorMessages.FIRST_NAME_REQUIRED));
@ -102,7 +103,7 @@ export default {
name: "customer-details",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle promises and get results
const promiseResultMap = [
@ -157,7 +158,10 @@ export default {
return store.getters.order.serviceLocation.techNotes;
},
backButtonAction() {
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
},
async forwardButtonAction() {
this.dispatchStoreAction(
@ -186,10 +190,13 @@ export default {
paymentMethods.NONE,
false
);
await store.getters.applicationUser.saveSessionPromise;
await flushSaveSessionQueue();
}
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
);
},
},
components: {

View file

@ -62,6 +62,7 @@ import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
import baseMixin from "@/mixins/base-mixin.js";
import { queryStrings } from "@/constants/query-strings";
import { nextTick } from "vue";
import { consumeQueryFromStash } from "@/router/a-rewrite/logic/querystring-stash";
// Define Validation Rules
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
@ -89,7 +90,7 @@ export default {
async beforeRouteEnter(to, from, next) {
//Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
@ -98,9 +99,9 @@ export default {
lowerCaseParams.append(name.toLowerCase(), value);
}
const zip = lowerCaseParams.get(queryStrings.ZIP_CODE)
? lowerCaseParams.get(queryStrings.ZIP_CODE)
: store.getters.order.serviceLocation.zipCode;
const zip =
consumeQueryFromStash(queryStrings.ZIP_CODE) ??
store.getters.order.serviceLocation.zipCode;
var vinByAddressPromise;
if (zip) {
@ -184,32 +185,35 @@ export default {
},
backButtonAction() {
// route to move backwards
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
},
async forwardButtonAction() {
if (this.selectedVinLookupMethod === vinLookupMethodSelections.MANUALVIN) {
await this.dispatchStoreAction(storeActions.CLEAR_VIN);
return this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_MANUAL_VIN,
this.$route
this.pageName
);
}
if (this.selectedVinLookupMethod === vinLookupMethodSelections.LICENSEPLATE) {
return this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_LICENSE_PLATE,
this.$route
this.pageName
);
}
if (this.selectedVinLookupMethod === vinLookupMethodSelections.HOMEADDRESS) {
return this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_HOME_ADDRESS,
this.$route
this.pageName
);
}
if (this.selectedVinLookupMethod === vinLookupMethodSelections.DECLINE) {
return this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_NO_VIN,
this.$route
this.pageName
);
}
},

View file

@ -58,6 +58,7 @@ import { experimentSettings } from "@/constants/experiments";
import { partNumberStrings } from "@/constants/part-number-strings";
import { deepClone } from "@/helpers/object-helper";
import store from "@/store";
import { flushSaveSessionQueue } from "@/helpers/heritage-integration/order-helper";
export default {
name: "insurance-company",
@ -81,7 +82,7 @@ export default {
}
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
const insuranceCompanyListPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_INSURANCE_COMPANY_LIST,
{},
@ -146,18 +147,20 @@ export default {
// Go back to Quote page
if (forceCashSelectionOnQuote) {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.$route,
{ isCashSelected: true }
this.navigationScenarios.CLICKED_PAY_ON_MY_OWN,
this.pageName
);
return;
}
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
},
async forwardButtonAction() {
// await any pending save-sessions. if you don't, we will save the new parent account into vuex and then a pending async save-session response overwrites it
await store.getters.applicationUser.saveSessionPromise;
await flushSaveSessionQueue();
await this.dispatchStoreAction(
this.storeActions.SAVE_PARENT_ACCOUNT_NUMBER,

View file

@ -119,6 +119,8 @@ import baseMixin from "@/mixins/base-mixin.js";
import store from "@/store";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { consumeQueryFromStash } from "@/router/a-rewrite/logic/querystring-stash";
import { queryStrings } from "@/constants/query-strings";
// DEFINE VALIDATION RULES
defineRule("license-plate-required", required(errorMessages.LICENSE_PLATE_REQUIRED));
@ -138,7 +140,7 @@ export default {
mixins: [vinPagesMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle promises and get results
const promiseResultMap = [
@ -163,7 +165,8 @@ export default {
data() {
return {
licensePlate: this.getLicensePlateFromStore(),
registrationZipCode: this.getRegistrationZipFromStore() ?? this.$route.query.zipcode,
registrationZipCode:
this.getRegistrationZipFromStore() ?? consumeQueryFromStash(queryStrings.ZIP_CODE),
emailOrSms: this.getEmailOrSmsFromStore(),
serviceZipCode: this.getServiceZipFromStore(),
carId: this.getCarIdfromStore(),
@ -187,7 +190,10 @@ export default {
},
backButtonAction() {
// route to move backwards
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
},
attachCustomEvents() {
this.prependActionToMethod(this, this.forwardButtonAction, () => {
@ -392,9 +398,7 @@ export default {
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
this.pageName
);
} else {
await this.navigateForwardWithSingleCarMatch();

View file

@ -47,7 +47,7 @@ export default {
mixins: [vehicleQuestionsMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle promises and get results
const promiseResultMap = [

View file

@ -47,7 +47,7 @@ export default {
mixins: [vehicleQuestionsMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle promises and get results
const promiseResultMap = [

View file

@ -168,6 +168,7 @@ import {
getSubTotal,
getSalesTax,
} from "@/helpers/pricing-helper.js";
import { consumeQueryFromStash } from "@/router/a-rewrite/logic/querystring-stash";
defineRule("payment-method-required", required(errorMessages.OPTION_REQUIRED));
defineRule("recal-ack-required", required(errorMessages.RECAL_ACK_REQUIRED));
@ -179,7 +180,7 @@ export default {
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
const lineItemsFromStore = deepClone(store.getters.order.lineItems);
@ -281,7 +282,7 @@ export default {
const oldActivePromos = store.getters.lineItems.promos?.slice(0);
const oldInactivePromos = store.getters.order.payment.inactivePromos?.slice(0);
const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
const promoCodeFromQueryString = consumeQueryFromStash(queryStrings.PROMO);
const { validatePromoResponse, revalidatePromoResponse } =
await revalidatePromosAndValidateQueryStringPromo(
promoCodeFromQueryString,
@ -374,7 +375,7 @@ export default {
doesCopyContainRouterLink,
getRouterLinkRouteFromCopy,
navigateWithScenario(scenarioName) {
this.$router.navigateWithoutSaving(scenarioName, this.$route);
this.$router.navigateWithoutSaving(scenarioName, this.pageName);
},
arePagePrerequisitesValid() {
// Service Location
@ -537,7 +538,10 @@ export default {
return this.$store.getters.order.isRecalAckOptIn;
},
backButtonAction() {
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
},
async forwardButtonAction() {
this.forwardClicked = true;
@ -575,16 +579,14 @@ export default {
await submitWorkOrder({ pageNameToLog: "payment-method", submitAfterSave: true });
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.$route,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: false }
this.pageName
);
} else {
if (this.paymentMethod == paymentMethods.INSURANCE) {
this.dispatchStoreAction(this.storeActions.SAVE_PAYMENT_TYPE, true, false);
return this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_INSURANCE,
this.$route
this.pageName
);
} else {
this.setupPia();
@ -603,16 +605,14 @@ export default {
} catch (error) {
console.log("error: response from pia submit work order:" + error.message);
this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
this.$route.query[queryStrings.DISPLAY_PIA_ALERT] = true;
this.$route.query.piaError = true;
return;
}
this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_PAY_NOW,
this.$route,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: false }
this.pageName
);
},
hasSubmittedOrder() {
@ -797,10 +797,7 @@ export default {
return this.paymentMethodInternalModel;
},
shouldDisplayPiaAlert() {
return (
this.$route.query[queryStrings.DISPLAY_PIA_ALERT] ||
getBoolFromString(window.history.state.displayPiaAlert)
);
return getBoolFromString(this.$route?.query?.piaError);
},
// Necessary to make the watcher of lineItems work
// JavaScript does not keep a record of the old value, only a reference to it's location in the memory.

View file

@ -39,20 +39,22 @@ export default {
store.getters.order.payment.piaType === paymentMethods.APPLE_PAY ||
store.getters.order.payment.piaType === paymentMethods.AFTERPAY;
if (paymentPageNavScenario) {
this.$router.navigateWithoutSaving(
this.navigationScenarios.PIA_CC_ERROR,
this.$route,
{
[queryStrings.DISPLAY_PIA_ALERT]: store.getters.order.payment.piaType,
}
const scenarios = {
[paymentMethods.CREDIT_CARD]: this.navigationScenarios.PIA_CC_ERROR,
[paymentMethods.APPLE_PAY]: this.navigationScenarios.PIA_APPLE_ERROR,
[paymentMethods.AFTERPAY]: this.navigationScenarios.PIA_AFTERPAY_ERROR,
};
const relevantScenario = scenarios[store.getters.order.payment.piaType];
await this.$router.navigateAndForceTopLevelNavigation(
relevantScenario,
this.pageName
);
} else {
this.$router.navigateWithoutSaving(
await this.$router.navigateAndForceTopLevelNavigation(
this.navigationScenarios.PIA_ERROR,
this.$route,
{
[queryStrings.DISPLAY_PIA_ALERT]: true,
}
this.pageName
);
}
} else {
@ -84,11 +86,9 @@ export default {
} else {
var msg = "Unknown Pia type: " + store.getters.order.payment.piaType;
console.log(msg);
this.$router.navigateWithoutSaving(
await this.$router.navigateAndForceTopLevelNavigation(
this.navigationScenarios.PIA_ERROR,
this.$route,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: true }
this.pageName
);
}
}
@ -123,11 +123,9 @@ export default {
" " +
store.getters.order.referralSequenceNumber
);
this.$router.navigateWithoutSaving(
this.$router.navigateAndForceTopLevelNavigation(
this.navigationScenarios.PIA_ERROR,
this.$route,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: true }
this.pageName
);
} else {
const expMonth = getQuerystringParameter(queryStrings.CARD_EXPIRATION_MONTH);
@ -181,11 +179,9 @@ export default {
});
} catch (error) {
console.log("error: response from submit work order:" + error.message);
this.$router.navigateWithoutSaving(
this.$router.navigateAndForceTopLevelNavigation(
this.navigationScenarios.PIA_ERROR,
this.$route,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: true }
this.pageName
);
this.$refs.loadingModal.isModalVisible = false;
return;
@ -193,7 +189,10 @@ export default {
this.$refs.loadingModal.isModalVisible = false;
await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_STATE);
this.$router.navigateWithoutSaving(this.navigationScenarios.PIA_SUCCESS, this.$route);
this.$router.navigateAndForceTopLevelNavigation(
this.navigationScenarios.PIA_SUCCESS,
this.pageName
);
},
},
components: {

View file

@ -289,7 +289,7 @@ export default {
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
const signaturePromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_SIGNATURE,
@ -684,12 +684,16 @@ export default {
});
await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_STATE);
window.location = applicationConfig.CONFIRMATION_URL;
this.$router.navigateAndForceTopLevelNavigation(
this.navigationScenarios.CLICKED_PAY_LATER,
this.pageName
);
//window.location = applicationConfig.CONFIRMATION_URL;
} catch (error) {
console.log("error: response from submit work order(payment pg):" + error.message);
this.$router.navigateWithoutSaving(
this.navigationScenarios.PIA_ERROR,
this.$route,
this.pageName,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: true }
);
@ -698,16 +702,13 @@ export default {
}
},
backButtonAction() {
// The only way I could figure out how to get navigation to work on a page with the iframe.
// This is also how a cancel from Paypal would work. Just a redirect to the payment-method page.
// The normal navigation sort of works but the page does not render. The "next" callback function does not get
// invoked in payment-method's beforeroute enter. I also spotted an error in vue-router.esm-bundler.js when this
// happens but was unable to ignore it with a try catch. The navigation guard error is:
// Error: Redirected from "/?fmgPage=payment-method" to "{ params: {isSavingNation: "false"}, query: "fmgPage: "payment-method"}"
// I don't know if the navigation guard thinks the to and from are the same page.
// Also tried overriding with a $router.push
window.location = applicationConfig.PIA_CANCEL_URL;
//this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
// Used to set the url directly here.
// Now hooks into a shared set of logic for doing this, also used with `payment-pia-return`.
// And uses nav scenarios properly.
this.$router.navigateAndForceTopLevelNavigation(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
},
submitHopForm() {
this.$nextTick(() => {
@ -804,10 +805,7 @@ export default {
}
},
shouldDisplayPiaAlert(payMethod) {
return (
this.$route.query[queryStrings.DISPLAY_PIA_ALERT] === payMethod ||
getBoolFromString(window.history.state.displayPiaAlert)
);
return this.$route?.query?.piaErrorType === payMethod;
},
},
components: {

View file

@ -168,16 +168,22 @@ import {
} from "@/helpers/heritage-integration/cookie-helper";
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { consumeQueryFromStash } from "@/router/a-rewrite/logic/querystring-stash";
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
const INSURANCE_TAB_TO_DISPLAY_THRESHOLD_DEFAULT = 300;
const ACCEPTED_QUOTE_TYPES = {
CASH: "cash",
INSURANCE: "insurance",
};
export default {
name: "quote",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
const wipersPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_WIPERS,
{
@ -214,7 +220,7 @@ export default {
userId: getUserIdValue(),
deviceId: getDeviceIdValue(),
sessionKey: getSessionKeyValue(),
pageName: to.query.fmgPage,
pageName: to.name,
experiment: skipQuoteExperiment,
},
"quote",
@ -244,7 +250,7 @@ export default {
userId: getUserIdValue(),
deviceId: getDeviceIdValue(),
sessionKey: getSessionKeyValue(),
pageName: to.query.fmgPage,
pageName: to.name,
experiment: afterpayBreakoutDisplayExperiment,
},
"quote",
@ -351,7 +357,7 @@ export default {
const oldActivePromos = store.getters.lineItems.promos?.slice(0);
const oldInactivePromos = store.getters.order.payment.inactivePromos?.slice(0);
const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
const promoCodeFromQueryString = consumeQueryFromStash(queryStrings.PROMO);
const { validatePromoResponse, revalidatePromoResponse } =
await revalidatePromosAndValidateQueryStringPromo(
promoCodeFromQueryString,
@ -401,10 +407,15 @@ export default {
}
const getIsInsuranceSelectedValue = (availableLineItems, insuranceThreshold) => {
// query param checked here is set on insurance-selection "Pay on my own" link click
if (to.query?.isCashSelected || to.query?.iscashselected) {
// Override auto-select if specified
const quoteTypeParam = to.query?.offer?.toLowerCase();
if (quoteTypeParam === ACCEPTED_QUOTE_TYPES.CASH) {
return false;
} else if (quoteTypeParam === ACCEPTED_QUOTE_TYPES.INSURANCE) {
return true;
}
const serviceLocationState = store.getters.order.serviceLocation.state;
// usually true when returning from heritage but can be false when returning from heritage on a save quote
@ -758,12 +769,12 @@ export default {
if (payment.isInsurance) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_INSURANCE,
this.$route
this.pageName
);
} else {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_CASH,
this.$route
this.pageName
);
}
},

View file

@ -55,7 +55,7 @@ export default {
name: "return-user",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle promises and get results
const promiseResultMap = [
{
@ -85,7 +85,7 @@ export default {
async forwardButtonAction() {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.$route
this.pageName
);
},
@ -96,11 +96,9 @@ export default {
"Start over",
true
);
deleteFunnelCookie();
await this.dispatchStoreAction(storeActions.RESET_STATE);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.$route
this.navigationScenarios.CLICKED_RESTART,
this.pageName
);
},
},

View file

@ -267,7 +267,7 @@ export default {
}
// Set up promises
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
const alertReasonsPromise = locationAlerts.methods.loadInitialData(
store.getters.order.serviceLocation.zipCodeCtu,
@ -532,7 +532,10 @@ export default {
}
},
backButtonAction() {
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
},
forwardButtonAction() {
this.updateSupportingItems();
@ -581,7 +584,10 @@ export default {
);
}
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
);
},
setDisplayWaitList() {
if (

View file

@ -215,7 +215,7 @@ export default {
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
const serviceZipCode = store.getters.order.serviceLocation.zipCode;
const zipCodeDataPromise = getZipCodeData(serviceZipCode);
@ -608,7 +608,7 @@ export default {
} else {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.$route
this.pageName
);
}
},
@ -748,7 +748,10 @@ export default {
this.updateAndSaveSupportingItems();
this.updateAndSaveIsMSRFeeApplicable();
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
);
},
openModalAction(modalName) {
this.$refs[modalName].openModal();

View file

@ -96,6 +96,7 @@ import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
import baseMixin from "@/mixins/base-mixin.js";
import { queryStrings } from "@/constants/query-strings";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { consumeQueryFromStash } from "@/router/a-rewrite/logic/querystring-stash";
// Define Validation Rules
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
@ -115,7 +116,7 @@ export default {
mixins: [vinPagesMixin],
data() {
return {
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
serviceZipCode: this.getZipFromStore() ?? consumeQueryFromStash(queryStrings.ZIP_CODE),
emailOrSms: this.getEmailOrSmsFromStore(),
carId: this.getCarIdfromStore(),
isHeavyTruck: this.getIsVehicleHeavyTruckServiceableFromStore(),
@ -127,7 +128,7 @@ export default {
async beforeRouteEnter(to, from, next) {
//Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
//Settle promises and get results
const promiseResultMap = [
@ -214,12 +215,12 @@ export default {
if (skipVin) {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK_WITH_SKIP_VIN,
this.$route
this.pageName
);
} else {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.$route
this.pageName
);
}
},
@ -317,7 +318,7 @@ export default {
await saveSession({ pageNameToLog: "service-zip" });
return this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_NO_QUESTIONS,
this.$route
this.pageName
);
} else {
// if we're skipping the vin-lookup but it's not a repair, we still need to get the parts

View file

@ -110,7 +110,7 @@ export default {
name: "vehicle-damage",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
const damageOptionsPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_DAMAGE_OPTIONS,
@ -249,7 +249,10 @@ export default {
backButtonAction() {
// route to move backwards
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
},
getDamageLocationsFromStore() {
@ -455,34 +458,26 @@ export default {
if (skipVin) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_SKIP_VIN,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
this.pageName
);
} else {
if (store.getters.damage.isRepair) {
this.$router.navigateWithSaving(
this.navigationScenarios
.CLICKED_FORWARD_WITH_REPAIR_AND_VERIFIED_INSURANCE,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
this.pageName
);
} else {
if (store.getters.vehicle.vin) {
this.$router.navigateWithSaving(
this.navigationScenarios
.CLICKED_FORWARD_WITH_REPLACE_AND_VERIFIED_INSURANCE,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
this.pageName
);
} else {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
this.pageName
);
}
}
@ -492,23 +487,17 @@ export default {
else if (store.getters.vehicle.vin) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_VIN,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
this.pageName
);
} else if (skipVin) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_SKIP_VIN,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
this.pageName
);
} else {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
this.pageName
);
}
},
@ -637,7 +626,7 @@ export default {
);
},
shouldDisplayVehicleChangeAlert() {
return getBoolFromString(window.history.state.displayVehicleChangeAlert);
return getBoolFromString(this.$route?.query?.displayVehicleChangeAlert);
},
shouldHideBackButton() {
return this.$store.getters.requiresVerifiedRedirecting;

View file

@ -154,7 +154,7 @@ export default {
},
PartDataFromApi() {
return this.$store.getters.pageData(this.$route.query.fmgPage) ?? {};
return this.$store.getters.pageData(this.pageName) ?? {};
},
},
methods: {

View file

@ -81,7 +81,7 @@ export default {
mixins: [vehicleQuestionsMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle promises and get results
const promiseResultMap = [
{

View file

@ -110,6 +110,10 @@ import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
import { applicationConfig } from "../../constants/application-config";
import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import {
consumeQueryFromStash,
peekQueryFromStash,
} from "@/router/a-rewrite/logic/querystring-stash";
//define validation rules
defineRule("year-required", required(errorMessages.YEAR_REQUIRED));
@ -133,7 +137,7 @@ export default {
imageUrl: this.getImagefromStore(),
imageVifNumber: this.getImageVifNumberfromStore(),
imageVifColor: this.getImageVifColorfromStore(),
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
serviceZipCode: this.getZipFromStore() ?? peekQueryFromStash(queryStrings.ZIP_CODE),
yearOptions: [],
makeOptions: [],
modelOptions: [],
@ -154,7 +158,7 @@ export default {
);
}
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
const experimentForLogging = store.getters.applicationUser.experiments.find(
(e) => e.universeName === experimentUniverses.CONCEPT_FUNNEL
);
@ -213,7 +217,7 @@ export default {
userId: getUserIdValue(),
deviceId: getDeviceIdValue(),
sessionKey: getSessionKeyValue(),
pageName: to.query.fmgPage,
pageName: to.name,
experiment: experimentForLogging,
},
"vehicle",
@ -536,7 +540,10 @@ export default {
}
}
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
);
},
initializeYearComponent(initialData) {
this.yearOptions = initialData;

View file

@ -160,6 +160,8 @@ import baseMixin from "@/mixins/base-mixin.js";
import store from "@/store";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { consumeQueryFromStash } from "@/router/a-rewrite/logic/querystring-stash";
import { queryStrings } from "@/constants/query-strings";
// DEFINE VALIDATION RULES
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
@ -180,7 +182,7 @@ export default {
mixins: [vinPagesMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const cmsContentPromise = fetchCmsContentForPage(to.name);
// Settle promises and get results
const promiseResultMap = [
@ -203,7 +205,7 @@ export default {
data() {
return {
vin: this.getVinFromStore(),
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
serviceZipCode: this.getZipFromStore() ?? consumeQueryFromStash(queryStrings.ZIP_CODE),
emailOrSms: this.getEmailOrSmsFromStore(),
carId: this.getCarIdfromStore(),
isHeavyTruck: this.getIsVehicleHeavyTruckServiceableFromStore(),
@ -247,12 +249,12 @@ export default {
if (this.$store.getters.vehicle.vin) {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK_WITH_VIN,
this.$route
this.pageName
);
} else {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.$route
this.pageName
);
}
},
@ -474,9 +476,7 @@ export default {
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
this.pageName
);
} else {
await this.navigateForwardWithSingleCarMatch();

View file

@ -2,7 +2,7 @@ import { createApp } from "vue";
import LoadScript from "vue-plugin-load-script";
import Maska from "maska";
import App from "./App.vue";
import router from "./router";
import router from "./router/a-rewrite";
import store from "@/store";
import baseMixin from "@/mixins/base-mixin.js";
import analyticsMixin from "@/mixins/analytics-mixin.js";

View file

@ -2,7 +2,7 @@ import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import { storeMutations } from "@/constants/store-mutations.js";
import { sessionStorageKeyConstants } from "@/constants/session-storage.js";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
import { navigationScenarios } from "@/router/a-rewrite/constants/navigation-scenarios";
import { vehicleCategories } from "@/constants/vehicle-categories.js";
import { routerParams } from "@/router/router-constants/router-params";
import { queryStrings } from "@/constants/query-strings";
@ -15,6 +15,7 @@ export default {
data() {
return {
cmsContentByWidget: {},
_componentPageName: null,
};
},
methods: {
@ -246,9 +247,15 @@ export default {
cssClassNameForCmsWidget() {
return "widget-name-" + this.cmsWidgetName;
},
pageName() {
return this._componentPageName ?? this.$route.name;
},
},
mounted() {
// Store route immutably so that components know their originating page even during page transition.
this._componentPageName = this.$route.name;
if (!store.getters.externalParameterState?.isExternalParameter) {
showFmgLoadingModal(false);
}

View file

@ -65,10 +65,10 @@ export default {
orderedVehicleQuestionPages.indexOf(fmgPage)
);
},
currentPageComesBeforePage(currentPage = this.$route.query.fmgPage, fmgPage) {
currentPageComesBeforePage(currentPage = this.pageName, fmgPage) {
return this.comparePageIndices(currentPage, fmgPage) < 0;
},
currentPageComesAfterPage(currentPage = this.$route.query.fmgPage, fmgPage) {
currentPageComesAfterPage(currentPage = this.pageName, fmgPage) {
return this.comparePageIndices(currentPage, fmgPage) > 0;
},
setupInitialData(glass, index, alreadyAnsweredQuestions, vm) {
@ -359,7 +359,7 @@ export default {
// Can't use `this` because navigateForward is also called from vin-pages-mixin
async navigateForward(partsOrQuestions, vm) {
const self = vm ?? this;
const currentPage = self.$route.query.fmgPage;
const currentPage = self.pageName;
const hasPartQuestions = this.hasPartQuestions(partsOrQuestions);
const hasGlassLocationWithMultipleParts =
@ -371,11 +371,9 @@ export default {
hasPartQuestions &&
this.currentPageComesBeforePage(currentPage, fmgPageValues.PART_QUESTIONS)
) {
self.$router.navigateWithSaving(
self.$router.navigateWithPageData(
self.navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
self.$route,
{},
{},
self.pageName,
{ partsOrQuestions: partsOrQuestions }
);
} else if (
@ -384,11 +382,9 @@ export default {
) {
// if multiple parts on any glass
// go to vehicle-parts page and pass the partsData
self.$router.navigateWithSaving(
self.$router.navigateWithPageData(
self.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
self.$route,
{},
{},
self.pageName,
{ partsOrQuestions: partsOrQuestions }
);
} else if (
@ -397,11 +393,9 @@ export default {
) {
// if any childpart questions
// go to molding-questions page and pass the partsData
self.$router.navigateWithSaving(
self.$router.navigateWithPageData(
self.navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
self.$route,
{},
{},
self.pageName,
{ partsOrQuestions: partsOrQuestions }
);
} else if (
@ -438,11 +432,9 @@ export default {
}
}
self.$router.navigateWithSaving(
self.$router.navigateWithPageData(
self.navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
self.$route,
{},
{},
self.pageName,
{ partsOrQuestions }
);
} else {
@ -477,7 +469,7 @@ export default {
} else {
self.$router.navigateWithSaving(
self.navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
self.$route
self.pageName
);
}
}
@ -485,7 +477,7 @@ export default {
// Can't use `this` because navigateForward is also called from quote
async navigateBack(vm) {
const self = vm ?? this;
const currentPage = self.$route.query.fmgPage;
const currentPage = self.pageName;
const pageDataCapabilityQuestions = self.$store.getters.pageData(
fmgPageValues.CAPABILITY_QUESTIONS
);
@ -539,7 +531,7 @@ export default {
backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS;
}
self.$router.navigateWithoutSaving(backNavigationScenario, self.$route);
self.$router.navigateWithoutSaving(backNavigationScenario, self.pageName);
},
},
};

View file

@ -0,0 +1,13 @@
import { routeData } from "./routes";
export const autoRouteTable = [
routeData.QUOTE,
routeData.CAPABILITY_QUESTIONS,
routeData.MOLDING_QUESTIONS,
routeData.VEHICLE_PARTS,
routeData.PART_QUESTIONS,
routeData.VIN_LOOKUP,
routeData.ESTIMATE,
routeData.VEHICLE_DAMAGE,
routeData.VEHICLE,
];

View file

@ -0,0 +1,69 @@
/**
* We want to name these to describe the scenario rather than what page(s) they're used on.
*
* Naming convention: [PAST_TENSE_VERB]_[DESCRIPTOR_OF_STATE]
* ex: Rather than "HAS_PART_QUESTIONS", we might name the
* scenario "CLICKED_FORWARD_WITH_PART_QUESTIONS"
*/
const navigationScenarios = {
// General
CLICKED_BACK: "CLICKED_BACK",
CLICKED_FORWARD: "CLICKED_FORWARD",
CLICKED_FORWARD_WITH_CASH: "CLICKED_FORWARD_WITH_CASH",
CLICKED_FORWARD_WITH_INSURANCE: "CLICKED_FORWARD_WITH_INSURANCE",
// TODO: use virtual page?
// Vin selection
CLICKED_BACK_WITH_VIN: "CLICKED_BACK_WITH_VIN",
CLICKED_BACK_WITH_SKIP_VIN: "CLICKED_BACK_WITH_SKIP_VIN",
CLICKED_FORWARD_WITH_VIN: "CLICKED_FORWARD_WITH_VIN",
CLICKED_FORWARD_WITH_REPAIR_AND_VERIFIED_INSURANCE:
"CLICKED_FORWARD_WITH_REPAIR_AND_VERIFIED_INSURANCE",
CLICKED_FORWARD_WITH_REPLACE_AND_VERIFIED_INSURANCE:
"CLICKED_FORWARD_WITH_REPLACE_AND_VERIFIED_INSURANCE",
CLICKED_FORWARD_WITHOUT_VIN: "CLICKED_FORWARD_WITHOUT_VIN",
CLICKED_FORWARD_WITH_SKIP_VIN: "CLICKED_FORWARD_WITH_SKIP_VIN",
CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES: "CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES",
SELECTED_VIN_WITH_MISMATCHED_GLASS: "SELECTED_VIN_WITH_MISMATCHED_GLASS",
SELECTED_MANUAL_VIN: "SELECTED_MANUAL_VIN",
SELECTED_LICENSE_PLATE: "SELECTED_LICENSE_PLATE",
SELECTED_HOME_ADDRESS: "SELECTED_HOME_ADDRESS",
SELECTED_NO_VIN: "SELECTED_NO_VIN",
CLICKED_FORWARD_WITH_NO_QUESTIONS: "CLICKED_FORWARD_WITH_NO_QUESTIONS",
CLICKED_VIN_RETRY: "CLICKED_VIN_RETRY",
// Part selection
CLICKED_FORWARD_WITH_PART_QUESTIONS: "CLICKED_FORWARD_WITH_PART_QUESTIONS",
CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE: "CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE",
CLICKED_FORWARD_WITH_MOLDING_QUESTIONS: "CLICKED_FORWARD_WITH_MOLDING_QUESTIONS",
CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS: "CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS",
CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS: "CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS",
CLICKED_BACK_WITH_PART_QUESTIONS: "CLICKED_BACK_WITH_PART_QUESTIONS",
CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE: "CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE",
CLICKED_BACK_WITH_MOLDING_QUESTIONS: "CLICKED_BACK_WITH_MOLDING_QUESTIONS",
CLICKED_BACK_WITH_CAPABILITY_QUESTIONS: "CLICKED_BACK_WITH_CAPABILITY_QUESTIONS",
CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS: "CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS",
CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS: "CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS",
// Insurance-Company
CLICKED_PAY_ON_MY_OWN: "CLICKED_PAY_ON_MY_OWN",
// Schedule
CLICKED_CHANGE_LOCATION: "CLICKED_CHANGE_LOCATION",
// Payment
CLICKED_INSURANCE: "CLICKED_INSURANCE",
CLICKED_PAY_NOW: "CLICKED_PAY_NOW",
CLICKED_PAY_LATER: "CLICKED_PAY_LATER",
PIA_ERROR: "PIA_ERROR",
PIA_CC_ERROR: "PIA_CC_ERROR",
PIA_APPLE_ERROR: "PIA_APPLE_ERROR",
PIA_AFTERPAY_ERROR: "PIA_AFTERPAY_ERROR",
PIA_SUCCESS: "PIA_SUCCESS",
// Return User
CLICKED_RESTART: "CLICKED_RESTART",
};
export { navigationScenarios };

View file

@ -0,0 +1,3 @@
export const ROUTE_PREFIX_TRIMMED = "fmg";
export const ROUTE_PREFIX_FULL = `/${ROUTE_PREFIX_TRIMMED}/`;

View file

@ -0,0 +1,123 @@
export const routeData = {
VEHICLE: {
name: "vehicle",
path: "/vehicle",
},
VEHICLE_DAMAGE: {
name: "vehicle-damage",
path: "/vehicle-damage",
},
ESTIMATE: {
name: "estimate",
path: "/estimate",
},
ADDRESS_LOOKUP: {
name: "address-lookup",
path: "/address-lookup",
},
VIN_LOOKUP: {
name: "vin-lookup",
path: "/vin-lookup",
},
LICENSE_PLATE_LOOKUP: {
name: "license-plate-lookup",
path: "/license-plate-lookup",
},
SERVICE_ZIP: {
name: "service-zip",
path: "/service-zip",
},
ADDRESS_VEHICLES: {
name: "address-vehicles",
path: "/address-vehicles",
},
VEHICLE_PARTS: {
name: "vehicle-parts",
path: "/vehicle-parts",
},
PART_QUESTIONS: {
name: "part-questions",
path: "/part-questions",
},
MOLDING_QUESTIONS: {
name: "molding-questions",
path: "/molding-questions",
},
CAPABILITY_QUESTIONS: {
name: "capability-questions",
path: "/capability-questions",
},
QUOTE: {
name: "quote",
path: "/quote",
},
INSURANCE_COMPANY: {
name: "insurance-company",
path: "/insurance-company",
},
SERVICE_LOCATION: {
name: "service-location",
path: "/service-location",
},
HERITAGE: {
name: "heritage",
path: "/virtual/heritage",
virtual: true,
},
SCHEDULE: {
name: "schedule",
path: "/schedule",
},
CUSTOMER_DETAILS: {
name: "customer-details",
path: "/customer-details",
},
PAYMENT_METHOD: {
name: "payment-method",
path: "/payment-method",
},
PAYMENT: {
name: "payment",
path: "/payment",
},
PAYMENT_PIA_RETURN: {
name: "payment-pia-return",
path: "/payment-pia-return",
},
CONFIRMATION: {
name: "confirmation",
path: "/confirmation",
},
RETURN_USER: {
name: "return-user",
path: "/return-user",
},
LOAD_SESSION: {
name: "load-session",
path: "/virtual/load-session",
virtual: true,
},
LANDING: {
name: "landing",
path: "/",
virtual: true,
},
AUTO_ROUTE: {
name: "auto-route",
path: "/virtual/auto-route",
virtual: true,
},
// TODO: RENAME FROM BAILOUT
ERROR: {
name: "error",
path: "/virtual/error",
virtual: true,
},
RESTART: {
name: "restart",
path: "/virtual/restart",
virtual: true,
},
};
export const FUNNEL_START_PAGE = routeData.VEHICLE;

View file

@ -0,0 +1,596 @@
import { routeData } from "@/router/a-rewrite/constants/routes";
import { navigationScenarios } from "@/router/a-rewrite/constants/navigation-scenarios";
import store from "@/store";
import { paymentMethods } from "../../../constants/payment-method-constants";
// Get as function to live-evaluate filters
const routingTable = function () {
return [
{
pageName: routeData.VEHICLE.name,
maps: [
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.VEHICLE_DAMAGE,
},
],
},
{
pageName: routeData.VEHICLE_DAMAGE.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.VEHICLE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_VIN,
destinationPageData: routeData.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
destinationPageData: routeData.ESTIMATE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SKIP_VIN,
destinationPageData: routeData.SERVICE_ZIP,
},
{
scenario:
navigationScenarios.CLICKED_FORWARD_WITH_REPAIR_AND_VERIFIED_INSURANCE,
destinationPageData: routeData.SERVICE_ZIP,
},
{
scenario:
navigationScenarios.CLICKED_FORWARD_WITH_REPLACE_AND_VERIFIED_INSURANCE,
destinationPageData: routeData.VIN_LOOKUP,
},
],
},
{
pageName: routeData.VIN_LOOKUP.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.ESTIMATE,
},
{
scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
destinationPageData: routeData.VEHICLE_DAMAGE,
params: {
displayVehicleChangeAlert: true,
},
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN,
destinationPageData: routeData.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_VIN_RETRY,
destinationPageData: routeData.ESTIMATE,
},
],
},
{
pageName: routeData.LICENSE_PLATE_LOOKUP.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.ESTIMATE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.VEHICLE_DAMAGE,
params: {
displayVehicleChangeAlert: true,
},
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_VIN_RETRY,
destinationPageData: routeData.ESTIMATE,
},
],
},
{
pageName: routeData.ADDRESS_LOOKUP.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.ESTIMATE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
destinationPageData: routeData.ADDRESS_VEHICLES,
},
{
scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
destinationPageData: routeData.VEHICLE_DAMAGE,
params: {
displayVehicleChangeAlert: true,
},
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_VIN_RETRY,
destinationPageData: routeData.ESTIMATE,
},
],
},
{
pageName: routeData.ADDRESS_VEHICLES.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.ADDRESS_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.VEHICLE_DAMAGE,
params: {
displayVehicleChangeAlert: true,
},
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_VIN_RETRY,
destinationPageData: routeData.ESTIMATE,
},
],
},
{
pageName: routeData.ESTIMATE.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.SELECTED_MANUAL_VIN,
destinationPageData: routeData.VIN_LOOKUP,
},
{
scenario: navigationScenarios.SELECTED_LICENSE_PLATE,
destinationPageData: routeData.LICENSE_PLATE_LOOKUP,
},
{
scenario: navigationScenarios.SELECTED_HOME_ADDRESS,
destinationPageData: routeData.ADDRESS_LOOKUP,
},
{
scenario: navigationScenarios.SELECTED_NO_VIN,
destinationPageData: routeData.SERVICE_ZIP,
},
],
},
{
pageName: routeData.SERVICE_ZIP.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.ESTIMATE,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_SKIP_VIN,
destinationPageData: routeData.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_QUESTIONS,
destinationPageData: routeData.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
},
],
},
{
pageName: routeData.PART_QUESTIONS.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
destinationPageData: routeData.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
destinationPageData: routeData.SERVICE_ZIP,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
},
],
},
{
pageName: routeData.VEHICLE_PARTS.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
destinationPageData: routeData.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
destinationPageData: routeData.SERVICE_ZIP,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
},
],
},
{
pageName: routeData.MOLDING_QUESTIONS.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
destinationPageData: routeData.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
destinationPageData: routeData.SERVICE_ZIP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
},
],
},
{
pageName: routeData.CAPABILITY_QUESTIONS.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
destinationPageData: routeData.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
destinationPageData: routeData.SERVICE_ZIP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
},
],
},
{
pageName: routeData.QUOTE.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
destinationPageData: routeData.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
destinationPageData: routeData.SERVICE_ZIP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CASH,
destinationPageData: routeData.SERVICE_LOCATION,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_INSURANCE,
destinationPageData: routeData.INSURANCE_COMPANY,
},
],
},
{
pageName: routeData.INSURANCE_COMPANY.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_PAY_ON_MY_OWN,
destinationPageData: routeData.QUOTE,
params: {
offer: "cash",
},
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.INSURANCE_DETAILS,
},
],
},
{
pageName: routeData.SERVICE_LOCATION.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.SCHEDULE,
},
],
},
{
pageName: routeData.SCHEDULE.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.SERVICE_LOCATION,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.CUSTOMER_DETAILS,
},
{
scenario: navigationScenarios.CLICKED_CHANGE_LOCATION,
destinationPageData: routeData.SERVICE_LOCATION,
},
],
},
{
pageName: routeData.CUSTOMER_DETAILS.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.SCHEDULE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.PAYMENT_METHOD,
},
{
scenario: navigationScenarios.CLICKED_PAY_NOW,
destinationPageData: routeData.PAYMENT_METHOD,
},
],
},
{
pageName: routeData.PAYMENT_METHOD.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.CUSTOMER_DETAILS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.CONFIRMATION,
},
{
scenario: navigationScenarios.CLICKED_PAY_NOW,
destinationPageData: routeData.PAYMENT,
},
{
scenario: navigationScenarios.CLICKED_INSURANCE,
destinationPageData: routeData.INSURANCE_COMPANY,
},
],
},
{
pageName: routeData.PAYMENT.name,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.PAYMENT_METHOD,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.CONFIRMATION,
},
{
scenario: navigationScenarios.PIA_ERROR,
destinationPageData: routeData.PAYMENT_METHOD,
params: {
piaError: "true",
},
},
],
},
{
pageName: routeData.PAYMENT_PIA_RETURN.name,
maps: [
{
scenario: navigationScenarios.PIA_ERROR,
destinationPageData: routeData.PAYMENT_METHOD,
params: {
piaError: "true",
},
},
{
scenario: navigationScenarios.PIA_CC_ERROR,
destinationPageData: routeData.PAYMENT,
params: {
piaErrorType: paymentMethods.CREDIT_CARD,
},
},
{
scenario: navigationScenarios.PIA_APPLE_ERROR,
destinationPageData: routeData.PAYMENT,
params: {
piaErrorType: paymentMethods.APPLE_PAY,
},
},
{
scenario: navigationScenarios.PIA_AFTERPAY_ERROR,
destinationPageData: routeData.PAYMENT,
params: {
piaErrorType: paymentMethods.AFTERPAY,
},
},
{
scenario: navigationScenarios.PIA_SUCCESS,
destinationPageData: routeData.CONFIRMATION,
},
],
},
{
pageName: routeData.CONFIRMATION.name,
},
{
pageName: routeData.RETURN_USER.name,
maps: [
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.LOAD_SESSION,
},
{
scenario: navigationScenarios.CLICKED_RESTART,
destinationPageData: routeData.RESTART,
},
],
},
];
};
export { routingTable };

View file

@ -0,0 +1,421 @@
import { routeData, FUNNEL_START_PAGE } from "@/router/a-rewrite/constants/routes";
import { createRoute, createVirtualRoute } from "@/router/a-rewrite/logic/create-route";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import { createWebHistory, createRouter } from "vue-router";
import { getDestination } from "@/router/a-rewrite/logic/get-destination";
import analyticsMixin from "@/mixins/analytics-mixin";
import {
getFunnelCookie,
deleteFunnelCookie,
updateOrCreateFunnelCookie,
} from "@/helpers/heritage-integration/cookie-helper";
import { isSavedSessionStillActive } from "@/helpers/heritage-integration/session-helper";
import { loadSessionIfPresent, saveSession } from "@/helpers/heritage-integration/order-helper";
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations";
import { sessionStorageKeyConstants } from "@/constants/session-storage";
import { savePageData } from "@/router/a-rewrite/logic/save-page-data";
import eventBus from "@/helpers/event-bus/event-bus";
import { globalEvents, globalEventTypes } from "@/constants/events";
import { autoRouteTable } from "@/router/a-rewrite/constants/auto-route-table";
import { queryStrings } from "@/constants/query-strings";
import { consumeReferralQuerystrings } from "@/router/a-rewrite/logic/consume-referral-info";
import { initializeFromQueryStrings } from "@/router/a-rewrite/logic/initialize-from-querystrings";
import { getBoolFromString } from "@/helpers/boolean-helper";
import { isVerifiedInsurance } from "@/router/a-rewrite/logic/requires-verified-redirect";
import baseMixin from "@/mixins/base-mixin";
import { runExperiments } from "@/router/a-rewrite/logic/run-experiments";
import { ROUTE_PREFIX_FULL } from "@/router/a-rewrite/constants/route-prefix";
import { buildManualUrl } from "@/router/a-rewrite/logic/build-manual-url";
import { consumeQueryFromStash, stashAllQueries } from "@/router/a-rewrite/logic/querystring-stash";
const routes = [
// Non-virtual pages.
createRoute(routeData.VEHICLE, async (to, from) => {
// If cookie indicates that vehicle has changed during insurance flow, reset parts info.
const hasVehicleChanged = getBoolFromString(getFunnelCookie()?.HasDelayedClaimRegistration);
if (hasVehicleChanged) {
store.commit(storeMutations.RESET_GLASS_PARTS_STATE);
}
if (isVerifiedInsurance()) {
return {
name: routeData.VEHICLE_DAMAGE.name,
replace: true,
};
}
}),
createRoute(routeData.VEHICLE_DAMAGE),
createRoute(routeData.ESTIMATE),
createRoute(routeData.ADDRESS_LOOKUP),
createRoute(routeData.VIN_LOOKUP),
createRoute(routeData.LICENSE_PLATE_LOOKUP),
createRoute(routeData.SERVICE_ZIP),
createRoute(routeData.ADDRESS_VEHICLES),
createRoute(routeData.VEHICLE_PARTS),
createRoute(routeData.PART_QUESTIONS),
createRoute(routeData.MOLDING_QUESTIONS),
createRoute(routeData.CAPABILITY_QUESTIONS),
createRoute(routeData.QUOTE, async (to, from) => {
if (isVerifiedInsurance()) {
return {
name: routeData.HERITAGE.name,
replace: true,
};
}
const offerQuote = to.query?.[queryStrings.OFFER_QUOTE];
if (offerQuote === "true") {
store.commit(storeMutations.UPDATE_IS_INSURANCE, false);
}
}),
createRoute(routeData.INSURANCE_COMPANY, async (to, from) => {
if (isVerifiedInsurance()) {
return {
name: routeData.HERITAGE.name,
replace: true,
};
}
}),
createRoute(routeData.SERVICE_LOCATION),
createRoute(routeData.SCHEDULE),
createRoute(routeData.CUSTOMER_DETAILS),
createRoute(routeData.PAYMENT_METHOD),
createRoute(routeData.PAYMENT),
createRoute(routeData.PAYMENT_PIA_RETURN),
createRoute(routeData.CONFIRMATION),
createRoute(routeData.RETURN_USER),
// Virtual pages (resolve to a non-virtual page.)
createVirtualRoute(routeData.LANDING, async (to, from) => {
await initializeFromQueryStrings();
// Save querystrings to temporary stash so they can be referred to later.
stashAllQueries(to);
// Change referral info. For use in local testing for insurance crossover.
await consumeReferralQuerystrings();
// Check for fmgpage parameter
const fmgPage = to?.query?.fmgPage;
if (fmgPage && router.hasRoute(fmgPage)) {
return {
name: fmgPage,
replace: true,
};
}
// If a session is still in memory, go to return-user.
if (store.getters.vehicle?.year > 0) {
console.log(`trying to redirect!`);
return {
name: routeData.RETURN_USER.name,
replace: true,
};
}
// Otherwise, load session and auto-route
return {
name: routeData.LOAD_SESSION.name,
replace: true,
};
}),
createVirtualRoute(routeData.HERITAGE, async (to, from) => {
await navigateToHeritageFunnel({ shouldSaveSession: false, pageNameToLog: to.name });
}),
createVirtualRoute(routeData.LOAD_SESSION, async (to, from) => {
const loadSessionResponse = await loadSessionIfPresent(false, to.name);
return {
name: routeData.AUTO_ROUTE.name,
replace: true,
};
}),
createVirtualRoute(routeData.AUTO_ROUTE, async (to, from) => {
for (let i = 0; i < autoRouteTable.length; i++) {
const testRouteData = autoRouteTable[i];
const isReady = await router.checkPagePrerequisites(testRouteData.name);
if (isReady) {
return {
name: testRouteData.name,
replace: true,
};
}
}
return {
name: FUNNEL_START_PAGE,
replace: true,
};
}),
createVirtualRoute(routeData.ERROR, async (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,
};
} else {
await store.dispatch(storeActions.UPDATE_HAS_TRIGGERED_ERROR, true);
}
// Add error event to bus
eventBus.addEventToBus(
globalEvents.Categories.GLOBAL_ALERT,
globalEvents.SubCategories.UNKNOWN_ERROR,
{
isDismissable: true,
messageCopy: "",
messageHeadline: "We're sorry, something went wrong.",
type: globalEventTypes.Danger,
}
);
let nextPage = FUNNEL_START_PAGE.name;
baseMixin.methods?.ResetExternalParamsAndHideModal();
if (store.getters.payment?.insuranceCoverage?.isVerified) {
nextPage = routeData.VEHICLE_DAMAGE.name;
}
if (from.name === nextPage) {
// Router won't load the page if we redirect to the already existing page
// Force refresh in this scenario.
router.go(0);
return false;
}
return {
name: nextPage,
replace: false,
};
}),
createVirtualRoute(routeData.RESTART, async (to, from) => {
await store.dispatch(storeActions.RESET_STATE);
deleteFunnelCookie();
if (from.name === FUNNEL_START_PAGE.name) {
// Router won't load the page if we redirect to the already existing page
// Force refresh in this scenario.
router.go(0);
return false;
}
return {
name: FUNNEL_START_PAGE.name,
replace: true,
};
}),
];
const router = createRouter({
history: createWebHistory(ROUTE_PREFIX_FULL),
routes,
// Scroll to top on navigation.
scrollBehavior(to, from, savedPosition) {
return { top: 0 };
},
});
////-- Global Guards
router.beforeEach(async (to, from) => {
console.log(to);
try {
await analyticsMixin.methods.validateSession();
if (getFunnelCookie()?.SuppressConceptFunnel) {
// Redirect to heritage.
return {
name: routeData.HERITAGE.name,
};
}
// Ensure session has not expired
if (getFunnelCookie() !== null && !isSavedSessionStillActive()) {
const errorPayload = {
cause: "expired session",
currentPage: from?.name,
nextPage: to?.name,
};
router.bailout(errorPayload, true);
return false;
}
// Block navigation if an order has been submitted.
if (window.sessionStorage.getItem(sessionStorageKeyConstants.SUBMITTED_STATE) !== null) {
if (to.name !== FUNNEL_START_PAGE.name && to.name !== routeData.CONFIRMATION.name) {
return false;
}
}
// Process funnel cookie.
updateOrCreateFunnelCookie();
// If sent from heritage, need to load session.
const fromHeritageFlag = consumeQueryFromStash(queryStrings.FROM_HERITAGE);
if (fromHeritageFlag) {
await loadSessionIfPresent(true, routeData.SERVICE_LOCATION.name);
}
// Ensure page-prerequisites are fulfilled
const arePagePrerequisitesValid = await router.checkPagePrerequisites(to.name);
if (!arePagePrerequisitesValid) {
const errorPayload = {
cause: "invalid page prerequisites for page",
currentPage: from?.name,
nextPage: to?.name,
};
router.bailout(errorPayload);
return;
}
await runExperiments(to.name);
} catch (error) {
const errorPayload = {
cause: "Uncaught exception in `beforeEach`.",
currentPage: from?.name,
nextPage: to?.name,
};
console.log(error);
router.bailout(errorPayload);
return;
}
});
router.afterEach(async (to, from) => {
// Push page view to GA
analyticsMixin.methods.pushPageViewToGA();
// Push experiments to Data Layer
analyticsMixin.methods.pushExperimentsToDataLayer();
// Push current order status to Data Layer
analyticsMixin.methods.pushOrderToDataLayer();
});
////-- End Global Guards
////-- Bound Functions
router.getRoute = (pageName) => {
return router.getRoutes().find((r) => r.name === pageName);
};
router.checkPagePrerequisites = async (pageName) => {
const route = router.getRoute(pageName);
if (!route) {
return false;
}
let component = route.components;
// Virtual routes have no component, so skip check.
if (!component) {
return true;
}
if (component?.default?.methods === undefined) {
component = await component?.default();
}
return component?.default?.methods?.arePagePrerequisitesValid();
};
router.navigateWithoutSaving = async (scenario, currentPageName) => {
return await router.navigate(currentPageName, scenario, false);
};
router.navigateWithSaving = async (scenario, currentPageName) => {
return await router.navigate(currentPageName, scenario, true);
};
router.navigateWithPageData = async (scenario, currentPageName, pageData = {}) => {
const nextPage = getDestination(currentPageName, scenario);
await savePageData(nextPage.name, pageData);
return await router.navigate(currentPageName, scenario, true);
};
router.navigateAndForceTopLevelNavigation = async (scenario, currentPageName, saving = false) => {
return await router.navigate(currentPageName, scenario, saving, true);
};
router.bailout = (errorPayload, forceRestart = false) => {
analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload);
if (forceRestart) {
router.push({
name: routeData.RESTART.name,
});
} else {
router.push({
name: routeData.ERROR.name,
});
}
};
router.navigate = async (
currentPageName,
scenario,
withSaving = false,
forceTopLevelNav = false
) => {
// Check to see if calling page is same as current page.
// If not, cancel navigation before it begins.
const callingRoute = currentPageName;
const actualRoute = router.currentRoute.value.name;
if (callingRoute !== actualRoute) {
return false;
}
const nextPage = getDestination(currentPageName, scenario);
if (!nextPage) {
console.error(
`Could not navigate from ${currentPageName} via scenario ${scenario}. Ensure routing table is configured correctly.`
);
const errorPayload = {
cause: "invalid page name",
currentPage: currentPageName,
nextPage: nextPage?.name,
};
router.bailout(errorPayload);
return;
}
if (withSaving) {
await saveSession({ pageNameToLog: nextPage.name });
}
// Some pages require manually setting the next url
// to work with iframes.
if (forceTopLevelNav) {
const newUrl = buildManualUrl(nextPage);
window.top.location.href = newUrl;
return;
}
// All other pages use router.push
router.push({
name: nextPage.name,
query: nextPage.params ?? {},
});
};
////-- End Router Functions
export default router;

View file

@ -0,0 +1,27 @@
import { ROUTE_PREFIX_TRIMMED } from "@/router/a-rewrite/constants/route-prefix";
export function buildManualUrl(nextPage) {
const queries = nextPage.params;
const querystring = buildSearchParams(queries);
const url = `${window.top.location.origin}/${ROUTE_PREFIX_TRIMMED}${nextPage.path}${querystring}`;
return url;
}
function buildSearchParams(paramList) {
if (!paramList) {
return "";
}
const keys = Object.keys(paramList);
if (keys?.length > 0) {
const queryFormattedParams = keys.map((k) => `${k}=${paramList[k]}`);
const querystring = queryFormattedParams.reduce((a, b) => `${a}&${b}`);
return `?${querystring}`;
}
return "";
}

View file

@ -0,0 +1,18 @@
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { queryStrings } from "@/constants/query-strings";
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";
import { updateOrCreateFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
export async function consumeReferralQuerystrings() {
const referralNumber = getQuerystringParameter(queryStrings.REFERRAL_NUMBER);
const parentAccount = getQuerystringParameter(queryStrings.PARENT_ACCOUNT);
const correlationId = getQuerystringParameter(queryStrings.CORRELATION_ID);
if (referralNumber) {
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber);
store.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, parentAccount);
store.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, correlationId);
// log(" --update cookie");
updateOrCreateFunnelCookie();
}
}

View file

@ -0,0 +1,39 @@
import { lazyLoadComponent } from "@/router/a-rewrite/logic/lazy-load-component";
import { routeData } from "@/router/a-rewrite/constants/routes";
export function createRoute(routeDatum, beforeEnter = async (to, from) => undefined) {
return {
name: routeDatum.name,
path: routeDatum.path,
component: lazyLoadComponent(routeDatum.name),
beforeEnter: async (to, from) => {
try {
return await beforeEnter(to, from);
} catch {
return {
name: routeData.BAILOUT.name,
replace: true,
};
}
},
};
}
export function createVirtualRoute(routeDatum, beforeEnter = async (to, from) => undefined) {
return {
name: routeDatum.name,
path: routeDatum.path,
beforeEnter: async (to, from) => {
try {
return await beforeEnter(to, from);
} catch (error) {
console.log(error);
return {
name: routeData.BAILOUT.name,
replace: true,
};
}
},
virtual: true,
};
}

View file

@ -0,0 +1,18 @@
import { routingTable } from "@/router/a-rewrite/constants/routing-table";
export function getDestination(sourcePageName, navigationScenario) {
const table = routingTable();
const pageEntry = table.find((entry) => entry.pageName === sourcePageName);
const map = pageEntry?.maps?.find((map) => map.scenario === navigationScenario);
if (!map || map?.filter === false) {
return null;
}
return {
...map.destinationPageData,
params: map.params,
};
}

View file

@ -0,0 +1,121 @@
import {
setupAdvertiserTracking,
getAffiliateCookies,
} from "@/helpers/heritage-integration/cookie-helper";
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";
import { storeActions } from "@/constants/store-actions";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { queryStrings } from "@/constants/query-strings";
import { externalParameterStatus } from "@/constants/external-parameters";
export async function initializeFromQueryStrings() {
// Get advertiser info
setupAdvertisersAndAffiliates();
// Read all external paramter queries and write to store.
updateExternalParameterState();
}
function setupAdvertisersAndAffiliates() {
const affiliateCookies = getAffiliateCookies();
if (affiliateCookies != null && affiliateCookies.length > 0) {
store.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies);
}
setupAdvertiserTracking();
}
function updateExternalParameterState() {
const externalParameterYear = getQuerystringParameter(queryStrings.VEHICLE_YEAR);
const externalParameterMake = getQuerystringParameter(queryStrings.VEHICLE_MAKE);
const externalParameterModel = getQuerystringParameter(queryStrings.VEHICLE_MODEL);
const externalParameterStyle = getQuerystringParameter(queryStrings.VEHICLE_STYLE);
const externalParameterDamage = getQuerystringParameter(queryStrings.VEHICLE_DAMAGE);
const externalParameterZipCode = getQuerystringParameter(queryStrings.SERVICE_ZIP);
const externalParameterEmail = getQuerystringParameter(queryStrings.EMAIL);
const externalParameterIsInsurance = getQuerystringParameter(queryStrings.IS_INSURANCE);
const externalParameterVinSelection = getQuerystringParameter(queryStrings.VIN_SELECTION);
const externalParameterServicePackage = getQuerystringParameter(queryStrings.SERVICE_PACKAGE);
const externalParameterNumberOfChips = getQuerystringParameter(queryStrings.NUMBER_OF_CHIPS);
const externalParameterSource = getQuerystringParameter(queryStrings.EXPERIMENTS);
const externalParameterPhoneNumber = getQuerystringParameter(queryStrings.PHONE_NUMBER);
if (
externalParameterYear &&
externalParameterMake &&
externalParameterModel &&
externalParameterStyle
) {
resetStoreForExternalParameter();
store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, externalParameterStatus.ACTIVE);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_YEAR, externalParameterYear);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MAKE, externalParameterMake);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MODEL, externalParameterModel);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_STYLE, externalParameterStyle);
}
if (
externalParameterDamage &&
(externalParameterDamage.toUpperCase() != "WINDSHIELDREPAIR" ||
externalParameterNumberOfChips?.length > 0)
) {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_DAMAGE_TYPE, externalParameterDamage);
if (externalParameterDamage.toUpperCase() == "WINDSHIELDREPLACE") {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_NUMBER_OF_CHIPS, null);
} else if (externalParameterDamage.toUpperCase() == "WINDSHIELDREPAIR") {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_REPAIR, true);
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_NUMBER_OF_CHIPS,
externalParameterNumberOfChips
);
}
}
if (externalParameterZipCode) {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_ZIP_CODE, externalParameterZipCode);
}
if (externalParameterEmail) {
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_EMAIL_ADDRESS,
externalParameterEmail
);
}
if (externalParameterIsInsurance?.toUpperCase() == "TRUE") {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_INSURANCE, true);
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_SERVICE_PACKAGE,
externalParameterServicePackage?.toLowerCase()
);
}
if (externalParameterDamage?.toUpperCase() != "WINDSHIELDREPAIR") {
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_VIN_SELECTION,
externalParameterVinSelection
);
}
if (externalParameterSource) {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_SOURCE, externalParameterSource);
}
if (externalParameterPhoneNumber) {
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_PHONE_NUMBER,
externalParameterPhoneNumber
);
}
}
// if there is an existing external parameter state then they have already been through from an external source(LeadGen) and
// are returning. clear out prior related things that need to be selected again like parts and damage type.
function resetStoreForExternalParameter() {
if (
store.getters.externalParameterState?.isExternalParameter ==
externalParameterStatus.INACTIVE
) {
store.dispatch(storeActions.RESET_VEHICLE_STATE_AND_DEPENDENCIES);
store.dispatch(storeActions.SAVE_SERVICE_ZIP_CODE_INFO, {
state: null,
zipCode: null,
zipCodeCtu: null,
});
store.dispatch(storeActions.SAVE_EMAIL, null);
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
}
}

View file

@ -0,0 +1,3 @@
export function lazyLoadComponent(componentName) {
return () => import(`@/layouts/${componentName}/${componentName}.vue`);
}

View file

@ -0,0 +1,58 @@
import { reactive } from "vue";
const queryStash = reactive({
queries: [],
});
function stash(key, value) {
const existingValue = getStashedQuery(key);
if (existingValue) {
existingValue.value = value;
existingValue.used = false;
return;
}
queryStash.queries.push({
key: key,
value: value,
used: false,
});
}
export function stashAllQueries(toRoute) {
const keys = Object.keys(toRoute.query);
keys.forEach((k) => stash(k, toRoute.query[k]));
}
function getStashedQuery(key) {
const match = queryStash.queries.find(
(entry) => entry?.key?.toLowerCase() === key?.toLowerCase()
);
return match;
}
export function peekQueryFromStash(key) {
return getStashedQuery(key)?.value;
}
export function consumeQueryFromStash(key) {
const match = getStashedQuery(key);
if (match) {
if (!match.used) {
match.used = true;
return match.value;
}
return null;
}
return null;
}
export function clearStash() {
queryStash.queries = [];
}

View file

@ -0,0 +1,8 @@
import store from "@/store";
export function isVerifiedInsurance() {
return (
store.getters.payment?.insuranceCoverage?.isVerified ||
store.getters.order?.referralNumber?.length === 6
);
}

View file

@ -0,0 +1,30 @@
import store from "@/store";
import baseMixin from "@/mixins/base-mixin";
import { storeActions } from "@/constants/store-actions";
import { getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper";
import { experimentTriggers } from "@/constants/experiments";
import { applicationConfig } from "@/constants/application-config";
export async function runExperiments(nextPageName) {
if (!store.getters.applicationUser.triggeredSiteEntry) {
await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.RUN_EXPERIMENTS_FOR_TRIGGER,
{
deviceId: getDeviceIdValue(),
triggerEvent: experimentTriggers.SITE_ENTRY,
triggerValue: applicationConfig.SITE_ENTRY_TRIGGER_VALUE,
},
nextPageName
);
}
await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.RUN_EXPERIMENTS_FOR_TRIGGER,
{
deviceId: getDeviceIdValue(),
triggerEvent: experimentTriggers.PAGE_ENTRY,
triggerValue: nextPageName,
},
nextPageName
);
}

View file

@ -0,0 +1,11 @@
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";
export async function savePageData(page, data) {
const existingPageData = store.getters.pageData(page);
const dataToSave = Object.keys(data).length > 0 ? data : (existingPageData ?? {});
// Save data if non-null
store.commit(storeMutations.UPDATE_PAGE_DATA, { page: page, data: dataToSave });
}

View file

@ -199,6 +199,7 @@ const getDefaultState = () => {
triggeredSiteEntry: false,
affiliateCookies: [],
loggingOption: false,
hasAlreadyTriggeredError: false,
},
};
};
@ -820,6 +821,9 @@ export const mutations = {
updateAffiliateCookies(state, affiliateCookies) {
state.applicationUser.affiliateCookies = affiliateCookies;
},
updateHasTriggeredError(state, hasTriggeredError) {
state.applicationUser.hasAlreadyTriggeredError = hasTriggeredError;
},
};
// Export Getters
@ -3419,6 +3423,10 @@ export const actions = {
}
}
},
updateHasTriggeredError(context, hasAlreadyTriggeredError) {
context.commit(storeMutations.UPDATE_HAS_TRIGGERED_ERROR, hasAlreadyTriggeredError);
},
};
export default createStore({