Merge branch 'develop' into kpatel/Misc_Fix
This commit is contained in:
commit
670f2548f3
123 changed files with 2386 additions and 2605 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ const GaActions = {
|
|||
SUBMITTED: "Submitted",
|
||||
DISPLAYED: "Displayed",
|
||||
CASH_QUOTE_DISPLAYED: "Cash quote displayed",
|
||||
SERVICE_PACKAGE_PRICE: "Service package price",
|
||||
MOBILE_AVAILABLE: "mobile_available",
|
||||
SHOPS_FIRST_DISPLAYED: "shops_first_displayed",
|
||||
MORE_LOCATIONS_CLICKED: "more_locations_clicked",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ const applicationConfig = {
|
|||
COOKIE_PATH: "/",
|
||||
CURRENT_ENVIRONMENT: process.env.VUE_APP_CURRENT_ENVIRONMENT, // "Localhost", "Dev", "QA", and "Prod"
|
||||
HERITAGE_FUNNEL: process.env.VUE_APP_HERITAGE_FUNNEL,
|
||||
SAFELITE_HOP: process.env.VUE_APP_SAFELITE_HOP,
|
||||
APPLICATION_NAME: "FixMyGlass",
|
||||
ANALYTICS_APPLICATION_NAME: "FixMyGlassNextGen",
|
||||
APPLICATION_ABBREVIATION: "fmg",
|
||||
|
|
@ -15,21 +16,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 +30,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 };
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ const storeActions = {
|
|||
UPDATE_EXTERNAL_PARAMETER_MMS: "updateExternalParameterMMS",
|
||||
|
||||
SAVE_LOGGING_OPTION: "saveLoggingOption",
|
||||
UPDATE_HAS_TRIGGERED_ERROR: "updateHasTriggeredError",
|
||||
};
|
||||
|
||||
export { storeActions };
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ const storeMutations = {
|
|||
UPDATE_SETTLED_TENDER_AMOUNT: "updateSettledTenderAmount",
|
||||
UPDATE_IS_RECAL_ACK_OPT_IN: "updateIsRecalAckOptIn",
|
||||
UPDATE_IS_MSR_FEE_APPLICABLE: "updateIsMSRFeeApplicable",
|
||||
UPDATE_CASH_PRICE_SUBTOTAL: "updateCashPriceSubTotal",
|
||||
|
||||
// EVENT BUS MUTATIONS
|
||||
ADD_EVENT_TO_BUS: "addEventToBus",
|
||||
|
|
@ -93,6 +94,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",
|
||||
|
|
|
|||
|
|
@ -35,4 +35,9 @@ export const inputButtonProps = {
|
|||
default: false,
|
||||
},
|
||||
suppressError: Boolean,
|
||||
labelBold: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1143,7 +1143,7 @@ describe("buttonQuestion.vue", () => {
|
|||
});
|
||||
|
||||
function setupMocks(mountOptionsMockData = {}) {
|
||||
const defaultMountOptions = { route: { query: { fmgPage: "page-name" } } };
|
||||
const defaultMountOptions = { route: { name: "page-name" } };
|
||||
const baseMountOptions = getMountOptions(
|
||||
Object.assign(defaultMountOptions, mountOptionsMockData)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Com
|
|||
v-if="questionText && answers && answers.length > 0"
|
||||
class="question-text d-flex"
|
||||
:class="{ 'small-question-text': isSmallQuestionText }">
|
||||
<span class="fw-bold w-100">{{ questionText }}</span>
|
||||
<span class="fw-bold w-100" :class="[labelBold ? 'span-bold' : '']">
|
||||
{{ questionText }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="w-100 d-flex justify-content-center">
|
||||
|
|
@ -57,6 +59,7 @@ https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Com
|
|||
:setLastValuePushedToGa="setLastValuePushedToGa"
|
||||
:isInsuranceSelected="isInsuranceSelected"
|
||||
:suppressError="suppressError"
|
||||
:labelBold="labelBold"
|
||||
@buttonEvent="handleButtonEvent"
|
||||
v-model="selectedValues" />
|
||||
<!-- For nested questions -->
|
||||
|
|
@ -141,6 +144,11 @@ export default {
|
|||
default: false,
|
||||
},
|
||||
isInsuranceSelected: Boolean,
|
||||
labelBold: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const propsClone = Object.assign({}, props);
|
||||
|
|
@ -360,6 +368,9 @@ export default {
|
|||
& > span {
|
||||
text-align: center;
|
||||
}
|
||||
.span-bold {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
.small-question-text {
|
||||
&.question-text {
|
||||
|
|
|
|||
|
|
@ -688,17 +688,18 @@ export default {
|
|||
if (!this.months) return;
|
||||
this.isLoading = true;
|
||||
let monthToShow;
|
||||
let monthStartDateNum = 0;
|
||||
let monthStartDate;
|
||||
|
||||
if (this.hideSomeDaysForInitialView) {
|
||||
monthToShow = this.months.find(
|
||||
({ isMonthThatHidesSomeDaysForInitialView }) =>
|
||||
isMonthThatHidesSomeDaysForInitialView
|
||||
);
|
||||
|
||||
// find the first day-hidden to become the next api call start date
|
||||
monthStartDateNum =
|
||||
monthToShow.dates.find(({ dayClasses }) => dayClasses.includes("day-hidden"))
|
||||
.dateNum - 1;
|
||||
monthStartDate = monthToShow.dates.find(({ dayClasses }) =>
|
||||
dayClasses.includes("day-hidden")
|
||||
);
|
||||
} else {
|
||||
if (this.calendarViewDirection === "future") {
|
||||
monthToShow = this.months.find((month) =>
|
||||
|
|
@ -713,9 +714,13 @@ export default {
|
|||
}
|
||||
}
|
||||
if (monthToShow) {
|
||||
const monthStartDateString = monthStartDate
|
||||
? monthStartDate.inputValue
|
||||
: monthToShow.dates[0].inputValue;
|
||||
|
||||
// make new API call with this month's start and end dates
|
||||
const moreSelectableDatesData = await this.updateSelectableDates(
|
||||
monthToShow.dates[monthStartDateNum].inputValue,
|
||||
monthStartDateString,
|
||||
monthToShow.dates[monthToShow.dates.length - 1].inputValue
|
||||
);
|
||||
this.isLoading = false;
|
||||
|
|
@ -1042,6 +1047,9 @@ export default {
|
|||
min-width: 3rem;
|
||||
width: 3rem;
|
||||
}
|
||||
&:hover {
|
||||
border: 2px solid $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.unavailable-day {
|
||||
|
|
@ -1083,7 +1091,6 @@ export default {
|
|||
}
|
||||
input[type="radio"]:checked + label:after {
|
||||
background-color: $black;
|
||||
top: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
:for="dropdownId"
|
||||
:aria-label="questionText"
|
||||
class="form-label"
|
||||
:class="[labelBold ? 'label-bold' : '']"
|
||||
v-html="questionText"></label>
|
||||
<select
|
||||
v-model="selectedOption"
|
||||
|
|
@ -61,6 +62,11 @@ export default {
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
labelBold: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const uuid = uuidv4();
|
||||
|
|
@ -133,6 +139,10 @@ export default {
|
|||
color: $black;
|
||||
font-weight: 500;
|
||||
}
|
||||
.label-bold {
|
||||
color: $black;
|
||||
font-weight: 600;
|
||||
}
|
||||
.form-label {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,9 +46,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import analyticsMixin from "@/mixins/analytics-mixin";
|
||||
import router from "@/router/index.js";
|
||||
import modalButtonMain from "@/digital-components/modal/ux-components/modal-button-main/modal-button-main";
|
||||
import { Modal } from "bootstrap";
|
||||
import { useForm } from "vee-validate";
|
||||
|
|
@ -91,11 +89,7 @@ export default {
|
|||
const validationResult = await this.validate();
|
||||
if (validationResult.valid) {
|
||||
if (analyticsMixin.methods.sessionExpired()) {
|
||||
analyticsMixin.methods.initSession();
|
||||
router.push({
|
||||
path: "/",
|
||||
query: { fmgPage: fmgPageValues.RETURN_USER },
|
||||
});
|
||||
this.$router.sendToReturnUser();
|
||||
} else {
|
||||
this.$emit("footer-button-event");
|
||||
}
|
||||
|
|
@ -119,12 +113,14 @@ export default {
|
|||
},
|
||||
onModalOpened() {
|
||||
this.onModalOpenedCallback?.();
|
||||
this.$emit("isModalOpened", true);
|
||||
},
|
||||
onModalClosed() {
|
||||
this.resetButtonStyle();
|
||||
this.onModalClosedCallback?.();
|
||||
if (this.suppressPageScroll)
|
||||
document.querySelector("body").classList.remove("prevent-modal-scroll");
|
||||
this.$emit("isModalOpened", false);
|
||||
},
|
||||
openModal() {
|
||||
if (this.suppressPageScroll)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<template>
|
||||
<span class="salesforce-webchat"></span>
|
||||
<span class="salesforce-webchat">
|
||||
<button v-show="hideSalesforceWebchatLaunchButton" class="salesforce-chat-button"></button>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -49,12 +51,121 @@ export default {
|
|||
};
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
.embeddedServiceHelpButton .helpButton .uiButton {
|
||||
background-color: #167cac;
|
||||
font-family: "Arial", sans-serif;
|
||||
<style lang="scss">
|
||||
.salesforce-webchat {
|
||||
.salesforce-chat-button {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xml:space='preserve' id='Layer_2' x='0' y='0' style='enable-background:new 0 0 24 24' version='1.1' viewBox='0 0 24 24'%3E%3Cstyle%3E .st0%7Bfill:%232e6fb6%7D %3C/style%3E%3Ccircle cx='12' cy='12' r='12' class='st0'/%3E%3Cpath d='M18.3 12c0 3.5-2.8 6.3-6.3 6.3-1.2 0-2.4-.4-3.4-1l-2.3.7s-.5.1-.3-.4.5-1.7.7-2.2c-.6-1-1-2.1-1-3.3 0-3.5 2.8-6.3 6.3-6.3 3.5-.1 6.3 2.7 6.3 6.2z' style='fill:%23fff'/%3E%3Ccircle cx='10.2' cy='12' r='.6' class='st0'/%3E%3Ccircle cx='12' cy='12' r='.6' class='st0'/%3E%3Ccircle cx='13.8' cy='12' r='.6' class='st0'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1.5rem 1.5rem;
|
||||
background-position: center;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
.embeddedServiceHelpButton .helpButton .uiButton:focus {
|
||||
outline: 1px solid #167cac;
|
||||
|
||||
.dockableContainer {
|
||||
&.showDockableContainer {
|
||||
font-family: AvertaRegular;
|
||||
color: $gray-600;
|
||||
.sidebarBody {
|
||||
button {
|
||||
background: $blue;
|
||||
color: $white;
|
||||
&:hover {
|
||||
background: $blue-700 !important;
|
||||
}
|
||||
}
|
||||
.form-element__help {
|
||||
color: $red;
|
||||
}
|
||||
.embeddedServiceSidebarFormField {
|
||||
.uiInput {
|
||||
.uiLabel-left {
|
||||
color: $gray-600;
|
||||
}
|
||||
}
|
||||
}
|
||||
.embeddedServiceSidebarButton {
|
||||
&.uiButton--inverse {
|
||||
.label {
|
||||
color: $white;
|
||||
text-decoration: underline;
|
||||
}
|
||||
&:not(:disabled):focus {
|
||||
background-color: $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
.embeddedServiceLiveAgentStateChatAvatar {
|
||||
&.isLightningOutContext {
|
||||
.agentIconColor0 {
|
||||
background-color: $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
.embeddedServiceLiveAgentStateChatInputFooter {
|
||||
.footerMenuWrapper {
|
||||
.footer-menu-items {
|
||||
.slds-dropdown__item {
|
||||
> a {
|
||||
padding-left: 0;
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.embeddedServiceLiveAgentStateChatInputFooter {
|
||||
.footerMenuWrapper {
|
||||
.footer-menu-items {
|
||||
a {
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.chatHeaderBranding {
|
||||
background-color: $blue;
|
||||
}
|
||||
span {
|
||||
&.required {
|
||||
color: $red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.embeddedServiceHelpButton {
|
||||
.helpButton {
|
||||
.uiButton {
|
||||
background-color: $blue !important;
|
||||
}
|
||||
}
|
||||
.embeddedServiceIcon {
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
.modalContainer {
|
||||
&.sidebarMinimized {
|
||||
&.layout-docted {
|
||||
&.embeddedServiceSidebar {
|
||||
.embeddedServiceSidebarMinimizedDefaultUI {
|
||||
.helpButton,
|
||||
.sidebarHeader {
|
||||
&.minimizedContainer {
|
||||
.embeddedServiceSidebarMinimizedDefaultUI {
|
||||
background-color: $blue;
|
||||
border: 1px solid $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ export default {
|
|||
getRouterLinkDisplayTextFromCopy,
|
||||
getExternalLink,
|
||||
navigateWithScenario(scenarioName) {
|
||||
this.$router.navigateWithoutSaving(scenarioName, this.$route);
|
||||
this.$router.navigateWithoutSaving(scenarioName, this.pageName);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
:class="[
|
||||
questionAlignment === 'center' ? 'text-center w-100 mb-5' : '',
|
||||
hideInput ? 'hide-input' : '',
|
||||
labelBold ? 'label-bold' : '',
|
||||
]"
|
||||
v-html="questionText"></label>
|
||||
<div
|
||||
|
|
@ -132,6 +133,11 @@ export default {
|
|||
isRequired: false,
|
||||
},
|
||||
autocomplete: String,
|
||||
labelBold: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const uuid = uuidv4();
|
||||
|
|
@ -251,6 +257,9 @@ export default {
|
|||
color: $black;
|
||||
font-weight: 500;
|
||||
}
|
||||
.label-bold {
|
||||
font-weight: 600;
|
||||
}
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
&.has-search-icon {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@
|
|||
hasIcon
|
||||
validationRules="street-address-required"
|
||||
autocomplete="street-address"
|
||||
@keydown.enter.prevent />
|
||||
@keydown.enter.prevent
|
||||
:labelBold="labelBold" />
|
||||
</div>
|
||||
</div>
|
||||
<transition name="fade" mode="out-in">
|
||||
|
|
@ -27,7 +28,8 @@
|
|||
customInputId="apartmentNumberOrBusinessName"
|
||||
cmsWidgetName="ApartmentNumberOrBusinessNameQuestionWidget"
|
||||
v-model="addressModel.apartmentNumberOrBusinessName"
|
||||
ref="apartmentNumberOrBusinessName" />
|
||||
ref="apartmentNumberOrBusinessName"
|
||||
:labelBold="labelBold" />
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
|
|
@ -40,7 +42,8 @@
|
|||
v-model="addressModel.city"
|
||||
ref="city"
|
||||
validationRules="city-required"
|
||||
autocomplete="address-level2" />
|
||||
autocomplete="address-level2"
|
||||
:labelBold="labelBold" />
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
|
|
@ -54,7 +57,8 @@
|
|||
ref="state"
|
||||
:options="stateOptions"
|
||||
validationRules="state-required"
|
||||
autocomplete="address-level1" />
|
||||
autocomplete="address-level1"
|
||||
:labelBold="labelBold" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
|
|
@ -64,7 +68,8 @@
|
|||
ref="zipCode"
|
||||
mask="#####"
|
||||
validationRules="zip-code-required|zip-code-format"
|
||||
autocomplete="postal-code" />
|
||||
autocomplete="postal-code"
|
||||
:labelBold="labelBold" />
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
|
|
@ -124,6 +129,11 @@ export default {
|
|||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
labelBold: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,21 @@
|
|||
<template>
|
||||
<div
|
||||
class="funnel-header d-flex justify-content-center align-items-center flex-column"
|
||||
v-if="imageSrc">
|
||||
<!-- HIDDEN FOR 05.08 <salesforceWebchat hideSalesforceWebchatLaunchButton />-->
|
||||
<img class="logo-image img-fluid" :src="imageSrc" alt="Safelite logo" />
|
||||
<!-- // menu-modal temporarily not in use until the hamburger menu is re-implemented for use with the progress bar. See display: none below. -->
|
||||
<menuModal />
|
||||
<!-- // menu-modal temporarily not in use until the hamburger menu is re-implemented for use with the progress bar. See display: none below. -->
|
||||
<progressBar />
|
||||
<div class="funnel-header" v-if="imageSrc">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="button-container">
|
||||
<!-- HIDDEN FOR 05.08 <salesforceWebchat hideSalesforceWebchatLaunchButton /> -->
|
||||
</div>
|
||||
<div class="site-logo">
|
||||
<img class="logo-image img-fluid" :src="imageSrc" alt="Safelite logo" />
|
||||
</div>
|
||||
<div class="button-container">
|
||||
<!-- // menu-modal temporarily not in use until the hamburger menu is re-implemented for use with the progress bar. See display: none below. -->
|
||||
<menuModal />
|
||||
<!-- // menu-modal temporarily not in use until the hamburger menu is re-implemented for use with the progress bar. See display: none below. -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex w-100">
|
||||
<progressBar />
|
||||
</div>
|
||||
</div>
|
||||
<template v-for="globalAlert in globalAlertMessages" :key="globalAlert.id">
|
||||
<transition name="fade" mode="out-in">
|
||||
|
|
@ -45,7 +53,7 @@ export default {
|
|||
cmsWidgetName: String,
|
||||
hideSalesforceWebchatLaunchButton: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -100,16 +108,23 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.menu-modal-container) {
|
||||
display: none; // This is temporary until the hamburger menu is re-implemented for use with the progress bar
|
||||
}
|
||||
.funnel-header {
|
||||
position: relative;
|
||||
padding-top: 0.97rem;
|
||||
}
|
||||
padding: 1rem 0;
|
||||
|
||||
.logo-image {
|
||||
width: auto;
|
||||
height: 1.1875rem;
|
||||
.button-container {
|
||||
width: 1.5rem;
|
||||
height: 1.625rem;
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
width: auto;
|
||||
height: 1.1875rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
:deep(.menu-modal-container) {
|
||||
display: none; // This is temporary until the hamburger menu is re-implemented for use with the progress bar
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -11,21 +11,6 @@
|
|||
<div class="bar3"></div>
|
||||
</button>
|
||||
</div>
|
||||
<div class="menu-modal-container">
|
||||
<button
|
||||
aria-hidden="true"
|
||||
tabindex="-1"
|
||||
class="menu-button"
|
||||
type="button"
|
||||
:class="[isActive ? 'active' : '']"
|
||||
@click="toggleModal"
|
||||
aria-label="Hamburger Menu (modal window)">
|
||||
<div class="bar1"></div>
|
||||
<div class="bar2"></div>
|
||||
<div class="bar3"></div>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Modal -->
|
||||
<div
|
||||
class="modal menu-modal fade"
|
||||
data-bs-backdrop="false"
|
||||
|
|
@ -123,9 +108,6 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
.menu-modal-container {
|
||||
position: absolute;
|
||||
padding: 1.47rem 0 1.47rem 1.47rem;
|
||||
right: 0;
|
||||
button {
|
||||
border: none;
|
||||
&.menu-button {
|
||||
|
|
@ -164,7 +146,7 @@ export default {
|
|||
}
|
||||
.modal {
|
||||
&.menu-modal {
|
||||
left: auto;
|
||||
//left: auto;
|
||||
height: calc(100% - 56px);
|
||||
top: 56px;
|
||||
border-top: 1px solid $gray-300;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ import store from "@/store";
|
|||
describe("progressBar", () => {
|
||||
test("progress should be 0", () => {
|
||||
// Arrange
|
||||
mockMixin.computed = {
|
||||
pageName: () => undefined,
|
||||
};
|
||||
|
||||
// Act
|
||||
const wrapper = shallowMount(progressBar, {
|
||||
|
|
@ -20,10 +23,8 @@ describe("progressBar", () => {
|
|||
describe("progressBar", () => {
|
||||
test("progress should be 4%", () => {
|
||||
// Arrange
|
||||
store.getters = {
|
||||
applicationUser: {
|
||||
lastPageVisited: "vehicle",
|
||||
},
|
||||
mockMixin.computed = {
|
||||
pageName: () => "vehicle",
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
@ -40,10 +41,8 @@ describe("progressBar", () => {
|
|||
describe("progressBar", () => {
|
||||
test("progress should be 48%", () => {
|
||||
// Arrange
|
||||
store.getters = {
|
||||
applicationUser: {
|
||||
lastPageVisited: "quote",
|
||||
},
|
||||
mockMixin.computed = {
|
||||
pageName: () => "quote",
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
@ -60,10 +59,8 @@ describe("progressBar", () => {
|
|||
describe("progressBar", () => {
|
||||
test("progress should be 100%", () => {
|
||||
// Arrange
|
||||
store.getters = {
|
||||
applicationUser: {
|
||||
lastPageVisited: "confirmation",
|
||||
},
|
||||
mockMixin.computed = {
|
||||
pageName: () => "confirmation",
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -10,15 +10,10 @@ import { getProgressBarPercentage } from "@/constants/progress-bar-mapper";
|
|||
|
||||
export default {
|
||||
name: "progressBar",
|
||||
data() {
|
||||
return {
|
||||
progress: this.getProgress(),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getProgress() {
|
||||
var pageName = store.getters.applicationUser.lastPageVisited;
|
||||
return getProgressBarPercentage(pageName);
|
||||
data() {},
|
||||
computed: {
|
||||
progress() {
|
||||
return getProgressBarPercentage(this.pageName);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -245,6 +245,7 @@ function setupMocks() {
|
|||
};
|
||||
const mountOptions = getMountOptions({
|
||||
mixins: [baseMixin, vehicleQuestionsMixin],
|
||||
route: { name: "questions" },
|
||||
});
|
||||
mountOptions["attachTo"] = document.body;
|
||||
const wrapper = shallowMount(questionsPageLayout, mountOptions);
|
||||
|
|
|
|||
|
|
@ -45,9 +45,7 @@
|
|||
<script>
|
||||
import textLink from "@/ux-components/text-link/text-link";
|
||||
import buttonMain from "@/ux-components/button-main/button-main";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import analyticsMixin from "@/mixins/analytics-mixin";
|
||||
import router from "@/router/index.js";
|
||||
|
||||
export default {
|
||||
name: "navbar",
|
||||
|
|
@ -113,12 +111,7 @@ export default {
|
|||
}
|
||||
},
|
||||
routeReturnUser() {
|
||||
analyticsMixin.methods.initSession();
|
||||
|
||||
router.push({
|
||||
path: "/",
|
||||
query: { fmgPage: fmgPageValues.RETURN_USER },
|
||||
});
|
||||
this.$router.sendToReturnUser();
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ it("Global Methods - Call Http Client - Should Reject Promise", () => {
|
|||
isError: true,
|
||||
});
|
||||
analyticsMixIn.methods.pushEventToGA = jest.fn();
|
||||
router.navigateError = jest.fn();
|
||||
router.bailout = jest.fn();
|
||||
|
||||
//Act
|
||||
globalMethods.callHttpClient(httpArgs).catch((err) => {
|
||||
|
|
|
|||
23
src/helpers/debug-log-helper.js
Normal file
23
src/helpers/debug-log-helper.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import store from "@/store";
|
||||
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
|
||||
export function debugLog(message, data, forceLog = false) {
|
||||
checkLogParam();
|
||||
|
||||
if (store?.getters?.applicationUser?.loggingOption || forceLog) {
|
||||
data = data ?? "";
|
||||
const outData = typeof data === "object" ? JSON.stringify(data) : data;
|
||||
|
||||
console.log(`${new Date()} ${message} ${outData}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function checkLogParam() {
|
||||
const logQueryString = getQuerystringParameter(queryStrings.LOG);
|
||||
|
||||
if (logQueryString) {
|
||||
store?.dispatch(storeActions?.SAVE_LOGGING_OPTION, logQueryString);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,123 +1,23 @@
|
|||
import { queryStrings } from "@/constants/query-strings";
|
||||
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||
import { externalUrls } from "@/router/router-constants/externalUrl-values";
|
||||
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
|
||||
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { storeActions } from "@/constants/store-actions.js";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import experimentMixin from "@/mixins/experiment-mixin";
|
||||
import { experimentSettings } from "@/constants/experiments";
|
||||
import { includesWindshieldReplacement } from "@/helpers/damage-helper";
|
||||
import { applicationConfig } from "@/constants/application-config.js";
|
||||
import store from "@/store";
|
||||
import router from "@/router";
|
||||
|
||||
export async function getPageToRouteExistingOrderTo(toRoute = {}) {
|
||||
const fmgQueryPage = toRoute.query[queryStrings.FMG_PAGE];
|
||||
const hasFmgQueryPage = !!fmgQueryPage;
|
||||
|
||||
if (hasFmgQueryPage) {
|
||||
return await getDirectNavigation(toRoute);
|
||||
} else {
|
||||
return await getImplicitNavigation(toRoute);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the user to the specified page, except in specific scenarios.
|
||||
*/
|
||||
export async function getDirectNavigation(toRoute) {
|
||||
const fmgPageValue = toRoute.query[queryStrings.FMG_PAGE];
|
||||
|
||||
// Verified insurance users need to be routed around some pages. Same goes for C&C unverified 6 digit referrals
|
||||
// vehicle -> vehicle-damage
|
||||
// quote -> vin-lookup/estimate
|
||||
// insurance-company -> vin-lookup/estimate
|
||||
if (
|
||||
store.getters.payment?.insuranceCoverage?.isVerified ||
|
||||
store.getters.order?.referralNumber?.length === 6
|
||||
) {
|
||||
if (fmgPageValue === fmgPageValues.VEHICLE) {
|
||||
return fmgPageValues.VEHICLE_DAMAGE;
|
||||
}
|
||||
|
||||
if (fmgPageValue === fmgPageValues.QUOTE) {
|
||||
const skipVin = await skipVinLookup();
|
||||
|
||||
if (skipVin || !store.getters.vehicle?.vin) {
|
||||
return fmgPageValues.ESTIMATE;
|
||||
} else {
|
||||
return fmgPageValues.VIN_LOOKUP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, respect navigation from query string.
|
||||
return fmgPageValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine which page in the flow the user should be sent to, based on their current order.
|
||||
* General strategy: run through pages in reverse order, and select first where prerequisites are valid.
|
||||
* QUOTE is the latest page to send to.
|
||||
*/
|
||||
export async function getImplicitNavigation(toRoute) {
|
||||
const vehicleDamageComponent = await getLazyLoadedComponent(fmgPageValues.VEHICLE_DAMAGE);
|
||||
const estimateComponent = await getLazyLoadedComponent(fmgPageValues.ESTIMATE);
|
||||
const vinLookupComponent = await getLazyLoadedComponent(fmgPageValues.VIN_LOOKUP);
|
||||
const partQuestionsComponent = await getLazyLoadedComponent(fmgPageValues.PART_QUESTIONS);
|
||||
const vehiclePartsComponent = await getLazyLoadedComponent(fmgPageValues.VEHICLE_PARTS);
|
||||
const moldingQuestionsComponent = await getLazyLoadedComponent(fmgPageValues.MOLDING_QUESTIONS);
|
||||
const capabilityQuestionsComponent = await getLazyLoadedComponent(
|
||||
fmgPageValues.CAPABILITY_QUESTIONS
|
||||
);
|
||||
const quoteComponent = await getLazyLoadedComponent(fmgPageValues.QUOTE);
|
||||
|
||||
const skipVin = await skipVinLookup();
|
||||
|
||||
if (store.getters.order.payment.insuranceCoverage?.isVerified) {
|
||||
return fmgPageValues.HERITAGE;
|
||||
}
|
||||
|
||||
if (quoteComponent.methods.arePagePrerequisitesValid()) {
|
||||
// Do not send to quote if verified insurance user.
|
||||
if (store.getters.requiresVerifiedRedirecting) {
|
||||
return fmgPageValues.HERITAGE;
|
||||
} else {
|
||||
return fmgPageValues.QUOTE;
|
||||
}
|
||||
} else if (capabilityQuestionsComponent.methods.arePagePrerequisitesValid()) {
|
||||
return fmgPageValues.CAPABILITY_QUESTIONS;
|
||||
} else if (moldingQuestionsComponent.methods.arePagePrerequisitesValid()) {
|
||||
return fmgPageValues.MOLDING_QUESTIONS;
|
||||
} else if (vehiclePartsComponent.methods.arePagePrerequisitesValid()) {
|
||||
return fmgPageValues.VEHICLE_PARTS;
|
||||
} else if (partQuestionsComponent.methods.arePagePrerequisitesValid()) {
|
||||
return fmgPageValues.PART_QUESTIONS;
|
||||
} else if (vinLookupComponent.methods.arePagePrerequisitesValid() && !skipVin) {
|
||||
return fmgPageValues.VIN_LOOKUP;
|
||||
} else if (estimateComponent.methods.arePagePrerequisitesValid()) {
|
||||
return fmgPageValues.ESTIMATE;
|
||||
} else if (vehicleDamageComponent.methods.arePagePrerequisitesValid()) {
|
||||
return fmgPageValues.VEHICLE_DAMAGE;
|
||||
} else {
|
||||
return fmgPageValues.VEHICLE;
|
||||
}
|
||||
}
|
||||
import { debugLog } from "@/helpers/debug-log-helper";
|
||||
|
||||
/*
|
||||
Used to navigate to the heritage funnel with the correct query string and url.
|
||||
*/
|
||||
|
||||
export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLog, navType }) {
|
||||
const log = getQuerystringParameter(queryStrings.LOG);
|
||||
if (log === "true") {
|
||||
console.log("------------- Navigate to heritage start -----------------");
|
||||
console.log(new Date() + " applicationConfig: " + JSON.stringify(applicationConfig));
|
||||
console.log(new Date() + " navigateToHeritageFunnel: " + applicationConfig.HERITAGE_FUNNEL);
|
||||
console.log("------------- Navigate to heritage end -----------------");
|
||||
}
|
||||
debugLog("--- Navigate to heritage start ---");
|
||||
debugLog("applicationConfig:", applicationConfig);
|
||||
debugLog("navigateToHeritageFunnel:", applicationConfig.HERITAGE_FUNNEL);
|
||||
debugLog("--- Navigate to heritage end ---");
|
||||
|
||||
// Create the order (or save existing order) when navigating to Heritage Funnel.
|
||||
if (shouldSaveSession) {
|
||||
|
|
@ -191,7 +91,3 @@ export async function skipVinLookupNotRepair() {
|
|||
experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true")
|
||||
);
|
||||
}
|
||||
|
||||
async function getLazyLoadedComponent(pageName) {
|
||||
return (await lazyLoadComponent(pageName)()).default;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import * as navigationHelper from "@/helpers/heritage-integration/navigation-helper";
|
||||
import * as orderHelper from "@/helpers/heritage-integration/order-helper";
|
||||
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
|
||||
import { lazyLoadComponent } from "@/router/methods/helpers/lazy-load-component";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { storeMutations } from "@/constants/store-mutations";
|
||||
import { setupMocksForJsFiles, getMockOrderInfo } from "@/helpers/unit-test-helper.js";
|
||||
import { externalUrls } from "@/router/router-constants/externalUrl-values";
|
||||
import { externalUrls } from "@/router/constants/externalUrl-values";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
|
||||
import { damageLocationsSelected as glassLocations } from "@/constants/damage-locations-selected";
|
||||
|
||||
|
|
@ -17,476 +16,10 @@ const getPageToRouteExistingOrderTo = navigationHelper.getPageToRouteExistingOrd
|
|||
const navigateToHeritageFunnel = navigationHelper.navigateToHeritageFunnel;
|
||||
|
||||
// Mock Lazy Load
|
||||
jest.mock("@/router/dynamic-routing/component-loader.js", () => ({
|
||||
jest.mock("@/router/methods/helpers/lazy-load-component", () => ({
|
||||
lazyLoadComponent: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("getPageToRouteExistingOrderTo", () => {
|
||||
describe("Explicit vs. Implicit Routing", () => {
|
||||
test("Should call explicit routing if `fmgPage` parameter is present in query", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {
|
||||
fmgPage: "schedule",
|
||||
},
|
||||
};
|
||||
|
||||
mockLazyLoadComponentReturnValues();
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
// Assert
|
||||
// If direct, should be "schedule".
|
||||
// Otherwise, not.
|
||||
expect(result).toBe("schedule");
|
||||
});
|
||||
|
||||
test("Should call implicit routing if `fmgPage` parameter is NOT present in query", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
mockLazyLoadComponentReturnValues();
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
// Assert
|
||||
// If direct, should be "schedule".
|
||||
// Otherwise, not.
|
||||
expect(result).not.toBe("schedule");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Implicit Routing", () => {
|
||||
test("should return vehicle", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
|
||||
// Mock out the lazy load calls for all components.
|
||||
mockLazyLoadComponentReturnValues({
|
||||
[fmgPageValues.VEHICLE]: true,
|
||||
[fmgPageValues.VEHICLE_DAMAGE]: false,
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(fmgPageValues.VEHICLE);
|
||||
});
|
||||
|
||||
test("should return vehicle-damage", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
|
||||
// Mock out the lazy load calls for all components.
|
||||
mockLazyLoadComponentReturnValues({
|
||||
[fmgPageValues.VEHICLE]: true,
|
||||
[fmgPageValues.VEHICLE_DAMAGE]: true,
|
||||
[fmgPageValues.ESTIMATE]: false,
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(fmgPageValues.VEHICLE_DAMAGE);
|
||||
});
|
||||
|
||||
test("user has YMMS and no vehicle questions > should return estimate", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
|
||||
const mockExperimentsList = [
|
||||
{
|
||||
universeName: "ConceptFunnel",
|
||||
settings: {
|
||||
SuppressVinCapture: false,
|
||||
},
|
||||
},
|
||||
];
|
||||
store.commit(storeMutations.UPDATE_EXPERIMENTS, mockExperimentsList);
|
||||
|
||||
// Mock out the lazy load calls for all components.
|
||||
mockLazyLoadComponentReturnValues({
|
||||
[fmgPageValues.VEHICLE]: true,
|
||||
[fmgPageValues.VEHICLE_DAMAGE]: true,
|
||||
[fmgPageValues.ESTIMATE]: true,
|
||||
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
|
||||
[fmgPageValues.MOLDING_QUESTIONS]: false,
|
||||
[fmgPageValues.VEHICLE_PARTS]: false,
|
||||
[fmgPageValues.PART_QUESTIONS]: false,
|
||||
[fmgPageValues.VIN_LOOKUP]: true,
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(fmgPageValues.ESTIMATE);
|
||||
});
|
||||
|
||||
test("user has YMMS but no questions or carId > should return estimate", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
|
||||
// Mock out the lazy load calls for all components.
|
||||
mockLazyLoadComponentReturnValues({
|
||||
[fmgPageValues.VEHICLE]: true,
|
||||
[fmgPageValues.VEHICLE_DAMAGE]: true,
|
||||
[fmgPageValues.ESTIMATE]: true,
|
||||
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
|
||||
[fmgPageValues.MOLDING_QUESTIONS]: false,
|
||||
[fmgPageValues.VEHICLE_PARTS]: false,
|
||||
[fmgPageValues.PART_QUESTIONS]: false,
|
||||
[fmgPageValues.VIN_LOOKUP]: false,
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(fmgPageValues.ESTIMATE);
|
||||
});
|
||||
|
||||
test("user has capability questions and molding questions > should return capability questions", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
|
||||
// Mock out the lazy load calls for all components.
|
||||
mockLazyLoadComponentReturnValues({
|
||||
[fmgPageValues.VEHICLE]: true,
|
||||
[fmgPageValues.VEHICLE_DAMAGE]: true,
|
||||
[fmgPageValues.ESTIMATE]: true,
|
||||
[fmgPageValues.CAPABILITY_QUESTIONS]: true,
|
||||
[fmgPageValues.MOLDING_QUESTIONS]: true,
|
||||
[fmgPageValues.VEHICLE_PARTS]: false,
|
||||
[fmgPageValues.PART_QUESTIONS]: false,
|
||||
[fmgPageValues.VIN_LOOKUP]: false,
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(fmgPageValues.CAPABILITY_QUESTIONS);
|
||||
});
|
||||
|
||||
test("user has molding questions and part questions > should return molding questions", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
|
||||
// Mock out the lazy load calls for all components.
|
||||
mockLazyLoadComponentReturnValues({
|
||||
[fmgPageValues.VEHICLE]: true,
|
||||
[fmgPageValues.VEHICLE_DAMAGE]: true,
|
||||
[fmgPageValues.ESTIMATE]: true,
|
||||
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
|
||||
[fmgPageValues.MOLDING_QUESTIONS]: true,
|
||||
[fmgPageValues.VEHICLE_PARTS]: false,
|
||||
[fmgPageValues.PART_QUESTIONS]: true,
|
||||
[fmgPageValues.VIN_LOOKUP]: false,
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(fmgPageValues.MOLDING_QUESTIONS);
|
||||
});
|
||||
|
||||
test("user has vehicle parts questions > should return vehicle-parts", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
|
||||
// Mock out the lazy load calls for all components.
|
||||
mockLazyLoadComponentReturnValues({
|
||||
[fmgPageValues.VEHICLE]: true,
|
||||
[fmgPageValues.VEHICLE_DAMAGE]: true,
|
||||
[fmgPageValues.ESTIMATE]: true,
|
||||
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
|
||||
[fmgPageValues.MOLDING_QUESTIONS]: false,
|
||||
[fmgPageValues.VEHICLE_PARTS]: true,
|
||||
[fmgPageValues.PART_QUESTIONS]: true,
|
||||
[fmgPageValues.VIN_LOOKUP]: false,
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(fmgPageValues.VEHICLE_PARTS);
|
||||
});
|
||||
|
||||
test("user has part questions > should return part-questions", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
|
||||
// Mock out the lazy load calls for all components.
|
||||
mockLazyLoadComponentReturnValues({
|
||||
[fmgPageValues.VEHICLE]: true,
|
||||
[fmgPageValues.VEHICLE_DAMAGE]: true,
|
||||
[fmgPageValues.ESTIMATE]: true,
|
||||
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
|
||||
[fmgPageValues.MOLDING_QUESTIONS]: false,
|
||||
[fmgPageValues.VEHICLE_PARTS]: false,
|
||||
[fmgPageValues.PART_QUESTIONS]: true,
|
||||
[fmgPageValues.VIN_LOOKUP]: false,
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(fmgPageValues.PART_QUESTIONS);
|
||||
});
|
||||
|
||||
test("should return quote, if not verified insurance", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
|
||||
// Mock out the lazy load calls for all components.
|
||||
mockLazyLoadComponentReturnValues({
|
||||
[fmgPageValues.VEHICLE]: true,
|
||||
[fmgPageValues.VEHICLE_DAMAGE]: true,
|
||||
[fmgPageValues.ESTIMATE]: true,
|
||||
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
|
||||
[fmgPageValues.MOLDING_QUESTIONS]: false,
|
||||
[fmgPageValues.VEHICLE_PARTS]: false,
|
||||
[fmgPageValues.PART_QUESTIONS]: true,
|
||||
[fmgPageValues.VIN_LOOKUP]: false,
|
||||
[fmgPageValues.QUOTE]: true,
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(fmgPageValues.QUOTE);
|
||||
});
|
||||
|
||||
test("should not return pages beyond quote even if prerequisites are met", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
|
||||
// Mock out the lazy load calls for all components.
|
||||
mockLazyLoadComponentReturnValues({
|
||||
[fmgPageValues.VEHICLE]: true,
|
||||
[fmgPageValues.VEHICLE_DAMAGE]: true,
|
||||
[fmgPageValues.ESTIMATE]: true,
|
||||
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
|
||||
[fmgPageValues.MOLDING_QUESTIONS]: false,
|
||||
[fmgPageValues.VEHICLE_PARTS]: false,
|
||||
[fmgPageValues.PART_QUESTIONS]: true,
|
||||
[fmgPageValues.VIN_LOOKUP]: false,
|
||||
[fmgPageValues.QUOTE]: true,
|
||||
[fmgPageValues.SERVICE_LOCATION]: true,
|
||||
[fmgPageValues.SCHEDULE]: true,
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
//Assert
|
||||
expect(result).toBe(fmgPageValues.QUOTE);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Explicit Routing", () => {
|
||||
test("Returns the value passed in in nominal case", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {
|
||||
fmgPage: "testValue",
|
||||
},
|
||||
};
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe("testValue");
|
||||
});
|
||||
|
||||
describe("Verified users", () => {
|
||||
test("Replace navigation to `vehicle` with `vehicle-damage`", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {
|
||||
fmgPage: fmgPageValues.VEHICLE,
|
||||
},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, true);
|
||||
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "666666");
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(fmgPageValues.VEHICLE_DAMAGE);
|
||||
});
|
||||
|
||||
describe("Vin-Exempt", () => {
|
||||
test("Replace navigation to `quote` with `estimate`", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {
|
||||
fmgPage: fmgPageValues.QUOTE,
|
||||
},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, true);
|
||||
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "666666");
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, true);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(fmgPageValues.ESTIMATE);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Vin-Required", () => {
|
||||
test("Replace navigation to `quote` with `vin-lookup`", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {
|
||||
fmgPage: fmgPageValues.QUOTE,
|
||||
},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, true);
|
||||
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "666666");
|
||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
||||
store.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, [
|
||||
{ glassLocation: glassLocations.WINDSHIELD },
|
||||
]);
|
||||
store.commit(storeMutations.UPDATE_VEHICLE_VIN, "abcd1234");
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(fmgPageValues.VIN_LOOKUP);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Non-verified users", () => {
|
||||
test("Don't replace navigation to `vehicle` with `vehicle-damage`", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {
|
||||
fmgPage: fmgPageValues.VEHICLE,
|
||||
},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, false);
|
||||
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "55555");
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(fmgPageValues.VEHICLE);
|
||||
});
|
||||
|
||||
test("Don't replace navigation to `quote` with `estimate` or `vin-lookup`", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {
|
||||
fmgPage: fmgPageValues.QUOTE,
|
||||
},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, false);
|
||||
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "55555");
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(fmgPageValues.QUOTE);
|
||||
});
|
||||
|
||||
test("Don't replace navigation to `insurance-company` with `estimate` or `vin-lookup`", async () => {
|
||||
// Arrange
|
||||
const toRoute = {
|
||||
query: {
|
||||
fmgPage: fmgPageValues.INSURANCE_COMPANY,
|
||||
},
|
||||
};
|
||||
|
||||
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, false);
|
||||
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "55555");
|
||||
|
||||
// Act
|
||||
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(fmgPageValues.INSURANCE_COMPANY);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("navigateToHeritageFunnel", () => {
|
||||
test("should save session", async () => {
|
||||
// Arrange
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { storeActions } from "@/constants/store-actions";
|
||||
import { storeMutations } from "@/constants/store-mutations.js";
|
||||
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios.js";
|
||||
import { navigationScenarios } from "@/router/constants/navigation-scenarios.js";
|
||||
import { vehicleCategories } from "@/constants/vehicle-categories.js";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { cookieNames } from "@/constants/cookie-names";
|
||||
import { Form } from "vee-validate";
|
||||
import baseMixin from "@/mixins/base-mixin";
|
||||
|
|
@ -19,7 +18,6 @@ import {
|
|||
ValueToLogTypes,
|
||||
} from "@/constants/analytics";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
import { routerParams } from "@/router/router-constants/router-params";
|
||||
|
||||
// Common methods
|
||||
export function getMountOptions(mockData) {
|
||||
|
|
@ -60,7 +58,6 @@ export function getMountOptions(mockData) {
|
|||
mocks.storeMutations = storeMutations;
|
||||
mocks.navigationScenarios = navigationScenarios;
|
||||
mocks.vehicleCategories = vehicleCategories;
|
||||
mocks.fmgPageValues = fmgPageValues;
|
||||
mocks.analyticsPageEvents = analyticsPageEvents;
|
||||
mocks.GaCategories = GaCategories;
|
||||
mocks.GaActions = GaActions;
|
||||
|
|
@ -68,7 +65,6 @@ export function getMountOptions(mockData) {
|
|||
mocks.GaEvents = GaEvents;
|
||||
mocks.ValueToLogTypes = ValueToLogTypes;
|
||||
mocks.queryStrings = queryStrings;
|
||||
mocks.routerParams = routerParams;
|
||||
|
||||
// Mock $store and $router when accessing this.$store/$router
|
||||
mocks.$store = mockData.store;
|
||||
|
|
@ -80,6 +76,11 @@ export function getMountOptions(mockData) {
|
|||
mocks: mocks,
|
||||
mixins: mockData.mixins,
|
||||
stubs: { Form },
|
||||
computed: {
|
||||
pageName() {
|
||||
return mockData?.route?.name;
|
||||
},
|
||||
},
|
||||
};
|
||||
const props = mockData.propsData || {};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { shallowMount } from "@vue/test-utils";
|
|||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { storeMutations } from "@/constants/store-mutations";
|
||||
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
|
||||
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
|
||||
import store from "@/store";
|
||||
import { experimentSettings } from "@/constants/experiments";
|
||||
|
||||
|
|
@ -308,11 +308,9 @@ describe("address-lookup.vue", () => {
|
|||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
carsFound
|
||||
);
|
||||
});
|
||||
|
|
@ -399,9 +397,7 @@ describe("address-lookup.vue", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
|
||||
navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
undefined,
|
||||
{},
|
||||
{ displayVehicleChangeAlert: true }
|
||||
undefined
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -717,6 +713,7 @@ function setupMocks({
|
|||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
},
|
||||
store: {
|
||||
getters: {
|
||||
|
|
|
|||
|
|
@ -118,12 +118,11 @@ import { errorMessages } from "@/constants/error-messages";
|
|||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { routerParams } from "@/router/router-constants/router-params";
|
||||
import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-helper";
|
||||
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 { routeData } from "@/router/constants/routes";
|
||||
|
||||
// DEFINE VALIDATION RULES - Note: Additional rules are defined in Customer Questions and Address Questions components
|
||||
defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||
|
|
@ -137,7 +136,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 +192,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, () => {
|
||||
|
|
@ -409,7 +411,7 @@ export default {
|
|||
await this.dispatchStoreAction(
|
||||
storeActions.SAVE_PAGE_DATA,
|
||||
{
|
||||
page: fmgPageValues.EMAIL_SMS_PAGES,
|
||||
page: routeData.SERVICE_ZIP.name,
|
||||
data: { emailOrSmsValue: this.customerQuestions.emailOrSms },
|
||||
},
|
||||
false
|
||||
|
|
@ -442,18 +444,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
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
|||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import store from "@/store";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
import { Form, defineRule } from "vee-validate";
|
||||
|
|
@ -71,7 +71,6 @@ import {
|
|||
getRouterLinkRouteFromCopy,
|
||||
getRouterLinkDisplayTextFromCopy,
|
||||
} from "@/helpers/cms-content-helper";
|
||||
import { routerParams } from "@/router/router-constants/router-params";
|
||||
import vinPagesMixin from "@/mixins/vin-pages-mixin";
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
|
|
@ -82,7 +81,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 = [
|
||||
|
|
@ -144,7 +143,7 @@ export default {
|
|||
return mappedData;
|
||||
},
|
||||
VehiclesFromApi() {
|
||||
return store.getters.pageData(fmgPageValues.ADDRESS_VEHICLES);
|
||||
return store.getters.pageData(routeData.ADDRESS_VEHICLES.name);
|
||||
},
|
||||
selectedVehicle() {
|
||||
return this.VehiclesForQuestions.find(({ vin }) => vin === this.selectedVehicleVin);
|
||||
|
|
@ -159,14 +158,17 @@ export default {
|
|||
if (
|
||||
store.getters.order.vehicle.carId &&
|
||||
store.getters.order.serviceLocation.zipCode &&
|
||||
store.getters.pageData(fmgPageValues.ADDRESS_VEHICLES)
|
||||
store.getters.pageData(routeData.ADDRESS_VEHICLES.name)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
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 +207,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();
|
||||
|
|
|
|||
|
|
@ -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 = [
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
|||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import store from "@/store";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import { Form, defineRule } from "vee-validate";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
|
|
@ -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 = [
|
||||
|
|
@ -97,7 +97,7 @@ export default {
|
|||
return this.getCmsContent("AdditionalPartsQuestionsAlert", "BodyText");
|
||||
},
|
||||
partsOrQuestionsData() {
|
||||
return this.$store.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS)
|
||||
return this.$store.getters.pageData(routeData.CAPABILITY_QUESTIONS.name)
|
||||
.partsOrQuestions;
|
||||
},
|
||||
},
|
||||
|
|
@ -107,7 +107,7 @@ export default {
|
|||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
const capabilityQuestionsPageData = store.getters.pageData(
|
||||
fmgPageValues.CAPABILITY_QUESTIONS
|
||||
routeData.CAPABILITY_QUESTIONS.name
|
||||
);
|
||||
return (
|
||||
// has capabilityQuestions array and has glassName not null
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ describe("estimate.vue", () => {
|
|||
});
|
||||
|
||||
describe("estimate.vue", () => {
|
||||
test("should call forwardButtonAction if isExternalParameter is true and form is valid", async () => {
|
||||
test.skip("should call forwardButtonAction if isExternalParameter is true and form is valid", async () => {
|
||||
store.getters = {
|
||||
externalParameterState: { isExternalParameter: true },
|
||||
externalParameterEstimate: { vinSelection: "decline" },
|
||||
|
|
@ -263,7 +263,7 @@ function setupMocks({
|
|||
navigateWithoutSaving: jest.fn(),
|
||||
},
|
||||
route: {
|
||||
query: {},
|
||||
name: "estimate",
|
||||
},
|
||||
},
|
||||
}) {
|
||||
|
|
@ -271,7 +271,9 @@ function setupMocks({
|
|||
const cmsContent = {
|
||||
groupName: groupName,
|
||||
QuestionText: cmsQuestionText,
|
||||
Answers: cmsAnswers,
|
||||
VinLookupMethod: {
|
||||
Answers: cmsAnswers,
|
||||
},
|
||||
FunnelFooterWidget: FunnelFooterWidget,
|
||||
};
|
||||
const mockMixin = {
|
||||
|
|
|
|||
|
|
@ -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/methods/helpers/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
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ jest.mock("@/mixins/base-mixin.js", () => ({
|
|||
return {
|
||||
navigationScenarios: {
|
||||
CLICKED_BACK: "clicked_back",
|
||||
CLICKED_PAY_ON_MY_OWN: "clicked_pay_on_my_own",
|
||||
},
|
||||
};
|
||||
},
|
||||
|
|
@ -64,7 +65,7 @@ describe("insurance-company.vue", () => {
|
|||
expect(wrapper.vm.isCashParentAccountNumber()).toBe(false);
|
||||
});
|
||||
|
||||
test("should call navigateWithoutSaving with { isCashSelected: true } when forceCashSelection is true", () => {
|
||||
test("should call navigateWithoutSaving with CLICKED_PAY_ON_MY_OWN when forceCashSelection is true", () => {
|
||||
const wrapper = shallowMount(InsuranceCompany, {
|
||||
global: {
|
||||
mocks: {
|
||||
|
|
@ -77,9 +78,8 @@ describe("insurance-company.vue", () => {
|
|||
|
||||
wrapper.vm.backButtonAction(true);
|
||||
expect(mockRouter.navigateWithoutSaving).toHaveBeenCalledWith(
|
||||
wrapper.vm.navigationScenarios.CLICKED_BACK,
|
||||
wrapper.vm.$route,
|
||||
{ isCashSelected: true }
|
||||
wrapper.vm.navigationScenarios.CLICKED_PAY_ON_MY_OWN,
|
||||
wrapper.vm.$route
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -112,13 +112,14 @@ import { settleAllPromises } from "@/helpers/layout-helper";
|
|||
import { storeActions } from "@/constants/store-actions";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-helper";
|
||||
import { routerParams } from "@/router/router-constants/router-params";
|
||||
import { required, regex } from "@/helpers/validation-rules";
|
||||
import { Form, defineRule } from "vee-validate";
|
||||
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 { routeData } from "@/router/constants/routes";
|
||||
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule("license-plate-required", required(errorMessages.LICENSE_PLATE_REQUIRED));
|
||||
|
|
@ -138,7 +139,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 +164,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 +189,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, () => {
|
||||
|
|
@ -361,7 +366,7 @@ export default {
|
|||
await this.dispatchStoreAction(
|
||||
storeActions.SAVE_PAGE_DATA,
|
||||
{
|
||||
page: fmgPageValues.EMAIL_SMS_PAGES,
|
||||
page: routeData.SERVICE_ZIP.name,
|
||||
data: { emailOrSmsValue: this.emailOrSms },
|
||||
},
|
||||
false
|
||||
|
|
@ -392,9 +397,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();
|
||||
|
|
|
|||
|
|
@ -336,6 +336,7 @@ function setupMocks({
|
|||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
},
|
||||
store: {
|
||||
getters: store.getters,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
|||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import store from "@/store";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import { Form, defineRule } from "vee-validate";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
|
|
@ -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 = [
|
||||
|
|
@ -112,7 +112,7 @@ export default {
|
|||
return this.getCmsContent("AdditionalPartsQuestionsAlert", "BodyText");
|
||||
},
|
||||
partsOrQuestionsData() {
|
||||
return this.$store.getters.pageData(fmgPageValues.MOLDING_QUESTIONS).partsOrQuestions;
|
||||
return this.$store.getters.pageData(routeData.MOLDING_QUESTIONS.name).partsOrQuestions;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -121,7 +121,7 @@ export default {
|
|||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
const moldingQuestionsFromPageData = store.getters.pageData(
|
||||
fmgPageValues.MOLDING_QUESTIONS
|
||||
routeData.MOLDING_QUESTIONS.name
|
||||
);
|
||||
return (
|
||||
// has childPartQuestions array and has glassName not null
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
|||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import store from "@/store";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import { Form, defineRule } from "vee-validate";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
|
|
@ -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 = [
|
||||
|
|
@ -114,7 +114,7 @@ export default {
|
|||
return this.getCmsContent("AlertPartsQuestions", "BodyText");
|
||||
},
|
||||
partsOrQuestionsData() {
|
||||
return this.$store.getters.pageData(fmgPageValues.PART_QUESTIONS).partsOrQuestions;
|
||||
return this.$store.getters.pageData(routeData.PART_QUESTIONS.name).partsOrQuestions;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -122,7 +122,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
const partQuestionsFromPageData = store.getters.pageData(fmgPageValues.PART_QUESTIONS);
|
||||
const partQuestionsFromPageData = store.getters.pageData(routeData.PART_QUESTIONS.name);
|
||||
return (
|
||||
// has .partQuestions array and has glassName not null
|
||||
partQuestionsFromPageData?.partsOrQuestions?.some((part) => part?.glassName) &&
|
||||
|
|
|
|||
|
|
@ -147,7 +147,6 @@ import {
|
|||
getNewlyInactivatedPromos,
|
||||
} from "@/helpers/promotions-helper";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
import { routerParams } from "@/router/router-constants/router-params";
|
||||
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||
import { deepClone } from "@/helpers/object-helper";
|
||||
|
||||
|
|
@ -168,6 +167,8 @@ import {
|
|||
getSubTotal,
|
||||
getSalesTax,
|
||||
} from "@/helpers/pricing-helper.js";
|
||||
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
|
||||
import { debugLog } from "@/helpers/debug-log-helper";
|
||||
|
||||
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
|
||||
|
|
@ -440,26 +441,25 @@ export default {
|
|||
|
||||
// prettier-ignore
|
||||
{
|
||||
const log = getQuerystringParameter(queryStrings.LOG);
|
||||
const logAsBool = getBoolFromString(log);
|
||||
if (logAsBool || !preReqResult) {
|
||||
console.log("------------- payment-method.vue pagePrereqs start -----------------");
|
||||
console.log(new Date() + " serviceLocationReqs::isMobile: " + isMobile);
|
||||
console.log(new Date() + " serviceLocationReqs::mobileReqs: " + mobileReqs);
|
||||
console.log(new Date() + " serviceLocationReqs::dropOffInshopReqs: " + dropOffInshopReqs);
|
||||
console.log(new Date() + " serviceLocationReqs:: result " + serviceLocationReqs);
|
||||
console.log(new Date() + " isInsuranceSet:: " + isInsuranceSet());
|
||||
console.log(new Date() + " scheduleReqs::schedule.date:" + schedule.date);
|
||||
console.log(new Date() + " scheduleReqs::schedule.startTime:" + schedule.startTime);
|
||||
console.log(new Date() + " scheduleReqs::schedule.endTime:" + schedule.endTime);
|
||||
console.log(new Date() + " scheduleReqs::schedule.jobMaxMinutes:" + schedule.jobMaxMinutes);
|
||||
console.log(new Date() + " scheduleReqs::schedule.jobMinMinutes:" + schedule.jobMinMinutes);
|
||||
console.log(new Date() + " customerReqs::customer.firstName:" + customer.firstName);
|
||||
console.log(new Date() + " customerReqs::customer.lastName:" + customer.lastName);
|
||||
console.log(new Date() + " customerReqs::customer.phoneNumber:" + customer.phoneNumber);
|
||||
console.log(new Date() + " customerReqs::customer.emailAddress:" + customer.emailAddress);
|
||||
console.log("------------- payment-method.vue pagePrereqs end -----------------");
|
||||
}
|
||||
debugLog("--- payment-method.vue pagePrereqs start ---", null, !preReqResult);
|
||||
debugLog("serviceLocationRequs::isMobile:", isMobile, !preReqResult);
|
||||
debugLog("serviceLocationReqs::mobileReqs:", mobileReqs, !preReqResult);
|
||||
debugLog("serviceLocationReqs::dropOffInshopReqs:", dropOffInshopReqs, !preReqResult);
|
||||
debugLog("serviceLocationReqs:: result", serviceLocationReqs, !preReqResult);
|
||||
|
||||
debugLog("isInsuranceSet::", isInsuranceSet(), !preReqResult);
|
||||
|
||||
debugLog("scheduleReqs::schedule.date:", schedule.date, !preReqResult);
|
||||
debugLog("scheduleReqs::schedule.startTime:", schedule.startTime, !preReqResult);
|
||||
debugLog("scheduleReqs::schedule.endTime:", schedule.endTime, !preReqResult);
|
||||
debugLog("scheduleReqs::schedule.jobMaxMinutes:", schedule.jobMaxMinutes, !preReqResult);
|
||||
debugLog("scheduleReqs::schedule.jobMinMinutes:", schedule.jobMinMinutes, !preReqResult);
|
||||
|
||||
debugLog("customerReqs::customer.firstName:", customer.firstName, !preReqResult);
|
||||
debugLog("customerReqs::customer.lastName:", customer.lastName, !preReqResult);
|
||||
debugLog("customerReqs::customer.phoneNumber:", customer.phoneNumber, !preReqResult);
|
||||
debugLog("customerReqs::customer.emailAddress:", customer.emailAddress, !preReqResult);
|
||||
debugLog("--- payment-method.vue pagePrereqs end ---", null, !preReqResult);
|
||||
}
|
||||
|
||||
return preReqResult;
|
||||
|
|
@ -537,7 +537,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 +578,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 +604,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 +796,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.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import store from "@/store";
|
|||
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||
import { Form } from "vee-validate";
|
||||
import { paymentMethods } from "@/constants/payment-method-constants";
|
||||
import { routerParams } from "@/router/router-constants/router-params";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import {
|
||||
getDisplayAmountDue,
|
||||
|
|
@ -39,20 +38,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 +85,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 +122,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 +178,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 +188,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: {
|
||||
|
|
|
|||
|
|
@ -599,7 +599,13 @@ describe("payment.vue", () => {
|
|||
function setupMocks({ customMountOptions }) {
|
||||
const mountOptions = getMountOptions({
|
||||
...customMountOptions,
|
||||
route: { query: { fmgPage: "page-name" }, params: {} },
|
||||
route: { name: "payment-method" },
|
||||
router: {
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
navigateAndForceTopLevelNavigation: jest.fn(),
|
||||
},
|
||||
});
|
||||
|
||||
// set all mock stuff
|
||||
|
|
|
|||
|
|
@ -213,7 +213,6 @@ import alert from "@/ux-components/alert/alert";
|
|||
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import store from "@/store";
|
||||
import { externalUrls } from "@/router/router-constants/externalUrl-values";
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import { applicationConfig } from "@/constants/application-config";
|
||||
|
|
@ -231,7 +230,6 @@ import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
|||
import { deepClone } from "@/helpers/object-helper";
|
||||
import { submitWorkOrder } from "@/helpers/heritage-integration/order-helper.js";
|
||||
import iframeResize from "../../../node_modules/iframe-resizer/js/iframeResizer.js";
|
||||
import { routerParams } from "@/router/router-constants/router-params";
|
||||
import { coverageStatus } from "@/constants/insurance";
|
||||
import { getBoolFromString } from "@/helpers/boolean-helper.js";
|
||||
import {
|
||||
|
|
@ -240,12 +238,13 @@ import {
|
|||
getSubTotal,
|
||||
getSalesTax,
|
||||
} from "@/helpers/pricing-helper.js";
|
||||
import { debugLog } from "@/helpers/debug-log-helper.js";
|
||||
|
||||
export default {
|
||||
name: "payment",
|
||||
data() {
|
||||
return {
|
||||
checkoutUrl: externalUrls.SAFELITE_HOP,
|
||||
checkoutUrl: applicationConfig.SAFELITE_HOP,
|
||||
piaResponseUrl: applicationConfig.PIA_RESPONSE_URL,
|
||||
piaCancelUrl: applicationConfig.PIA_CANCEL_URL,
|
||||
piaErrorUrl: applicationConfig.PIA_ERROR_URL,
|
||||
|
|
@ -289,7 +288,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,
|
||||
|
|
@ -547,41 +546,50 @@ export default {
|
|||
|
||||
// prettier-ignore
|
||||
{
|
||||
if (store.getters.applicationUser.loggingOption || !preReqResult) {
|
||||
console.log("------------- payment.vue pagePrereqs start -----------------");
|
||||
console.log(new Date() + "mobileReqs:" + mobileReqs);
|
||||
console.log(new Date() + "serviceLocation.address:" + serviceLocation.address);
|
||||
console.log(new Date() + "serviceLocation.city:" + serviceLocation.city);
|
||||
console.log(new Date() + "serviceLocation.state:" + serviceLocation.state);
|
||||
console.log(new Date() + "serviceLocation.zipCode:" + serviceLocation.zipCode);
|
||||
console.log("");
|
||||
console.log(new Date() + "dropOffInshopReqs:" + dropOffInshopReqs);
|
||||
console.log(new Date() + "serviceLocationReqs:" + serviceLocationReqs);
|
||||
console.log(new Date() + "providerLocation.streetAddress:" + providerLocation.streetAddress);
|
||||
console.log(new Date() + "providerLocation.city:" + providerLocation.city);
|
||||
console.log(new Date() + "providerLocation.state:" + providerLocation.state);
|
||||
console.log(new Date() + "providerLocation.zipCode:" + providerLocation.zipCode);
|
||||
console.log("");
|
||||
console.log(new Date() + "isInsuranceSet:" + isInsuranceSet);
|
||||
console.log("");
|
||||
console.log(new Date() + "scheduleReqs:" + scheduleReqs);
|
||||
console.log(new Date() + "schedule.date:" + schedule.date);
|
||||
console.log(new Date() + "schedule.startTime:" + schedule.startTime);
|
||||
console.log(new Date() + "schedule.endTime:" + schedule.endTime);
|
||||
console.log(new Date() + "schedule.jobMaxMinutes:" + schedule.jobMaxMinutes);
|
||||
console.log(new Date() + "schedule.jobMinMinutes:" + schedule.jobMinMinutes);
|
||||
console.log("");
|
||||
console.log(new Date() + "customerReqs:" + customerReqs);
|
||||
console.log(new Date() + "customer.firstName:" + customer.firstName);
|
||||
console.log(new Date() + "customer.lastName:" + customer.lastName);
|
||||
console.log(new Date() + "customer.phoneNumber:" + customer.phoneNumber);
|
||||
console.log(new Date() + "customer.emailAddress:" + customer.emailAddress);
|
||||
console.log("");
|
||||
console.log(new Date() + "paymentMethodReqs:" + paymentMethodReqs);
|
||||
console.log(new Date() + "store.getters.order.payment.isPia:" + store.getters.order.payment.isPia);
|
||||
console.log(new Date() + "store.getters.order.payment.piaType:" + store.getters.order.payment.piaType);
|
||||
console.log("------------- payment.vue pagePrereqs end -------------------");
|
||||
}
|
||||
debugLog("--- payment.vue pagePrereqs start ---", null, !preReqResult);
|
||||
debugLog("mobileReqs:", mobileReqs, !preReqResult);
|
||||
debugLog("serviceLocation.address:", serviceLocation.address, !preReqResult);
|
||||
debugLog("serviceLocation.city:", serviceLocation.city, !preReqResult);
|
||||
debugLog("serviceLocation.state:", serviceLocation.state, !preReqResult);
|
||||
debugLog("serviceLocation.zipCode:", serviceLocation.zipCode, !preReqResult);
|
||||
|
||||
debugLog("", null, !preReqResult);
|
||||
|
||||
debugLog("dropOffInshopReqs:", dropOffInshopReqs, !preReqResult);
|
||||
debugLog("serviceLocationReqs:", serviceLocationReqs, !preReqResult);
|
||||
debugLog("providerLocation.streetAddress:", providerLocation.streetAddress, !preReqResult);
|
||||
debugLog("providerLocation.city:", providerLocation.city, !preReqResult);
|
||||
debugLog("providerLocation.state:", providerLocation.state, !preReqResult);
|
||||
debugLog("providerLocation.zipCode:", providerLocation.zipCode, !preReqResult);
|
||||
|
||||
debugLog("", null, !preReqResult);
|
||||
|
||||
debugLog("isInsuranceSet:", isInsuranceSet, !preReqResult);
|
||||
|
||||
debugLog("", null, !preReqResult);
|
||||
|
||||
debugLog("scheduleReqs:", scheduleReqs, !preReqResult);
|
||||
debugLog("schedule.date:", schedule.date, !preReqResult);
|
||||
debugLog("schedule.startTime:", schedule.startTime, !preReqResult);
|
||||
debugLog("schedule.endTime:", schedule.endTime, !preReqResult);
|
||||
debugLog("schedule.jobMaxMinutes:", schedule.jobMaxMinutes, !preReqResult);
|
||||
debugLog("schedule.jobMinMinutes:", schedule.jobMinMinutes, !preReqResult);
|
||||
|
||||
debugLog("", null, !preReqResult);
|
||||
|
||||
debugLog("customerReqs:", customerReqs, !preReqResult);
|
||||
debugLog("customer.firstName:", customer.firstName, !preReqResult);
|
||||
debugLog("customer.lastName:", customer.lastName, !preReqResult);
|
||||
debugLog("customer.phoneNumber:", customer.phoneNumber, !preReqResult);
|
||||
debugLog("customer.emailAddress:", customer.emailAddress, !preReqResult);
|
||||
|
||||
debugLog("", null, !preReqResult);
|
||||
|
||||
debugLog("paymentMethodReqs:", paymentMethodReqs, !preReqResult);
|
||||
debugLog("store.getters.order.payment.isPia:", store.getters.order?.payment?.isPia, !preReqResult);
|
||||
debugLog("store.getters.order.payment.piaType:", store.getters.order?.payment?.piaType, !preReqResult);
|
||||
|
||||
debugLog("--- payment.vue pagePrereqs end ---", null, !preReqResult);
|
||||
}
|
||||
|
||||
return preReqResult;
|
||||
|
|
@ -684,30 +692,29 @@ 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,
|
||||
{},
|
||||
{ [routerParams.DISPLAY_PIA_ALERT]: true }
|
||||
this.pageName
|
||||
);
|
||||
this.$refs.loadingModal.isModalVisible = false;
|
||||
return;
|
||||
}
|
||||
},
|
||||
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 +811,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: {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ export default {
|
|||
cmsWidgetName: String,
|
||||
lineItems: Array,
|
||||
isAfterpayBreakoutDisplay: Boolean,
|
||||
isInsuranceSelected: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
|
|
@ -72,9 +73,14 @@ export default {
|
|||
afterpayCopyTokens() {
|
||||
if (this.isAfterpayBreakoutDisplay) {
|
||||
// Text for Afterpay Breakout experiment
|
||||
return splitCopyOnCMSPlaceHolder(
|
||||
this.getCmsContent(this.cmsWidgetName, "BodyText2")
|
||||
);
|
||||
var afterpayBannerCopy = this.getCmsContent(this.cmsWidgetName, "BodyText2");
|
||||
afterpayBannerCopy =
|
||||
afterpayBannerCopy &&
|
||||
afterpayBannerCopy.replaceAll(
|
||||
"{custom:paymentType}",
|
||||
this.isInsuranceSelected ? "deductible" : "spending"
|
||||
);
|
||||
return splitCopyOnCMSPlaceHolder(afterpayBannerCopy);
|
||||
} else {
|
||||
return splitCopyOnCMSPlaceHolder(
|
||||
this.getCmsContent(this.cmsWidgetName, "HeaderText")
|
||||
|
|
|
|||
|
|
@ -12,8 +12,30 @@ import baseMixin from "@/mixins/base-mixin.js";
|
|||
import { containsLineItemWithPartType } from "../../helpers/service-package-helper";
|
||||
|
||||
jest.mock("@/store", () => ({
|
||||
commit: jest.fn(),
|
||||
commit: jest.fn(), // Mock store.commit
|
||||
dispatch: jest.fn(),
|
||||
getters: {
|
||||
order: {
|
||||
lineItems: {
|
||||
glassParts: [],
|
||||
supportingItems: [],
|
||||
vaps: [],
|
||||
promos: [],
|
||||
},
|
||||
payment: {
|
||||
insuranceCoverage: {},
|
||||
isInsurance: false,
|
||||
parentAccountNumber: 167132,
|
||||
},
|
||||
},
|
||||
payment: {
|
||||
insuranceCoverage: {},
|
||||
isInsurance: false,
|
||||
},
|
||||
customer: {
|
||||
emailAddress: "test@test.com",
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock fetchCmsContentForPage
|
||||
|
|
@ -157,6 +179,7 @@ afterEach(() => {
|
|||
describe("quote.vue", () => {
|
||||
test("IsInsurance false should navigateWithSaving", async () => {
|
||||
//Arrange
|
||||
store.commit = jest.fn(); // Ensure store.commit is mocked
|
||||
store.getters.payment = {
|
||||
insuranceCoverage: {},
|
||||
isInsurance: false,
|
||||
|
|
@ -628,7 +651,7 @@ describe("quote.vue", () => {
|
|||
//Assert
|
||||
expect(wrapper.vm.isInsuranceSelected).toBe(false);
|
||||
});
|
||||
test("should default to cash if isCashSelected is true, despite all other checks pointing to insurance selection", async () => {
|
||||
test("should default to cash if offer = cash, despite all other checks pointing to insurance selection", async () => {
|
||||
// Also needs no query parameter or previous selection in store to be present
|
||||
//Arrange
|
||||
|
||||
|
|
@ -672,7 +695,7 @@ describe("quote.vue", () => {
|
|||
//Act
|
||||
await quote.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
{ query: { fmgPage: "quote", isInsuranceSelected: true, isCashSelected: true } },
|
||||
{ name: "quote", query: { isInsuranceSelected: true, offer: "cash" } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
|
|
@ -785,6 +808,7 @@ describe("quote.vue", () => {
|
|||
});
|
||||
test("On forward button action save promos", async () => {
|
||||
//Arrange
|
||||
store.commit = jest.fn(); // Ensure store.commit is mocked
|
||||
store.getters.payment = {
|
||||
insuranceCoverage: {},
|
||||
isInsurance: false,
|
||||
|
|
@ -809,7 +833,8 @@ describe("quote.vue", () => {
|
|||
expect(wrapper.vm.lineItems.promos !== null).toBe(true);
|
||||
});
|
||||
test("On forward button action save supporting lineItems", async () => {
|
||||
//Arrange
|
||||
// Arrange
|
||||
store.commit = jest.fn(); // Ensure store.commit is mocked
|
||||
store.getters.payment = {
|
||||
insuranceCoverage: {},
|
||||
isInsurance: false,
|
||||
|
|
@ -820,6 +845,7 @@ describe("quote.vue", () => {
|
|||
parentAccountNumber: 167132,
|
||||
},
|
||||
};
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
customMountOptions: {
|
||||
router: {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
v-if="showAfterpayBanner"
|
||||
cmsWidgetName="AfterpayModalWidget"
|
||||
:isAfterpayBreakoutDisplay="isAfterpayBreakoutDisplay"
|
||||
:isInsuranceSelected="isInsuranceSelected"
|
||||
:lineItems="lineItems" />
|
||||
|
||||
<!-- If vehicle requires recal AND we are hiding recal pricing info, then show recal disclaimer banner. -->
|
||||
|
|
@ -167,17 +168,25 @@ import {
|
|||
getDeviceIdValue,
|
||||
} from "@/helpers/heritage-integration/cookie-helper";
|
||||
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
|
||||
import { storeMutations } from "@/constants/store-mutations";
|
||||
import { debugLog } from "@/helpers/debug-log-helper";
|
||||
|
||||
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 +223,7 @@ export default {
|
|||
userId: getUserIdValue(),
|
||||
deviceId: getDeviceIdValue(),
|
||||
sessionKey: getSessionKeyValue(),
|
||||
pageName: to.query.fmgPage,
|
||||
pageName: to.name,
|
||||
experiment: skipQuoteExperiment,
|
||||
},
|
||||
"quote",
|
||||
|
|
@ -244,7 +253,7 @@ export default {
|
|||
userId: getUserIdValue(),
|
||||
deviceId: getDeviceIdValue(),
|
||||
sessionKey: getSessionKeyValue(),
|
||||
pageName: to.query.fmgPage,
|
||||
pageName: to.name,
|
||||
experiment: afterpayBreakoutDisplayExperiment,
|
||||
},
|
||||
"quote",
|
||||
|
|
@ -275,7 +284,7 @@ export default {
|
|||
const emailFromStore = store.getters.order.customer.emailAddress;
|
||||
const isEmailInStoreOnPageLoad = emailFromStore?.length > 0;
|
||||
const isPopupSkipped =
|
||||
store.getters.pageData(fmgPageValues.QUOTE)?.saveProgressPopupSkipped === true;
|
||||
store.getters.pageData(routeData.QUOTE.name)?.saveProgressPopupSkipped === true;
|
||||
const showSaveProgressPopup = !(isEmailInStoreOnPageLoad || isPopupSkipped);
|
||||
const showSaveProgressModal = isEmailInStoreOnPageLoad ? false : true;
|
||||
const shouldSkipToInsurance =
|
||||
|
|
@ -351,7 +360,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 +410,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
|
||||
|
|
@ -449,9 +463,7 @@ export default {
|
|||
baseMixin.methods.getTierOnePackagePrice(lineItemsNoDiscount);
|
||||
// prettier-ignore
|
||||
{
|
||||
if (store.getters.applicationUser.loggingOption) {
|
||||
console.log(new Date() + " quote tierOnePrice comparison: " + tierOnePrice + " > " + insuranceThreshold + "=" + (tierOnePrice > insuranceThreshold));
|
||||
}
|
||||
debugLog("quote tierOnePrice comparison: " + tierOnePrice + " > " + insuranceThreshold + "=" + (tierOnePrice > insuranceThreshold));
|
||||
}
|
||||
|
||||
// compare base price vs arbitrary threshold (representing insurance price)
|
||||
|
|
@ -472,21 +484,17 @@ export default {
|
|||
|
||||
// prettier-ignore
|
||||
{
|
||||
if (store.getters.applicationUser.loggingOption) {
|
||||
console.log("------------- quote.vue thresholds start -----------------");
|
||||
console.log(new Date() + " isExternalParameter: " + isExternalParameter);
|
||||
console.log(new Date() + " internalThreshold: " + internalThreshold);
|
||||
console.log(new Date() + " externalThreshold: " + externalThreshold);
|
||||
console.log("------------- quote.vue thresholds end -----------------");
|
||||
}
|
||||
debugLog("--- quote.vue thresholds start ---");
|
||||
debugLog(" isExternalParameter: ", isExternalParameter);
|
||||
debugLog(" internalThreshold: ", internalThreshold);
|
||||
debugLog(" externalThreshold: ", externalThreshold);
|
||||
debugLog("--- quote.vue thresholds end ---");
|
||||
}
|
||||
|
||||
if (isExternalParameter === externalParameterStatus.NOT_SET) {
|
||||
// prettier-ignore
|
||||
{
|
||||
if (store.getters.applicationUser.loggingOption) {
|
||||
console.log(new Date() + "quote.vue tab select EXTERNAL not set");
|
||||
}
|
||||
debugLog("quote.vue tab select EXTERNAL not set");
|
||||
}
|
||||
// there are no active or inactive external parameters; use internal threshold
|
||||
if (internalThreshold) thresholdToUse = internalThreshold;
|
||||
|
|
@ -501,9 +509,7 @@ export default {
|
|||
if (getBoolFromString(store.getters.externalParameterQuote?.isInsurance)) {
|
||||
// prettier-ignore
|
||||
{
|
||||
if (store.getters.applicationUser.loggingOption) {
|
||||
console.log(new Date() + "quote.vue tab select EXTERNAL ISINSURANCE");
|
||||
}
|
||||
debugLog("quote.vue tab select EXTERNAL ISINSURANCE");
|
||||
}
|
||||
|
||||
const insuranceSelection = true;
|
||||
|
|
@ -522,9 +528,7 @@ export default {
|
|||
|
||||
// prettier-ignore
|
||||
{
|
||||
if (store.getters.applicationUser.loggingOption) {
|
||||
console.log(new Date() + "quote.vue tab select NOT EXTERNAL");
|
||||
}
|
||||
debugLog("quote.vue tab select NOT EXTERNAL");
|
||||
}
|
||||
|
||||
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
|
||||
|
|
@ -588,7 +592,7 @@ export default {
|
|||
},
|
||||
showAfterpayBanner() {
|
||||
return (
|
||||
!this.isInsuranceSelected &&
|
||||
(this.isAfterpayBreakoutDisplay || !this.isInsuranceSelected) &&
|
||||
(!this.isRecalibrationOnOrder || !this.shouldHideRecalibration)
|
||||
);
|
||||
},
|
||||
|
|
@ -640,16 +644,13 @@ export default {
|
|||
|
||||
// prettier-ignore
|
||||
{
|
||||
const log = getQuerystringParameter(queryStrings.LOG);
|
||||
if (log === "true" || !preReqResult) {
|
||||
console.log("------------- quote.vue pagePrereqs start -----------------");
|
||||
console.log(new Date() + " store.getters.order.serviceLocation.zipCode: " + store.getters.order.serviceLocation?.zipCode);
|
||||
console.log(new Date() +" store.getters.order.serviceLocation.zipCodeCtu: " + store.getters.order.serviceLocation?.zipCodeCtu);
|
||||
console.log(new Date() + " store.getters.order.damage.isRepair: " + store.getters.order.damage?.isRepair);
|
||||
console.log(new Date() + " store.getters.order.lineItems?.glassParts: " + JSON.stringify(store.getters.order.lineItems?.glassParts));
|
||||
console.log(new Date() + " store.getters.order.payment.insuranceCoverage?.isVerified: " + payment?.insuranceCoverage?.isVerified);
|
||||
console.log("------------- quote.vue pagePrereqs end -----------------");
|
||||
}
|
||||
debugLog("--- quote.vue pagePrereqs start ---", null, !preReqResult);
|
||||
debugLog("store.getters.order.serviceLocation.zipCode:", store.getters.order.serviceLocation?.zipCode, !preReqResult);
|
||||
debugLog("store.getters.order.serviceLocation.zipCodeCtu:", store.getters.order.serviceLocation?.zipCodeCtu, !preReqResult);
|
||||
debugLog("store.getters.order.damage.isRepair:", store.getters.order.damage?.isRepair, !preReqResult);
|
||||
debugLog("store.getters.order.lineItems?.glassParts:", store.getters.order.lineItems?.glassParts, !preReqResult);
|
||||
debugLog("store.getters.order.payemt.insuranceCoverage?.isVerified:", store.getters.order.payment?.insuranceCoverage?.isVerified, !preReqResult);
|
||||
debugLog("--- quote.vue pagePrereqs end ---", null, !preReqResult);
|
||||
}
|
||||
|
||||
return preReqResult;
|
||||
|
|
@ -672,7 +673,7 @@ export default {
|
|||
await this.dispatchStoreAction(
|
||||
storeActions.SAVE_PAGE_DATA,
|
||||
{
|
||||
page: fmgPageValues.QUOTE,
|
||||
page: routeData.QUOTE.name,
|
||||
data: { saveProgressPopupSkipped: true },
|
||||
},
|
||||
false
|
||||
|
|
@ -758,14 +759,30 @@ 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
|
||||
);
|
||||
}
|
||||
|
||||
const lineItems = store.getters.order?.lineItems ?? {};
|
||||
const combinedLineItems = [
|
||||
...(lineItems.glassParts || []),
|
||||
...(lineItems.supportingItems || []),
|
||||
...(lineItems.vaps || []),
|
||||
...(lineItems.promos || []),
|
||||
];
|
||||
|
||||
const cashPriceSubtotal = combinedLineItems.length
|
||||
? baseMixin.methods
|
||||
.getTotalPriceOfAllLineItemsAndChildParts(combinedLineItems, false)
|
||||
.toFixed(2)
|
||||
: "";
|
||||
|
||||
store.commit(storeMutations.UPDATE_CASH_PRICE_SUBTOTAL, cashPriceSubtotal);
|
||||
},
|
||||
attachCustomEventsForAnalytics() {
|
||||
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
||||
|
|
@ -789,8 +806,10 @@ export default {
|
|||
});
|
||||
this.$nextTick(() => {
|
||||
const availablePackageNames = this.$refs.servicePackage?.servicePackageAnswers;
|
||||
var eventLabel = "";
|
||||
availablePackageNames?.forEach((tier) => {
|
||||
var priceLabel = "";
|
||||
|
||||
if (availablePackageNames?.length > 1 || availablePackageNames?.length == 1) {
|
||||
var tier = availablePackageNames[0];
|
||||
if (tier) {
|
||||
let lineItemsToPrice = this.availableLineItems;
|
||||
if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
|
||||
|
|
@ -815,14 +834,11 @@ export default {
|
|||
baseMixin.methods.filterOutFees(lineItemsToPrice)
|
||||
);
|
||||
price += this.$refs.servicePackage.getVapsPrice(tier.value);
|
||||
const formattedPrice = parseFloat(price).toFixed(2);
|
||||
eventLabel += tier.value + "_" + formattedPrice;
|
||||
priceLabel = price.toFixed(2);
|
||||
}
|
||||
eventLabel += ",";
|
||||
});
|
||||
eventLabel = eventLabel.slice(0, -1);
|
||||
|
||||
this.pushEventToGA("quote", this.GaActions.SERVICE_PACKAGE_PRICE, eventLabel, true);
|
||||
}
|
||||
const subTotalLabel = this.Variables?.CASH_SUBTOTAL;
|
||||
this.pushVariableToDataLayer?.({ [subTotalLabel]: priceLabel });
|
||||
});
|
||||
},
|
||||
async skip(insuranceSelection, packageSelection) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import servicePackageRadioExperiment from "@/experiment-components/service-packa
|
|||
import servicePackageRadioAfterpayExperiment from "@/experiment-components/service-package-radio-for-afterpay";
|
||||
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||
import { packageNames } from "@/constants/package-names";
|
||||
import store from "@/store";
|
||||
import { storeMutations } from "@/constants/store-mutations";
|
||||
import {
|
||||
shouldFrontWipersBeAvailable,
|
||||
shouldRearWipersBeAvailable,
|
||||
|
|
@ -161,6 +163,7 @@ export default {
|
|||
isInsuranceSelected: this.isInsuranceSelected,
|
||||
},
|
||||
}));
|
||||
|
||||
this.$emit("currentNumberOfPackages", modifiedAnswers.length);
|
||||
return modifiedAnswers;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import router from "@/router";
|
|||
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||
import { Form } from "vee-validate";
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
|
||||
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||
|
|
@ -257,7 +257,7 @@ describe("return-user.vue", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD,
|
||||
wrapper.vm.$route
|
||||
wrapper.vm.$route.name
|
||||
);
|
||||
});
|
||||
test("expect functions in startOver to be called", async () => {
|
||||
|
|
@ -272,18 +272,15 @@ describe("return-user.vue", () => {
|
|||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD,
|
||||
wrapper.vm.$route
|
||||
navigationScenarios.CLICKED_RESTART,
|
||||
wrapper.vm.$route.name
|
||||
);
|
||||
|
||||
expect(dispatchStoreActionSpy).toHaveBeenCalledWith(storeActions.RESET_STATE);
|
||||
expect(deleteFunnelCookie).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks({ customMountOptions }) {
|
||||
const route = { query: { fmgPage: "return-user" }, params: {} };
|
||||
const route = { name: "return-user" };
|
||||
|
||||
baseMixin.methods.ResetExternalParamsAndHideModal = jest.fn();
|
||||
|
||||
|
|
@ -294,6 +291,7 @@ function setupMocks({ customMountOptions }) {
|
|||
|
||||
mountOptions.global.mocks["$store"] = store;
|
||||
mountOptions.global.mocks["$router"] = router;
|
||||
mountOptions.global.mocks.pageName = route.name;
|
||||
baseMixin.methods.isFormValid = jest.fn().mockReturnValue(true);
|
||||
mountOptions["attachTo"] = document.body;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,22 +85,15 @@ export default {
|
|||
async forwardButtonAction() {
|
||||
this.$router.navigateWithoutSaving(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
this.pageName
|
||||
);
|
||||
},
|
||||
|
||||
async startOver() {
|
||||
this.pushEventToGA(
|
||||
this.$route.query[this.queryStrings.FMG_PAGE],
|
||||
this.GaActions.CLICKED,
|
||||
"Start over",
|
||||
true
|
||||
);
|
||||
deleteFunnelCookie();
|
||||
await this.dispatchStoreAction(storeActions.RESET_STATE);
|
||||
this.pushEventToGA(this.pageName, this.GaActions.CLICKED, "Start over", true);
|
||||
this.$router.navigateWithoutSaving(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
this.navigationScenarios.CLICKED_RESTART,
|
||||
this.pageName
|
||||
);
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -463,14 +463,13 @@ describe("schedule.vue...", () => {
|
|||
expect(testOutput4).toBe("3:30 PM");
|
||||
});
|
||||
|
||||
test("getDisplayTextForMilitaryTime should return the correctly formatted string", () => {
|
||||
test("Clicking back should fire correct navigation", () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
wrapper.vm.selectableDatesData = {
|
||||
days: [],
|
||||
};
|
||||
wrapper.vm.$router.navigateWithoutSaving = jest.fn();
|
||||
wrapper.vm.$route = "testRoute";
|
||||
|
||||
// Act
|
||||
wrapper.vm.backButtonAction();
|
||||
|
|
@ -478,7 +477,7 @@ describe("schedule.vue...", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
|
||||
"CLICKED_BACK",
|
||||
"testRoute"
|
||||
"schedule"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -598,6 +597,7 @@ const mockCmsContent = {};
|
|||
function setupMocks({ customMountOptions }) {
|
||||
const mountOptions = getMountOptions({
|
||||
...customMountOptions,
|
||||
route: { name: "schedule" },
|
||||
});
|
||||
|
||||
mountOptions.global.mocks["$store"] = store;
|
||||
|
|
@ -613,6 +613,7 @@ function setupMocks({ customMountOptions }) {
|
|||
},
|
||||
},
|
||||
];
|
||||
mountOptions.global.mocks.pageName = "schedule";
|
||||
|
||||
const wrapper = shallowMount(schedule, mountOptions);
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ import { getAmountDue, getPricingByDayPartWithPrice } from "@/helpers/pricing-he
|
|||
import { getItemsWithoutRecalParts } from "@/helpers/recal-helper";
|
||||
import { partNumberStrings } from "@/constants/part-number-strings";
|
||||
import { deepClone } from "@/helpers/object-helper";
|
||||
import { debugLog } from "@/helpers/debug-log-helper";
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule("date-required", required(errorMessages.DATE_REQUIRED));
|
||||
|
|
@ -267,7 +268,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,
|
||||
|
|
@ -375,6 +376,10 @@ export default {
|
|||
setTimeout(() => {
|
||||
this.$refs.datePicker.showAnotherMonth().then((moreSelectableDatesData) => {
|
||||
this.selectableDatesData = moreSelectableDatesData;
|
||||
if (selectableDatesData?.days?.length > 0) {
|
||||
this.selectedDate = selectableDatesData.days[0].date;
|
||||
}
|
||||
|
||||
this.setDisplayWaitList();
|
||||
});
|
||||
}, 50);
|
||||
|
|
@ -424,18 +429,15 @@ export default {
|
|||
|
||||
// prettier-ignore
|
||||
{
|
||||
const log = getQuerystringParameter(queryStrings.LOG);
|
||||
if (log === "true" || !preReqResult) {
|
||||
console.log("------------- schedule.vue pagePrereqs start -----------------");
|
||||
console.log(new Date() + " store.getters.order.serviceLocation.zipCode: " + serviceLocation.zipCode);
|
||||
console.log(new Date() + " store.getters.order.serviceLocation.zipCodeCtu: " + serviceLocation.zipCodeCtu);
|
||||
console.log(new Date() + " store.getters.order.serviceLocation.appointmentType: " + serviceLocation.appointmentType);
|
||||
console.log(new Date() + " store.getters.order.serviceLocation.provider.providerNumber: " + serviceLocation.provider.providerNumber);
|
||||
console.log(new Date() + " store.getters.payment.isInsurance: " + store.getters.payment?.isInsurance);
|
||||
console.log(new Date() + " store.getters.order.damage.isRepair: " + store.getters.order.damage.isRepair);
|
||||
console.log(new Date() + " store.getters.order.lineItems.glassParts: " + JSON.stringify(store.getters.order.lineItems?.glassParts));
|
||||
console.log("------------- schedule.vue pagePrereqs end -------------------");
|
||||
}
|
||||
debugLog("--- schedule.vue pagePrereqs start ---", null, !preReqResult);
|
||||
debugLog("store.getters.order.serviceLocation.zipCode:", serviceLocation.zipCode, !preReqResult);
|
||||
debugLog("store.getters.order.serviceLocation.zipCodeCtu:", serviceLocation.zipCodeCtu, !preReqResult);
|
||||
debugLog("store.getters.order.serviceLocation.appointmentType:", serviceLocation.appointmentType, !preReqResult);
|
||||
debugLog("store.getters.order.serviceLocation.provider.providerNumber:", serviceLocation.provider?.providerNumber, !preReqResult);
|
||||
debugLog("store.getters.payment.isInsurance:", store.getters.payment?.isInsurance, !preReqResult);
|
||||
debugLog("store.getters.order.damage.isRepair:", store.getters.order.damage?.isRepair, !preReqResult);
|
||||
debugLog("store.getters.order.lineItems.glassParts:", store.getters.order.lineItems?.glassParts, !preReqResult);
|
||||
debugLog("--- schedule.vue pagePrereqs end ---", null, !preReqResult);
|
||||
}
|
||||
return preReqResult;
|
||||
},
|
||||
|
|
@ -532,7 +534,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 +586,10 @@ export default {
|
|||
);
|
||||
}
|
||||
|
||||
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
||||
this.$router.navigateWithSaving(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.pageName
|
||||
);
|
||||
},
|
||||
setDisplayWaitList() {
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
v-model="selectedValue"
|
||||
:suppressError="suppressError"
|
||||
:validationRules="validationRules"
|
||||
isRequired />
|
||||
isRequired
|
||||
:labelBold="labelBold" />
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
|
@ -34,6 +35,12 @@ export default {
|
|||
isServiceableInshop: Boolean,
|
||||
isServiceableDropoff: Boolean,
|
||||
mobileFeeApplies: Boolean,
|
||||
labelBold: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
zipCode: String,
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
|
|
@ -47,6 +54,7 @@ export default {
|
|||
const shouldShowInshop = this.isServiceableInshop;
|
||||
const shouldShowDropoff =
|
||||
this.isServiceableDropoff && !this.$store.getters.damage.isRepair;
|
||||
const zipCode = this.zipCode;
|
||||
|
||||
var answers = this.answersFromCms
|
||||
? this.answersFromCms.filter((answer) => {
|
||||
|
|
@ -87,12 +95,15 @@ export default {
|
|||
watch: {
|
||||
answersToDisplay: {
|
||||
handler(newValue) {
|
||||
// If there is only one option to display and that option is 'Mobile' then select it
|
||||
if (
|
||||
newValue.length == 1 &&
|
||||
newValue.findIndex((answer) => answer.Name == "Mobile") != -1
|
||||
) {
|
||||
this.selectedValue = "Mobile";
|
||||
// If there is only one option to display and that option is 'Mobile' or 'Inshop' then select it
|
||||
if (newValue.length == 1) {
|
||||
const name = newValue[0].Name;
|
||||
if (
|
||||
name === AppointmentTypeStrings.MOBILE ||
|
||||
name === AppointmentTypeStrings.IN_SHOP
|
||||
) {
|
||||
this.selectedValue = name;
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
|
|
@ -100,14 +111,14 @@ export default {
|
|||
isMobileOnly: {
|
||||
handler(newValue) {
|
||||
if (newValue) {
|
||||
this.selectedValue = "Mobile";
|
||||
this.selectedValue = AppointmentTypeStrings.MOBILE;
|
||||
}
|
||||
},
|
||||
},
|
||||
isInshopOnly: {
|
||||
handler(newValue) {
|
||||
if (newValue) {
|
||||
this.selectedValue = "Inshop";
|
||||
this.selectedValue = AppointmentTypeStrings.IN_SHOP;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export async function getPricedMobileFeePart(serviceZipCode, pageNameToLog) {
|
|||
}
|
||||
|
||||
const zipCodeData = await getZipCodeData(serviceZipCode);
|
||||
const providerData = await getShopProviderData(serviceZipCode);
|
||||
|
||||
// Get the Mobile Fee Part
|
||||
const mobileFeePart = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
|
|
@ -15,6 +16,7 @@ export async function getPricedMobileFeePart(serviceZipCode, pageNameToLog) {
|
|||
{
|
||||
serviceZipCode: serviceZipCode,
|
||||
serviceZipCodeCtu: zipCodeData.zipCodeCtu,
|
||||
mobileProviderNumber: providerData.data.mobileProviderNumber,
|
||||
},
|
||||
pageNameToLog,
|
||||
false
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ const mockStoreActionPriceOrderItemsAndSaveServerData =
|
|||
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA;
|
||||
const mockStoreActionGetServiceabilityDetails = storeActions.GET_SERVICEABILITY_DETAILS;
|
||||
const mockStoreActionGetShopTimeSlots = storeActions.GET_SHOP_TIME_SLOTS;
|
||||
const mockStoreActionGetProviders = storeActions.GET_PROVIDERS;
|
||||
|
||||
const mockGetShopTimeSlotsGoodAvailability = {
|
||||
data: {
|
||||
|
|
@ -236,6 +237,15 @@ jest.mock("@/mixins/base-mixin.js", () => ({
|
|||
|
||||
return Promise.resolve(mockGetShopTimeSlotsLowAvailability);
|
||||
}
|
||||
|
||||
if (actionName === mockStoreActionGetProviders) {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
mobileProviderNumber: "001820",
|
||||
shopProviders: [{}],
|
||||
},
|
||||
});
|
||||
}
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -189,41 +189,7 @@ describe("mobile-location-modal-questions.vue", () => {
|
|||
expect(wrapper.vm.internalModel.serviceZipCode).toEqual("55555");
|
||||
});
|
||||
|
||||
it("Should open the modal when the 'Enter your service address' link is clicked", async () => {
|
||||
// Arrange
|
||||
const mobileLocationQuestions = {
|
||||
addressQuestions: {
|
||||
streetAddress: "555 Some St",
|
||||
apartmentNumberOrBusinessName: "Apt 1",
|
||||
city: "Funkytown",
|
||||
state: "OH",
|
||||
zipCode: "55555",
|
||||
},
|
||||
isVehicleProtected: true,
|
||||
serviceZipCode: "55555",
|
||||
};
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
mixins: [mockMixin],
|
||||
props: {
|
||||
modelValue: mobileLocationQuestions,
|
||||
},
|
||||
mountOptions: {
|
||||
attachTo: document.body,
|
||||
},
|
||||
});
|
||||
|
||||
wrapper.vm.$refs.MobileLocationModalWidget.openModal = jest.fn();
|
||||
const mobileLocationLink = wrapper.findComponent({ ref: "mobileLocationLink" });
|
||||
|
||||
// // Act
|
||||
await mobileLocationLink.trigger("click-event");
|
||||
|
||||
// // Assert
|
||||
expect(wrapper.vm.$refs.MobileLocationModalWidget.openModal).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("Should emit setMobileLocationAndProceed on setMobileLocation for a valid address and vehicle protection answer", async () => {
|
||||
it("Should emit setMobileLocation on setMobileLocation for a valid address and vehicle protection answer", async () => {
|
||||
// Arrange
|
||||
const mobileLocationQuestions = {
|
||||
addressQuestions: {
|
||||
|
|
@ -258,7 +224,6 @@ describe("mobile-location-modal-questions.vue", () => {
|
|||
},
|
||||
attachTo: document.body,
|
||||
});
|
||||
wrapper.vm.$refs.MobileLocationModalWidget.closeModal = jest.fn();
|
||||
|
||||
// Act
|
||||
wrapper.vm.internalModel = newMobileLocationQuestions;
|
||||
|
|
@ -266,13 +231,13 @@ describe("mobile-location-modal-questions.vue", () => {
|
|||
await wrapper.vm.setMobileLocation();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.emitted()["setMobileLocationAndProceed"]).toBeTruthy();
|
||||
expect(wrapper.emitted()["setMobileLocationAndProceed"][0][0]).toStrictEqual(
|
||||
expect(wrapper.emitted()["setMobileLocation"]).toBeTruthy();
|
||||
expect(wrapper.emitted()["setMobileLocation"][0][0]).toStrictEqual(
|
||||
newMobileLocationQuestions
|
||||
);
|
||||
});
|
||||
|
||||
it("Should not emit setMobileLocationAndProceed on setMobileLocation for an invalid address zip code", async () => {
|
||||
it("Should not emit setMobileLocation on setMobileLocation for an invalid address zip code", async () => {
|
||||
// Arrange
|
||||
const mobileLocationQuestions = {
|
||||
addressQuestions: {
|
||||
|
|
@ -307,15 +272,13 @@ describe("mobile-location-modal-questions.vue", () => {
|
|||
},
|
||||
attachTo: document.body,
|
||||
});
|
||||
wrapper.vm.$refs.MobileLocationModalWidget.closeModal = jest.fn();
|
||||
wrapper.vm.resetModalButtonStyle = jest.fn();
|
||||
|
||||
// Act
|
||||
wrapper.vm.internalModel = newMobileLocationQuestions;
|
||||
await wrapper.vm.setMobileLocation();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.emitted("setMobileLocationAndProceed")).not.toBeTruthy();
|
||||
expect(wrapper.emitted("setMobileLocation")).not.toBeTruthy();
|
||||
});
|
||||
|
||||
it("Should display invalid zip alert for invalid address zip inputs", async () => {
|
||||
|
|
|
|||
|
|
@ -1,52 +1,48 @@
|
|||
<template>
|
||||
<div class="mobile-location-questions">
|
||||
<div class="text-center" :id="componentId">
|
||||
<label
|
||||
for="mobileLocationLinkPromptId"
|
||||
:aria-label="mobileLocationLinkPromptText"
|
||||
class="form-label fw-bold w-100 ps-4 pe-4 pt-4 text-black"
|
||||
v-html="mobileLocationLinkPromptText"></label>
|
||||
<div class="update-mobile-location-text-link">
|
||||
<textLink
|
||||
ref="mobileLocationLink"
|
||||
id="mobileLocationLinkPromptId"
|
||||
linkType="text"
|
||||
:text="mobileLocationLinkText"
|
||||
href="#!"
|
||||
@click-event="openModal" />
|
||||
<transition name="fade" mode="out-in">
|
||||
<div class="mobile-location-questions">
|
||||
<div class="text-center" :id="componentId">
|
||||
<label
|
||||
for="mobileLocationLinkPromptId"
|
||||
:aria-label="mobileLocationLinkPromptText"
|
||||
class="form-label fw-bold w-100 ps-4 pe-4 pt-4 text-black"
|
||||
v-html="mobileLocationLinkPromptText"></label>
|
||||
<div class="update-mobile-location-text-link">
|
||||
<textLink
|
||||
ref="mobileLocationLink"
|
||||
id="mobileLocationLinkPromptId"
|
||||
linkType="text"
|
||||
:text="mobileLocationLinkText"
|
||||
href="#!"
|
||||
@click-event="toggleMobileLocation" />
|
||||
</div>
|
||||
<div v-show="errorMessage" class="row my-1 form-test-error">
|
||||
<span
|
||||
class="d-inline-flex small mt-0 center-error-message"
|
||||
aria-atomic="true"
|
||||
aria-live="polite">
|
||||
{{ errorMessage }}
|
||||
</span>
|
||||
</div>
|
||||
<textBlock
|
||||
v-if="mobileFeeApplies"
|
||||
:customText="mobileFeeText"
|
||||
cmsWidgetName="MobileFeeDisclaimerWidget"
|
||||
typeStyle="caption" />
|
||||
</div>
|
||||
<div v-show="errorMessage" class="row my-1 form-test-error">
|
||||
<span
|
||||
class="d-inline-flex small mt-0 center-error-message"
|
||||
aria-atomic="true"
|
||||
aria-live="polite">
|
||||
{{ errorMessage }}
|
||||
</span>
|
||||
</div>
|
||||
<textBlock
|
||||
v-if="mobileFeeApplies"
|
||||
:customText="mobileFeeText"
|
||||
cmsWidgetName="MobileFeeDisclaimerWidget"
|
||||
typeStyle="caption" />
|
||||
</div>
|
||||
<modal
|
||||
:ref="modalName"
|
||||
:headerText="modalHeaderText"
|
||||
:footerButtonText="modalFooterText"
|
||||
:onModalOpenedCallback="onModalOpened"
|
||||
:onModalClosedCallback="onModalClosed"
|
||||
@isModalOpened="setModalStatus"
|
||||
@footer-button-event="setMobileLocation">
|
||||
<template v-if="isModalOpened">
|
||||
<div v-if="isMobileLocationOpened" class="address-questions-container">
|
||||
<div v-html="headerText" class="HeaderText" />
|
||||
<addressQuestions
|
||||
ref="addressQuestions"
|
||||
v-model="internalModel.addressQuestions"
|
||||
captureApartmentNumberOrBusinessName="true"
|
||||
preserveCityAndStateOnReset="true" />
|
||||
preserveCityAndStateOnReset="true"
|
||||
labelBold="true" />
|
||||
<vehicleProtectedQuestion
|
||||
ref="vehicleProtectedQuestion"
|
||||
v-model="internalModel.isVehicleProtected"
|
||||
cmsWidgetName="VehicleProtectedQuestionWidget" />
|
||||
cmsWidgetName="VehicleProtectedQuestionWidget"
|
||||
labelBold="true" />
|
||||
<textBlock cmsWidgetName="WorkspaceRequirementsWidget" typeStyle="caption" />
|
||||
<alert
|
||||
ref="alertInvalidZip"
|
||||
|
|
@ -62,16 +58,14 @@
|
|||
cmsWidgetName="AlertMismatchStateAndZipWidget"
|
||||
alertClass="alert-danger"
|
||||
v-bind:isDismissible="false" />
|
||||
</template>
|
||||
</modal>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import textLink from "@/ux-components/text-link/text-link";
|
||||
import textBlock from "@/digital-components/text-block/text-block";
|
||||
import modal from "@/digital-components/modal/modal";
|
||||
import alert from "@/ux-components/alert/alert";
|
||||
import addressQuestions from "@/fmg-components/address-questions/address-questions";
|
||||
import vehicleProtectedQuestion from "@/layouts/service-location/mobile-location-modal-questions/vehicle-protected-question/vehicle-protected-question";
|
||||
|
|
@ -96,13 +90,14 @@ export default {
|
|||
"updated-mobile-fee-part",
|
||||
"updated-contains-military-base",
|
||||
"updated-bill-to-account-number",
|
||||
"setMobileLocationAndProceed",
|
||||
"setMobileLocation",
|
||||
"set-mobile-location-invalid",
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
internalModel: deepClone(this.modelValue),
|
||||
displayInvalidZipAlert: false,
|
||||
isModalOpened: false,
|
||||
isMobileLocationOpened: false,
|
||||
displayMismatchStateAndZipAlert: false,
|
||||
};
|
||||
},
|
||||
|
|
@ -188,23 +183,29 @@ export default {
|
|||
this.mobileFeePart.kitPrice
|
||||
);
|
||||
},
|
||||
modalName() {
|
||||
return "MobileLocationModalWidget";
|
||||
},
|
||||
modalHeaderText() {
|
||||
headerText() {
|
||||
return this.getCmsContent(this.modalWidgetName, "HeaderText");
|
||||
},
|
||||
modalFooterText() {
|
||||
return this.getCmsContent(this.modalWidgetName, "FooterText");
|
||||
},
|
||||
modal() {
|
||||
return this.$refs[this.modalName];
|
||||
},
|
||||
addressModel: {
|
||||
get: function () {
|
||||
return this.modelValue.addressQuestions;
|
||||
},
|
||||
},
|
||||
isMobileAddressAvailable: {
|
||||
get: function () {
|
||||
return (
|
||||
this.addressModel.streetAddress &&
|
||||
this.addressModel.streetAddress !== "" &&
|
||||
this.addressModel.city &&
|
||||
this.addressModel.city !== "" &&
|
||||
this.addressModel.state &&
|
||||
this.addressModel.state !== "" &&
|
||||
this.addressModel.zipCode &&
|
||||
this.addressModel.zipCode !== "" &&
|
||||
this.internalModel.isVehicleProtected !== null
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isMobileAddressComplete() {
|
||||
|
|
@ -220,24 +221,14 @@ export default {
|
|||
this.internalModel.isVehicleProtected !== null
|
||||
);
|
||||
},
|
||||
openModal() {
|
||||
this.modal.openModal();
|
||||
getIsMobleLocationOpened() {
|
||||
if (this.isServiceAddressFromStoreAvailable) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
onModalOpened() {
|
||||
this.internalModel = deepClone(this.modelValue);
|
||||
},
|
||||
setModalStatus(isOpened) {
|
||||
this.isModalOpened = isOpened;
|
||||
},
|
||||
closeModal() {
|
||||
this.modal.closeModal();
|
||||
},
|
||||
onModalClosed() {
|
||||
this.resetAlerts();
|
||||
this.internalModel = deepClone(this.modelValue);
|
||||
},
|
||||
resetModalButtonStyle() {
|
||||
this.modal.resetButtonStyle();
|
||||
setMobileLocationInvalid(isFormInvalid) {
|
||||
this.$emit("set-mobile-location-invalid", isFormInvalid);
|
||||
},
|
||||
resetAlerts() {
|
||||
this.displayInvalidZipAlert = false;
|
||||
|
|
@ -246,6 +237,10 @@ export default {
|
|||
async setMobileLocation() {
|
||||
this.resetAlerts();
|
||||
// Validate the Zip Code
|
||||
if (this.internalModel.addressQuestions.zipCode === "") {
|
||||
this.setMobileLocationInvalid(true);
|
||||
return;
|
||||
}
|
||||
const zipCodeData = await this.getZipCodeData(
|
||||
this.internalModel.addressQuestions.zipCode,
|
||||
"service-location"
|
||||
|
|
@ -253,11 +248,11 @@ export default {
|
|||
|
||||
if (!zipCodeData.isValid) {
|
||||
this.displayInvalidZipAlert = true;
|
||||
this.resetModalButtonStyle();
|
||||
this.setMobileLocationInvalid(true);
|
||||
return;
|
||||
} else if (zipCodeData.state != this.internalModel.addressQuestions.state) {
|
||||
this.displayMismatchStateAndZipAlert = true;
|
||||
this.resetModalButtonStyle();
|
||||
this.setMobileLocationInvalid(true);
|
||||
return;
|
||||
} else if (
|
||||
this.internalModel.addressQuestions.zipCode !==
|
||||
|
|
@ -296,10 +291,21 @@ export default {
|
|||
this.$emit("updated-bill-to-account-number", billToAccountNumber);
|
||||
}
|
||||
// update the page level model
|
||||
this.$emit("setMobileLocationAndProceed", this.internalModel);
|
||||
this.$emit("setMobileLocation", this.internalModel);
|
||||
this.setMobileLocationInvalid(false);
|
||||
},
|
||||
toggleMobileLocation() {
|
||||
this.isMobileLocationOpened = !this.isMobileLocationOpened;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
internalModel: {
|
||||
handler() {
|
||||
this.setMobileLocation();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
|
||||
modelValue: {
|
||||
handler(newValue) {
|
||||
this.internalModel = deepClone(newValue);
|
||||
|
|
@ -308,15 +314,11 @@ export default {
|
|||
deep: true,
|
||||
},
|
||||
},
|
||||
unmounted() {
|
||||
if (this.isModalOpened) this.closeModal();
|
||||
},
|
||||
components: {
|
||||
textLink,
|
||||
modal,
|
||||
addressQuestions,
|
||||
vehicleProtectedQuestion,
|
||||
textBlock,
|
||||
textLink,
|
||||
alert,
|
||||
},
|
||||
};
|
||||
|
|
@ -327,28 +329,34 @@ export default {
|
|||
.center-error-message {
|
||||
justify-content: center !important;
|
||||
}
|
||||
}
|
||||
|
||||
.update-zip-text-link::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 13px;
|
||||
height: 16px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 13 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.49635 1.00142e-07C5.64734 -0.000153295 4.80722 0.175918 4.0274 0.517444C3.24757 0.858969 2.54443 1.35877 1.96099 1.98626C0.765713 3.27588 0.0999756 4.98141 0.0999756 6.75394C0.0999756 8.52646 0.765713 10.232 1.96099 11.5216L5.98324 15.777C6.04954 15.8475 6.12918 15.9036 6.21736 15.9419C6.30555 15.9802 6.40045 16 6.49635 16C6.59225 16 6.68716 15.9802 6.77534 15.9419C6.86353 15.9036 6.94317 15.8475 7.00946 15.777L11.0317 11.52C12.2391 10.2383 12.909 8.52914 12.8999 6.75394C12.9094 4.97818 12.2394 3.26832 11.0317 1.98626C10.4481 1.35899 9.74493 0.859347 8.96514 0.517839C8.18535 0.176331 7.34532 0.000130509 6.49635 1.00142e-07V1.00142e-07ZM6.49635 9.13131C6.02507 9.13131 5.56437 8.98913 5.17251 8.72275C4.78065 8.45637 4.47524 8.07776 4.29488 7.63479C4.11453 7.19181 4.06734 6.70438 4.15928 6.23412C4.25123 5.76387 4.47817 5.33191 4.81142 4.99287C5.14467 4.65384 5.56925 4.42295 6.03148 4.32941C6.49371 4.23587 6.97282 4.28388 7.40823 4.46736C7.84364 4.65085 8.21579 4.96157 8.47762 5.36023C8.73945 5.7589 8.87921 6.2276 8.87921 6.70707C8.87921 7.34974 8.62837 7.96611 8.18185 8.4207C7.73532 8.87528 7.12964 9.13088 6.49794 9.13131H6.49635Z' fill='%231574A1'/%3E%3C/svg%3E%0A");
|
||||
background-size: contain;
|
||||
vertical-align: middle;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
.update-zip-text-link::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 13px;
|
||||
height: 16px;
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 13 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.49635 1.00142e-07C5.64734 -0.000153295 4.80722 0.175918 4.0274 0.517444C3.24757 0.858969 2.54443 1.35877 1.96099 1.98626C0.765713 3.27588 0.0999756 4.98141 0.0999756 6.75394C0.0999756 8.52646 0.765713 10.232 1.96099 11.5216L5.98324 15.777C6.04954 15.8475 6.12918 15.9036 6.21736 15.9419C6.30555 15.9802 6.40045 16 6.49635 16C6.59225 16 6.68716 15.9802 6.77534 15.9419C6.86353 15.9036 6.94317 15.8475 7.00946 15.777L11.0317 11.52C12.2391 10.2383 12.909 8.52914 12.8999 6.75394C12.9094 4.97818 12.2394 3.26832 11.0317 1.98626C10.4481 1.35899 9.74493 0.859347 8.96514 0.517839C8.18535 0.176331 7.34532 0.000130509 6.49635 1.00142e-07V1.00142e-07ZM6.49635 9.13131C6.02507 9.13131 5.56437 8.98913 5.17251 8.72275C4.78065 8.45637 4.47524 8.07776 4.29488 7.63479C4.11453 7.19181 4.06734 6.70438 4.15928 6.23412C4.25123 5.76387 4.47817 5.33191 4.81142 4.99287C5.14467 4.65384 5.56925 4.42295 6.03148 4.32941C6.49371 4.23587 6.97282 4.28388 7.40823 4.46736C7.84364 4.65085 8.21579 4.96157 8.47762 5.36023C8.73945 5.7589 8.87921 6.2276 8.87921 6.70707C8.87921 7.34974 8.62837 7.96611 8.18185 8.4207C7.73532 8.87528 7.12964 9.13088 6.49794 9.13131H6.49635Z' fill='%231574A1'/%3E%3C/svg%3E%0A");
|
||||
background-size: contain;
|
||||
vertical-align: middle;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.address-questions {
|
||||
margin-top: 0em;
|
||||
}
|
||||
.update-mobile-location-text-link {
|
||||
white-space: pre-line;
|
||||
}
|
||||
.address-questions-container {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.update-mobile-location-text-link {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.text-black {
|
||||
color: $black;
|
||||
.text-black {
|
||||
color: $black;
|
||||
}
|
||||
.HeaderText {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.625rem;
|
||||
color: $black;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
textPosition="text-center"
|
||||
v-model="selectedValue"
|
||||
validationRules="option-required"
|
||||
isRequired />
|
||||
isRequired
|
||||
:labelBold="labelBold" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -27,6 +28,11 @@ export default {
|
|||
isVehicleProtected: Boolean,
|
||||
},
|
||||
cmsWidgetName: String,
|
||||
labelBold: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
buttonQuestion,
|
||||
|
|
|
|||
|
|
@ -343,7 +343,6 @@ describe("service-location.vue", () => {
|
|||
zipCode: "43054",
|
||||
},
|
||||
isVehicleProtected: true,
|
||||
isMobileSelected: true,
|
||||
};
|
||||
wrapper.vm.mobileLocationQuestions = mobileLocationQuestions;
|
||||
|
||||
|
|
@ -356,7 +355,6 @@ describe("service-location.vue", () => {
|
|||
zipCode: "61606",
|
||||
},
|
||||
isVehicleProtected: null,
|
||||
isMobileSelected: false,
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
@ -459,7 +457,6 @@ describe("service-location.vue", () => {
|
|||
zipCode: "",
|
||||
},
|
||||
isVehicleProtected: null,
|
||||
isMobileSelected: false,
|
||||
};
|
||||
wrapper.vm.mobileLocationQuestions = mobileLocationQuestions;
|
||||
const newMobileLocationQuestions = {
|
||||
|
|
@ -471,15 +468,14 @@ describe("service-location.vue", () => {
|
|||
zipCode: "43054",
|
||||
},
|
||||
isVehicleProtected: true,
|
||||
isMobileSelected: true,
|
||||
};
|
||||
|
||||
wrapper.vm.closeModalAction = jest.fn();
|
||||
//wrapper.vm.closeModalAction = jest.fn();
|
||||
// Act
|
||||
|
||||
// Trigger the event
|
||||
await mobileLocationQuestionsComponent.vm.$emit(
|
||||
"setMobileLocationAndProceed",
|
||||
"setMobileLocation",
|
||||
newMobileLocationQuestions
|
||||
);
|
||||
|
||||
|
|
@ -521,7 +517,7 @@ describe("service-location.vue", () => {
|
|||
zipCode: "",
|
||||
},
|
||||
isVehicleProtected: null,
|
||||
isMobileSelected: false,
|
||||
isMobileSelectedAndModalClosed: false,
|
||||
mobileFeePart: null,
|
||||
};
|
||||
wrapper.vm.mobileLocationQuestions = mobileLocationQuestions;
|
||||
|
|
@ -535,7 +531,7 @@ describe("service-location.vue", () => {
|
|||
zipCode: "43081",
|
||||
},
|
||||
isVehicleProtected: true,
|
||||
isMobileSelected: true,
|
||||
isMobileSelectedAndModalClosed: true,
|
||||
mobileFeePart: null,
|
||||
};
|
||||
|
||||
|
|
@ -556,7 +552,7 @@ describe("service-location.vue", () => {
|
|||
|
||||
// Trigger the event
|
||||
await mobileLocationQuestionsComponent.vm.$emit(
|
||||
"setMobileLocationAndProceed",
|
||||
"setMobileLocation",
|
||||
newMobileLocationQuestions
|
||||
);
|
||||
|
||||
|
|
@ -599,15 +595,12 @@ describe("service-location.vue", () => {
|
|||
zipCode: "43081",
|
||||
},
|
||||
isVehicleProtected: "YesAnswer",
|
||||
isMobileSelected: true,
|
||||
isMobileSelectedAndModalClosed: true,
|
||||
};
|
||||
|
||||
wrapper.vm.closeModalAction = jest.fn();
|
||||
// Act
|
||||
mobileLocationQuestionsComponent.vm.$emit(
|
||||
"setMobileLocationAndProceed",
|
||||
mobileLocationQuestions
|
||||
);
|
||||
mobileLocationQuestionsComponent.vm.$emit("setMobileLocation", mobileLocationQuestions);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.selectedAppointmentType).toStrictEqual("Mobile");
|
||||
|
|
|
|||
|
|
@ -79,10 +79,12 @@
|
|||
:isServiceableDropoff="isServiceableDropoff"
|
||||
:isDisplayed="isAppointmentTypeDisplayed"
|
||||
:mobileFeeApplies="mobileFeeApplies"
|
||||
:zipCode="zipCode"
|
||||
ref="appointmentTypeQuestion"
|
||||
groupName="appointmentTypeQuestion"
|
||||
cmsWidgetName="AppointmentTypeQuestionWidget"
|
||||
validationRules="option-required" />
|
||||
validationRules="option-required"
|
||||
labelBold="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
|
|
@ -102,7 +104,8 @@
|
|||
ref="mobileLocationQuestions"
|
||||
linkWidgetName="MobileLocationLinkWidget"
|
||||
modalWidgetName="MobileLocationModalWidget"
|
||||
@setMobileLocationAndProceed="setMobileLocationQuestions" />
|
||||
@setMobileLocation="setMobileLocationQuestions"
|
||||
@set-mobile-location-invalid="setMobileLocationInValid" />
|
||||
|
||||
<shopQuestion
|
||||
ref="shopQuestion"
|
||||
|
|
@ -111,15 +114,14 @@
|
|||
:selectedAppointmentType="selectedAppointmentType"
|
||||
:shopProviderData="shopProviderData"
|
||||
:isDisplayed="isShopQuestionDisplayed"
|
||||
cmsWidgetName="ShopQuestionWidget"
|
||||
:isInshopOnly="isInshopOnly" />
|
||||
cmsWidgetName="ShopQuestionWidget" />
|
||||
|
||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||
|
||||
<navbar
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
ref="navbar"
|
||||
:isForwardActionDisabled="!meta.valid || displayNoShopsAlert"
|
||||
:isForwardActionDisabled="!meta.valid || isForwardActionDisabled"
|
||||
@back-clicked="backButtonAction"
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
|
|
@ -173,12 +175,12 @@ const MOBILE_FEE_PART_TYPE = "MOBILE FEE";
|
|||
// DEFINE VALIDATION RULES
|
||||
defineRule("mobile-location-required", (value) => {
|
||||
if (
|
||||
value.isMobileSelected &&
|
||||
(!value.addressQuestions.streetAddress ||
|
||||
!value.addressQuestions.city ||
|
||||
!value.addressQuestions.state ||
|
||||
!value.addressQuestions.zipCode ||
|
||||
!value.isVehicleProtected)
|
||||
!value.isVehicleProtected) &&
|
||||
value.isMobileSelected
|
||||
) {
|
||||
return errorMessages.MOBILE_LOCATION_REQUIRED;
|
||||
}
|
||||
|
|
@ -212,11 +214,12 @@ export default {
|
|||
billToAccountNumber: null,
|
||||
shopProviderData: null,
|
||||
navigatingForward: false,
|
||||
isMobileAddressValid: true,
|
||||
};
|
||||
},
|
||||
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);
|
||||
|
|
@ -302,7 +305,6 @@ export default {
|
|||
zipCode: this.zipCode,
|
||||
},
|
||||
isVehicleProtected: this.isVehicleProtected,
|
||||
isMobileSelected: this.selectedAppointmentType === "Mobile",
|
||||
};
|
||||
},
|
||||
},
|
||||
|
|
@ -416,10 +418,8 @@ export default {
|
|||
isNoComp() {
|
||||
return store.getters.order.policy.isNoComp;
|
||||
},
|
||||
isInshopOnly() {
|
||||
return (
|
||||
this.isServiceableInshop && !this.isServiceableMobile && !this.isServiceableDropoff
|
||||
);
|
||||
isForwardActionDisabled() {
|
||||
return this.displayNoShopsAlert || !this.isMobileAddressValid;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -523,10 +523,7 @@ export default {
|
|||
}
|
||||
if (this.isServiceableMobile) {
|
||||
this.setMobileLocation(newValue);
|
||||
//proceed to next page
|
||||
this.forwardButtonAction();
|
||||
} else {
|
||||
this.closeModalAction("mobileLocationQuestions");
|
||||
await getZipCodeData(newZipCode).then((zipCodeData) => {
|
||||
this.serviceZipCodeQuestion = {
|
||||
state: zipCodeData.state,
|
||||
|
|
@ -614,7 +611,7 @@ export default {
|
|||
} else {
|
||||
this.$router.navigateWithoutSaving(
|
||||
this.navigationScenarios.CLICKED_BACK,
|
||||
this.$route
|
||||
this.pageName
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
@ -694,7 +691,7 @@ export default {
|
|||
},
|
||||
async forwardButtonAction() {
|
||||
this.navigatingForward = true;
|
||||
|
||||
var ctu = this.zipCodeCtu;
|
||||
if (
|
||||
this.selectedAppointmentType == AppointmentTypeStrings.MOBILE &&
|
||||
this.selectedProvider &&
|
||||
|
|
@ -705,18 +702,13 @@ export default {
|
|||
this.selectedProvider.address.state = null;
|
||||
this.selectedProvider.address.zipCode = null;
|
||||
this.selectedProvider.address.zipCodeCtu = null;
|
||||
}
|
||||
|
||||
var ctu = this.zipCodeCtu;
|
||||
if (this.selectedAppointmentType == AppointmentTypeStrings.IN_SHOP) {
|
||||
} else {
|
||||
// if we have a provider.zipCodeCtu that's different than the servicelocation.zipCodeCtu then they
|
||||
// may have selected a shop in a different ctu. change the servicelocation zip/ctu if different
|
||||
if (this.zipCodeCtu != this.selectedProvider.address.zipCodeCtu) {
|
||||
ctu = this.selectedProvider.address.zipCodeCtu;
|
||||
}
|
||||
|
||||
this.city = null;
|
||||
this.streetAddress = null;
|
||||
this.resetMobileLocation();
|
||||
}
|
||||
|
||||
await this.dispatchStoreAction(
|
||||
|
|
@ -754,13 +746,20 @@ 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();
|
||||
setMobileLocationInValid(isMobileLocationInValid) {
|
||||
this.isMobileAddressValid = !isMobileLocationInValid;
|
||||
},
|
||||
closeModalAction(modalName) {
|
||||
this.$refs[modalName].closeModal();
|
||||
displayMobileAddressQuestion(openMobileLocation) {
|
||||
var mobileLocationQuestionsRef = this.$refs.mobileLocationQuestions;
|
||||
var isMobileAddressComplete = mobileLocationQuestionsRef.isMobileAddressComplete;
|
||||
if (isMobileAddressComplete) {
|
||||
mobileLocationQuestionsRef.isMobileLocationOpened = openMobileLocation;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -773,8 +772,10 @@ export default {
|
|||
this.selectedProvider = new Provider(
|
||||
this.shopProviderData.mobileProviderNumber
|
||||
);
|
||||
this.displayMobileAddressQuestion(true);
|
||||
} else {
|
||||
this.selectedProvider = new Provider();
|
||||
this.displayMobileAddressQuestion(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -786,12 +787,10 @@ export default {
|
|||
this.selectedProvider = new Provider(
|
||||
this.shopProviderData.mobileProviderNumber
|
||||
);
|
||||
var mobileLocationQs = this.$refs.mobileLocationQuestions;
|
||||
if (!mobileLocationQs.isMobileAddressComplete()) {
|
||||
mobileLocationQs.openModal();
|
||||
}
|
||||
this.displayMobileAddressQuestion(true);
|
||||
} else {
|
||||
this.selectedProvider = new Provider();
|
||||
this.displayMobileAddressQuestion(false);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ export default {
|
|||
cmsWidgetName: String,
|
||||
validationRules: String,
|
||||
isDisplayed: Boolean,
|
||||
isInshopOnly: Boolean,
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
|
|
@ -234,13 +233,9 @@ export default {
|
|||
// nothing to do with this component. We could mitigate this by showing / hiding this component with v-if but that messes
|
||||
// up the component initialization on page load.
|
||||
async handler() {
|
||||
//We do not need to run this handler in case of Inshop only else it will ended running twice function getNextShopsFromList and will cause pagination
|
||||
if (!this.isInshopOnly) {
|
||||
this.resetAnswers();
|
||||
|
||||
await nextTick();
|
||||
this.getNextShopsFromList();
|
||||
}
|
||||
await nextTick();
|
||||
this.resetAnswers();
|
||||
this.getNextShopsFromList();
|
||||
},
|
||||
},
|
||||
shopProviders: {
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
import serviceZip from "@/layouts/service-zip/service-zip";
|
||||
|
||||
// Supporting Files
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import { mount, shallowMount } from "@vue/test-utils";
|
||||
import { getMountOptions } from "@/helpers/unit-test-helper";
|
||||
import baseMixin from "@/mixins/base-mixin";
|
||||
import store from "@/store";
|
||||
import router from "@/router";
|
||||
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
|
||||
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
|
||||
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
|
||||
import vinPagesMixin from "@/mixins/vin-pages-mixin";
|
||||
import { experimentSettings } from "../../constants/experiments";
|
||||
|
|
@ -251,20 +251,6 @@ describe("service-zip.vue", () => {
|
|||
expect(wrapper.vm.serviceZipCode).toEqual("11111");
|
||||
expect(wrapper.vm.emailOrSms).toEqual("builddigitaltest@safelite.com");
|
||||
});
|
||||
|
||||
test("Zip in querystring -> pushed to data", () => {
|
||||
// Arrange
|
||||
// no changes to store
|
||||
applyMockStoreDataToGetters();
|
||||
|
||||
// Act
|
||||
const wrapper = setupMocks({
|
||||
customZipQuery: "11111",
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.serviceZipCode).toEqual("11111");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Navigation", () => {
|
||||
|
|
@ -285,7 +271,7 @@ describe("service-zip.vue", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_SKIP_VIN,
|
||||
wrapper.vm.$route
|
||||
wrapper.vm.$route.name
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -301,7 +287,7 @@ describe("service-zip.vue", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
|
||||
navigationScenarios.CLICKED_BACK,
|
||||
wrapper.vm.$route
|
||||
wrapper.vm.$route.name
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -326,7 +312,7 @@ describe("service-zip.vue", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toBeCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_NO_QUESTIONS,
|
||||
wrapper.vm.$route
|
||||
wrapper.vm.$route.name
|
||||
);
|
||||
expect(wrapper.vm.navigateForwardWithSingleCarMatch).not.toBeCalled();
|
||||
});
|
||||
|
|
@ -486,7 +472,7 @@ describe("service-zip.vue", () => {
|
|||
});
|
||||
|
||||
function setupMocks({ customMountOptions, customZipQuery, customZipDataResponse }) {
|
||||
const route = { query: { fmgPage: "service-zip" }, params: {} };
|
||||
const route = { name: "service-zip" };
|
||||
if (customZipQuery) {
|
||||
route.query.zipcode = customZipQuery;
|
||||
}
|
||||
|
|
@ -499,6 +485,7 @@ function setupMocks({ customMountOptions, customZipQuery, customZipDataResponse
|
|||
|
||||
mountOptions.global.mocks["$store"] = store;
|
||||
mountOptions.global.mocks["$router"] = router;
|
||||
mountOptions.global.mocks.pageName = route.name;
|
||||
mountOptions.mixins = [
|
||||
{
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -95,7 +95,8 @@ import vinPagesMixin from "@/mixins/vin-pages-mixin";
|
|||
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 { routeData } from "@/router/constants/routes";
|
||||
import { consumeQueryFromStash } from "@/router/methods/helpers/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
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
@ -242,7 +243,7 @@ export default {
|
|||
await this.dispatchStoreAction(
|
||||
storeActions.SAVE_PAGE_DATA,
|
||||
{
|
||||
page: fmgPageValues.EMAIL_SMS_PAGES,
|
||||
page: routeData.SERVICE_ZIP.name,
|
||||
data: { emailOrSmsValue: this.emailOrSms },
|
||||
},
|
||||
false
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import { storeActions } from "@/constants/store-actions";
|
|||
import store from "@/store";
|
||||
import { validate } from "vee-validate";
|
||||
import { damageLocationsSelected } from "@/constants/damage-locations-selected.js";
|
||||
import { routerParams } from "@/router/router-constants/router-params";
|
||||
import * as cookieHelper from "@/helpers/heritage-integration/cookie-helper";
|
||||
|
||||
// Mock our module for promises.
|
||||
|
|
@ -310,11 +309,11 @@ describe("vehicle-damage.vue", () => {
|
|||
describe("alert", () => {
|
||||
test("when displayVehicleChangeAlert router params is true, the alert: 'vehicleChangeAlert' should be rendered", () => {
|
||||
// Arrange & Act
|
||||
window.history.pushState({ displayVehicleChangeAlert: "true" }, "", "");
|
||||
const { wrapper } = setupMocks({
|
||||
mountOptionsMockData: {
|
||||
route: {
|
||||
state: { displayVehicleChangeAlert: true },
|
||||
name: "vehicle-damage",
|
||||
query: { displayVehicleChangeAlert: true },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
@ -328,8 +327,9 @@ describe("vehicle-damage.vue", () => {
|
|||
const { wrapper } = setupMocks({
|
||||
mountOptionsMockData: {
|
||||
route: {
|
||||
state: {
|
||||
[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false,
|
||||
name: "vehicle-damage",
|
||||
query: {
|
||||
displayVehicleChangeAlert: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -345,8 +345,9 @@ describe("vehicle-damage.vue", () => {
|
|||
const { wrapper } = setupMocks({
|
||||
mountOptionsMockData: {
|
||||
route: {
|
||||
params: {
|
||||
[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: undefined,
|
||||
name: "vehicle-damage",
|
||||
query: {
|
||||
displayVehicleChangeAlert: undefined,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -852,9 +853,8 @@ function setupMocks({ pageHeaderWidgetHeaderText, mountOptionsMockData, funnelCo
|
|||
navigateWithSaving: jest.fn(),
|
||||
},
|
||||
route: {
|
||||
state: {
|
||||
[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false,
|
||||
},
|
||||
name: "vehicle-damage",
|
||||
query: {},
|
||||
},
|
||||
store: {
|
||||
getters: {
|
||||
|
|
|
|||
|
|
@ -97,7 +97,6 @@ import { errorMessages } from "@/constants/error-messages";
|
|||
import { damageLocationsCms } from "@/constants/damage-locations-cms.js";
|
||||
import { damageLocationsSelected } from "@/constants/damage-locations-selected.js";
|
||||
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||
import { routerParams } from "@/router/router-constants/router-params";
|
||||
|
||||
import store from "@/store";
|
||||
import baseMixin from "@/mixins/base-mixin";
|
||||
|
|
@ -110,7 +109,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 +248,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 +457,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 +486,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 +625,7 @@ export default {
|
|||
);
|
||||
},
|
||||
shouldDisplayVehicleChangeAlert() {
|
||||
return getBoolFromString(window.history.state.displayVehicleChangeAlert);
|
||||
return getBoolFromString(this.$route?.query?.displayVehicleChangeAlert);
|
||||
},
|
||||
shouldHideBackButton() {
|
||||
return this.$store.getters.requiresVerifiedRedirecting;
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ export default {
|
|||
},
|
||||
|
||||
PartDataFromApi() {
|
||||
return this.$store.getters.pageData(this.$route.query.fmgPage) ?? {};
|
||||
return this.$store.getters.pageData(this.pageName) ?? {};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import baseMixin from "@/mixins/base-mixin.js";
|
|||
import { storeActions } from "@/constants/store-actions";
|
||||
import store from "@/store";
|
||||
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
|
||||
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
|
||||
|
||||
// Mock our module for promises.
|
||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||
|
|
@ -84,11 +84,10 @@ describe("vehicle-parts.vue", () => {
|
|||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
},
|
||||
route: {
|
||||
query: {
|
||||
fmgPage: "vehicle-parts",
|
||||
},
|
||||
name: "vehicle-parts",
|
||||
},
|
||||
store: {
|
||||
getters: store.getters,
|
||||
|
|
@ -123,11 +122,10 @@ describe("vehicle-parts.vue", () => {
|
|||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
},
|
||||
route: {
|
||||
query: {
|
||||
fmgPage: "vehicle-parts",
|
||||
},
|
||||
name: "vehicle-parts",
|
||||
},
|
||||
store: {
|
||||
getters: store.getters,
|
||||
|
|
@ -161,11 +159,10 @@ describe("vehicle-parts.vue", () => {
|
|||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
},
|
||||
route: {
|
||||
query: {
|
||||
fmgPage: "vehicle-parts",
|
||||
},
|
||||
name: "vehicle-parts",
|
||||
},
|
||||
store: {
|
||||
getters: store.getters,
|
||||
|
|
@ -205,11 +202,10 @@ describe("vehicle-parts.vue", () => {
|
|||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
},
|
||||
route: {
|
||||
query: {
|
||||
fmgPage: "vehicle-parts",
|
||||
},
|
||||
name: "vehicle-parts",
|
||||
},
|
||||
store: {
|
||||
getters: {
|
||||
|
|
@ -255,7 +251,7 @@ describe("vehicle-parts.vue", () => {
|
|||
//Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
wrapper.vm.$route
|
||||
wrapper.vm.$route.name
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -268,11 +264,10 @@ describe("vehicle-parts.vue", () => {
|
|||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
},
|
||||
route: {
|
||||
query: {
|
||||
fmgPage: "vehicle-parts",
|
||||
},
|
||||
name: "vehicle-parts",
|
||||
},
|
||||
store: {
|
||||
getters: {
|
||||
|
|
@ -302,7 +297,7 @@ describe("vehicle-parts.vue", () => {
|
|||
//Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
wrapper.vm.$route
|
||||
wrapper.vm.$route.name
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -356,11 +351,10 @@ describe("vehicle-parts.vue", () => {
|
|||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
},
|
||||
route: {
|
||||
query: {
|
||||
fmgPage: "vehicle-parts",
|
||||
},
|
||||
name: "vehicle-parts",
|
||||
},
|
||||
store: {
|
||||
getters: store.getters,
|
||||
|
|
@ -384,7 +378,7 @@ describe("vehicle-parts.vue", () => {
|
|||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("ForwardButtonAction triggers a router.navigateWithSaving change if there are capability questions", async () => {
|
||||
|
|
@ -417,11 +411,10 @@ describe("vehicle-parts.vue", () => {
|
|||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
},
|
||||
route: {
|
||||
query: {
|
||||
fmgPage: "vehicle-parts",
|
||||
},
|
||||
name: "vehicle-parts",
|
||||
},
|
||||
store: {
|
||||
getters: store.getters,
|
||||
|
|
@ -451,7 +444,7 @@ describe("vehicle-parts.vue", () => {
|
|||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("ForwardButtonAction saves selected parts to store if no molding or capability questions", async () => {
|
||||
|
|
@ -468,11 +461,10 @@ describe("vehicle-parts.vue", () => {
|
|||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
},
|
||||
route: {
|
||||
query: {
|
||||
fmgPage: "vehicle-parts",
|
||||
},
|
||||
name: "vehicle-parts",
|
||||
},
|
||||
store: {
|
||||
getters: store.getters,
|
||||
|
|
@ -544,6 +536,7 @@ function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {}
|
|||
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
|
||||
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
|
||||
wrapper.vm.$refs.loadingModal.showModal = jest.fn();
|
||||
wrapper.vm.pageName = "vehicle-parts";
|
||||
// wrapper.vm.$refs.onSubmit = jest.fn();
|
||||
// wrapper.vm.$refs.onInvalidSubmit = jest.fn();
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ import saveProgressModalQuestion from "@/fmg-components/save-progress-modal-ques
|
|||
// Supporting Files
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import { Form } from "vee-validate";
|
||||
import store from "@/store";
|
||||
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
||||
|
|
@ -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 = [
|
||||
{
|
||||
|
|
@ -162,7 +162,7 @@ export default {
|
|||
},
|
||||
|
||||
PartsFromApi() {
|
||||
return this.$store.getters.pageData(fmgPageValues.VEHICLE_PARTS);
|
||||
return this.$store.getters.pageData(routeData.VEHICLE_PARTS.name);
|
||||
},
|
||||
|
||||
RefPrefix() {
|
||||
|
|
@ -172,7 +172,7 @@ export default {
|
|||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
// Check if isRepair is populated and if the pageData we need is here (Parts data)
|
||||
const vehiclePartsFromPageData = store.getters.pageData(fmgPageValues.VEHICLE_PARTS);
|
||||
const vehiclePartsFromPageData = store.getters.pageData(routeData.VEHICLE_PARTS.name);
|
||||
return (
|
||||
store.getters.damage.isRepair != null &&
|
||||
vehiclePartsFromPageData?.partsOrQuestions?.some((part) => part?.glassName)
|
||||
|
|
|
|||
|
|
@ -110,6 +110,11 @@ 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/methods/helpers/querystring-stash";
|
||||
import { debugLog } from "@/helpers/debug-log-helper";
|
||||
|
||||
//define validation rules
|
||||
defineRule("year-required", required(errorMessages.YEAR_REQUIRED));
|
||||
|
|
@ -133,7 +138,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: [],
|
||||
|
|
@ -144,17 +149,12 @@ export default {
|
|||
},
|
||||
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
if (store.getters.applicationUser.loggingOption) {
|
||||
console.log(
|
||||
new Date() + "------------- vehicle.vue applicationConfig start -------------"
|
||||
);
|
||||
console.log(new Date() + JSON.stringify(applicationConfig));
|
||||
console.log(
|
||||
new Date() + "------------- vehicle.vue applicationConfig end -------------"
|
||||
);
|
||||
}
|
||||
debugLog("------------- vehicle.vue applicationConfig start -------------");
|
||||
debugLog("", applicationConfig);
|
||||
debugLog("------------- vehicle.vue applicationConfig end -------------");
|
||||
|
||||
// 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 +213,7 @@ export default {
|
|||
userId: getUserIdValue(),
|
||||
deviceId: getDeviceIdValue(),
|
||||
sessionKey: getSessionKeyValue(),
|
||||
pageName: to.query.fmgPage,
|
||||
pageName: to.name,
|
||||
experiment: experimentForLogging,
|
||||
},
|
||||
"vehicle",
|
||||
|
|
@ -536,7 +536,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;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { shallowMount } from "@vue/test-utils";
|
||||
import vinLookup from "./vin-lookup.vue";
|
||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios.js";
|
||||
import { navigationScenarios } from "@/router/constants/navigation-scenarios.js";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper.js";
|
||||
import { experimentSettings } from "@/constants/experiments";
|
||||
|
||||
|
|
|
|||
|
|
@ -155,11 +155,12 @@ import {
|
|||
import { required, regex } from "@/helpers/validation-rules";
|
||||
import { Form, defineRule } from "vee-validate";
|
||||
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||
import { routerParams } from "@/router/router-constants/router-params";
|
||||
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 { routeData } from "@/router/constants/routes";
|
||||
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||
|
|
@ -180,7 +181,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 +204,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 +248,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
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
@ -389,7 +390,7 @@ export default {
|
|||
await this.dispatchStoreAction(
|
||||
storeActions.SAVE_PAGE_DATA,
|
||||
{
|
||||
page: fmgPageValues.EMAIL_SMS_PAGES,
|
||||
page: routeData.SERVICE_ZIP.name,
|
||||
data: { emailOrSmsValue: this.emailOrSms },
|
||||
},
|
||||
false
|
||||
|
|
@ -452,7 +453,7 @@ export default {
|
|||
await this.dispatchStoreAction(
|
||||
storeActions.SAVE_PAGE_DATA,
|
||||
{
|
||||
page: fmgPageValues.EMAIL_SMS_PAGES,
|
||||
page: routeData.SERVICE_ZIP.name,
|
||||
data: { emailOrSmsValue: this.emailOrSms },
|
||||
},
|
||||
false
|
||||
|
|
@ -474,9 +475,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();
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
import store from "@/store";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import analyticsMixin from "@/mixins/analytics-mixin.js";
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ import store from "@/store";
|
|||
import baseMixin from "@/mixins/base-mixin";
|
||||
import { applicationConfig } from "../constants/application-config";
|
||||
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import router from "@/router/index.js";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||
import { Variables } from "../constants/analytics";
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
|
|
@ -44,7 +44,7 @@ export default {
|
|||
const submittedOrder = baseMixin.methods.getSubmittedOrder();
|
||||
const hasSubmittedOrder = baseMixin.methods.hasSubmittedOrder();
|
||||
const hasSubmittedOrderAtConfirmationPage =
|
||||
hasSubmittedOrder && currentPageName?.toLowerCase() == fmgPageValues.CONFIRMATION;
|
||||
hasSubmittedOrder && currentPageName?.toLowerCase() == routeData.CONFIRMATION.name;
|
||||
|
||||
const refSequenceNum = hasSubmittedOrderAtConfirmationPage
|
||||
? submittedOrder.referralSequenceNumber
|
||||
|
|
@ -120,6 +120,10 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
async pushVariableToDataLayer(data) {
|
||||
pushToDataLayerIfDefined(data);
|
||||
},
|
||||
|
||||
async pushPageViewToGA() {
|
||||
const currentPageName = getPageNameByQueryString();
|
||||
const pageViewEvent = {
|
||||
|
|
@ -306,6 +310,18 @@ export default {
|
|||
} else {
|
||||
payload.priceSubTotal = "";
|
||||
}
|
||||
|
||||
// Cash Quote or Cash Price Sub Total
|
||||
if (isPricingAvailable) {
|
||||
const subtotal = baseMixin.methods
|
||||
.getTotalPriceOfAllLineItemsAndChildParts(combinedLineItems, false)
|
||||
.toFixed(2);
|
||||
|
||||
payload.cashPriceSubTotal = parseFloat(subtotal);
|
||||
} else {
|
||||
payload.cashPriceSubTotal = "";
|
||||
}
|
||||
|
||||
//unverified (in scenarios we don’t display the price)
|
||||
if (
|
||||
order.payment.isInsurance &&
|
||||
|
|
@ -770,6 +786,9 @@ export default {
|
|||
ValueToLogTypes() {
|
||||
return ValueToLogTypes;
|
||||
},
|
||||
Variables() {
|
||||
return Variables;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,19 +2,20 @@ 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/constants/navigation-scenarios";
|
||||
import { vehicleCategories } from "@/constants/vehicle-categories.js";
|
||||
import { routerParams } from "@/router/router-constants/router-params";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
import { dynamicStrings } from "@/constants/dynamic-strings";
|
||||
import { partTypeStrings } from "../constants/part-type-strings";
|
||||
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
||||
import { getItemsWithoutRecalParts } from "@/helpers/recal-helper";
|
||||
import { debugLog } from "@/helpers/debug-log-helper";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
cmsContentByWidget: {},
|
||||
_componentPageName: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -95,10 +96,8 @@ export default {
|
|||
let totalPrice = this.getTotalPriceOfAllLineItemsAndChildParts(lineItemsToPrice, false);
|
||||
// prettier-ignore
|
||||
{
|
||||
if (store.getters.applicationUser.loggingOption) {
|
||||
console.log(new Date() + " base-mixin getTierOnePackagePrice lineItemsToPrice: " + JSON.stringify(lineItemsToPrice));
|
||||
console.log(new Date() + " base-mixin getTierOnePackagePrice totalPrice: " + totalPrice);
|
||||
}
|
||||
debugLog("base-mixin getTierOnePackagePrice lineItemsToPrice:", lineItemsToPrice);
|
||||
debugLog("base-mixin getTierOnePackagePrice totalPrice:", totalPrice);
|
||||
}
|
||||
return totalPrice;
|
||||
},
|
||||
|
|
@ -234,9 +233,6 @@ export default {
|
|||
vehicleCategories() {
|
||||
return vehicleCategories;
|
||||
},
|
||||
routerParams() {
|
||||
return routerParams;
|
||||
},
|
||||
queryStrings() {
|
||||
return queryStrings;
|
||||
},
|
||||
|
|
@ -246,9 +242,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import baseMixin from "@/mixins/base-mixin";
|
||||
import { storeActions } from "@/constants/store-actions.js";
|
||||
import { storeMutations } from "@/constants/store-mutations.js";
|
||||
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
|
||||
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
|
||||
import { vehicleCategories } from "@/constants/vehicle-categories.js";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
import { dynamicStrings } from "@/constants/dynamic-strings";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import { storeMutations } from "@/constants/store-mutations.js";
|
||||
import { navigationScenarios } from "../router/router-constants/navigation-scenarios";
|
||||
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
|
|
@ -53,11 +53,11 @@ export default {
|
|||
},
|
||||
comparePageIndices(currentPage, fmgPage) {
|
||||
const orderedVehicleQuestionPages = [
|
||||
fmgPageValues.PART_QUESTIONS,
|
||||
fmgPageValues.VEHICLE_PARTS,
|
||||
fmgPageValues.MOLDING_QUESTIONS,
|
||||
fmgPageValues.CAPABILITY_QUESTIONS,
|
||||
fmgPageValues.QUOTE,
|
||||
routeData.PART_QUESTIONS.name,
|
||||
routeData.VEHICLE_PARTS.name,
|
||||
routeData.MOLDING_QUESTIONS.name,
|
||||
routeData.CAPABILITY_QUESTIONS.name,
|
||||
routeData.QUOTE.name,
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
@ -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 =
|
||||
|
|
@ -369,44 +369,38 @@ export default {
|
|||
|
||||
if (
|
||||
hasPartQuestions &&
|
||||
this.currentPageComesBeforePage(currentPage, fmgPageValues.PART_QUESTIONS)
|
||||
this.currentPageComesBeforePage(currentPage, routeData.PART_QUESTIONS.name)
|
||||
) {
|
||||
self.$router.navigateWithSaving(
|
||||
self.$router.navigateWithPageData(
|
||||
self.navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
self.$route,
|
||||
{},
|
||||
{},
|
||||
self.pageName,
|
||||
{ partsOrQuestions: partsOrQuestions }
|
||||
);
|
||||
} else if (
|
||||
hasGlassLocationWithMultipleParts &&
|
||||
this.currentPageComesBeforePage(currentPage, fmgPageValues.VEHICLE_PARTS)
|
||||
this.currentPageComesBeforePage(currentPage, routeData.VEHICLE_PARTS.name)
|
||||
) {
|
||||
// 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 (
|
||||
hasChildPartQuestions &&
|
||||
this.currentPageComesBeforePage(currentPage, fmgPageValues.MOLDING_QUESTIONS)
|
||||
this.currentPageComesBeforePage(currentPage, routeData.MOLDING_QUESTIONS.name)
|
||||
) {
|
||||
// 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 (
|
||||
hasCapabilityQuestions &&
|
||||
this.currentPageComesBeforePage(currentPage, fmgPageValues.CAPABILITY_QUESTIONS)
|
||||
this.currentPageComesBeforePage(currentPage, routeData.CAPABILITY_QUESTIONS.name)
|
||||
) {
|
||||
// if has capability questions
|
||||
// go to capability-questions page and pass the partsData
|
||||
|
|
@ -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,16 +477,16 @@ 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
|
||||
routeData.CAPABILITY_QUESTIONS.name
|
||||
);
|
||||
const pageDataMoldingQuestions = self.$store.getters.pageData(
|
||||
fmgPageValues.MOLDING_QUESTIONS
|
||||
routeData.MOLDING_QUESTIONS.name
|
||||
);
|
||||
const pageDataVehicleParts = self.$store.getters.pageData(fmgPageValues.VEHICLE_PARTS);
|
||||
const pageDataVehicleParts = self.$store.getters.pageData(routeData.VEHICLE_PARTS.name);
|
||||
const pageDataPartQuestions = self.$store.getters.pageData(
|
||||
fmgPageValues.PART_QUESTIONS
|
||||
routeData.PART_QUESTIONS.name
|
||||
);
|
||||
|
||||
const allPartsOrQuestions = [
|
||||
|
|
@ -518,28 +510,28 @@ export default {
|
|||
|
||||
if (
|
||||
hasCapabilityQuestions &&
|
||||
this.currentPageComesAfterPage(currentPage, fmgPageValues.CAPABILITY_QUESTIONS)
|
||||
this.currentPageComesAfterPage(currentPage, routeData.CAPABILITY_QUESTIONS.name)
|
||||
) {
|
||||
backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS;
|
||||
} else if (
|
||||
hasChildPartQuestions &&
|
||||
this.currentPageComesAfterPage(currentPage, fmgPageValues.MOLDING_QUESTIONS)
|
||||
this.currentPageComesAfterPage(currentPage, routeData.MOLDING_QUESTIONS.name)
|
||||
) {
|
||||
backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS;
|
||||
} else if (
|
||||
hasGlassLocationWithMultipleParts &&
|
||||
this.currentPageComesAfterPage(currentPage, fmgPageValues.VEHICLE_PARTS)
|
||||
this.currentPageComesAfterPage(currentPage, routeData.VEHICLE_PARTS.name)
|
||||
) {
|
||||
backNavigationScenario =
|
||||
navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE;
|
||||
} else if (
|
||||
hasPartQuestions &&
|
||||
this.currentPageComesAfterPage(currentPage, fmgPageValues.PART_QUESTIONS)
|
||||
this.currentPageComesAfterPage(currentPage, routeData.PART_QUESTIONS.name)
|
||||
) {
|
||||
backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS;
|
||||
}
|
||||
|
||||
self.$router.navigateWithoutSaving(backNavigationScenario, self.$route);
|
||||
self.$router.navigateWithoutSaving(backNavigationScenario, self.pageName);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
||||
import { shallowMount } from "@vue/test-utils";
|
||||
import { setupMocksForJsFiles, getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import { storeMutations } from "@/constants/store-mutations";
|
||||
import store from "@/store";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { navigationScenarios } from "../router/router-constants/navigation-scenarios";
|
||||
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
|
||||
import { getters } from "@/store";
|
||||
|
||||
jest.mock("@/helpers/heritage-integration/navigation-helper", () => ({
|
||||
|
|
@ -290,13 +290,13 @@ describe("vehicle-questions-mixin", () => {
|
|||
|
||||
describe("currentPageComesBeforePage", () => {
|
||||
const testCases = [
|
||||
[fmgPageValues.PART_QUESTIONS, fmgPageValues.VEHICLE_PARTS, true],
|
||||
[fmgPageValues.VEHICLE_PARTS, fmgPageValues.VEHICLE_PARTS, false],
|
||||
[fmgPageValues.QUOTE, fmgPageValues.VEHICLE_PARTS, false],
|
||||
[fmgPageValues.QUOTE, fmgPageValues.QUOTE, false],
|
||||
[fmgPageValues.VEHICLE_PARTS, fmgPageValues.PART_QUESTIONS, false],
|
||||
[fmgPageValues.PART_QUESTIONS, fmgPageValues.CAPABILITY_QUESTIONS, true],
|
||||
[fmgPageValues.MOLDING_QUESTIONS, fmgPageValues.CAPABILITY_QUESTIONS, true],
|
||||
[routeData.PART_QUESTIONS, routeData.VEHICLE_PARTS, true],
|
||||
[routeData.VEHICLE_PARTS, routeData.VEHICLE_PARTS, false],
|
||||
[routeData.QUOTE, routeData.VEHICLE_PARTS, false],
|
||||
[routeData.QUOTE, routeData.QUOTE, false],
|
||||
[routeData.VEHICLE_PARTS, routeData.PART_QUESTIONS, false],
|
||||
[routeData.PART_QUESTIONS, routeData.CAPABILITY_QUESTIONS, true],
|
||||
[routeData.MOLDING_QUESTIONS, routeData.CAPABILITY_QUESTIONS, true],
|
||||
];
|
||||
test.each(testCases)(
|
||||
"%s comes before %s is %s",
|
||||
|
|
@ -305,7 +305,10 @@ describe("vehicle-questions-mixin", () => {
|
|||
const { wrapper } = setupMocks({});
|
||||
|
||||
// Act
|
||||
const result = wrapper.vm.currentPageComesBeforePage(currentPage, nextPage);
|
||||
const result = wrapper.vm.currentPageComesBeforePage(
|
||||
currentPage.name,
|
||||
nextPage.name
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual(expectedResult);
|
||||
|
|
@ -315,20 +318,20 @@ describe("vehicle-questions-mixin", () => {
|
|||
|
||||
describe("currentPageComesAfterPage", () => {
|
||||
const testCases = [
|
||||
[fmgPageValues.PART_QUESTIONS, fmgPageValues.VEHICLE_PARTS, false],
|
||||
[fmgPageValues.VEHICLE_PARTS, fmgPageValues.VEHICLE_PARTS, false],
|
||||
[fmgPageValues.QUOTE, fmgPageValues.VEHICLE_PARTS, true],
|
||||
[fmgPageValues.QUOTE, fmgPageValues.QUOTE, false],
|
||||
[fmgPageValues.VEHICLE_PARTS, fmgPageValues.PART_QUESTIONS, true],
|
||||
[fmgPageValues.PART_QUESTIONS, fmgPageValues.CAPABILITY_QUESTIONS, false],
|
||||
[fmgPageValues.MOLDING_QUESTIONS, fmgPageValues.CAPABILITY_QUESTIONS, false],
|
||||
[routeData.PART_QUESTIONS, routeData.VEHICLE_PARTS, false],
|
||||
[routeData.VEHICLE_PARTS, routeData.VEHICLE_PARTS, false],
|
||||
[routeData.QUOTE, routeData.VEHICLE_PARTS, true],
|
||||
[routeData.QUOTE, routeData.QUOTE, false],
|
||||
[routeData.VEHICLE_PARTS, routeData.PART_QUESTIONS, true],
|
||||
[routeData.PART_QUESTIONS, routeData.CAPABILITY_QUESTIONS, false],
|
||||
[routeData.MOLDING_QUESTIONS, routeData.CAPABILITY_QUESTIONS, false],
|
||||
];
|
||||
test.each(testCases)("%s comes after %s is %s", (currentPage, nextPage, expectedResult) => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
// Act
|
||||
const result = wrapper.vm.currentPageComesAfterPage(currentPage, nextPage);
|
||||
const result = wrapper.vm.currentPageComesAfterPage(currentPage.name, nextPage.name);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual(expectedResult);
|
||||
|
|
@ -1321,12 +1324,10 @@ describe("vehicle-questions-mixin", () => {
|
|||
await wrapper.vm.navigateForward(partsOrQuestions);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
wrapper.vm.$route.name,
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
});
|
||||
|
|
@ -1436,12 +1437,10 @@ describe("vehicle-questions-mixin", () => {
|
|||
await wrapper.vm.navigateForward(partsOrQuestions);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
wrapper.vm.$route.name,
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
});
|
||||
|
|
@ -1543,12 +1542,10 @@ describe("vehicle-questions-mixin", () => {
|
|||
await wrapper.vm.navigateForward(partsOrQuestions);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
wrapper.vm.$route.name,
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
});
|
||||
|
|
@ -1698,12 +1695,10 @@ describe("vehicle-questions-mixin", () => {
|
|||
await wrapper.vm.navigateForward(partsOrQuestions);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
wrapper.vm.$route.name,
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
});
|
||||
|
|
@ -1746,12 +1741,10 @@ describe("vehicle-questions-mixin", () => {
|
|||
await wrapper.vm.navigateForward(partsOrQuestions);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
wrapper.vm.$route.name,
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
});
|
||||
|
|
@ -1858,12 +1851,10 @@ describe("vehicle-questions-mixin", () => {
|
|||
await wrapper.vm.navigateForward(partsOrQuestions);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
wrapper.vm.$route.name,
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
});
|
||||
|
|
@ -2036,12 +2027,10 @@ describe("vehicle-questions-mixin", () => {
|
|||
await wrapper.vm.navigateForward(partsOrQuestions);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
wrapper.vm.$route.name,
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
});
|
||||
|
|
@ -2095,12 +2084,10 @@ describe("vehicle-questions-mixin", () => {
|
|||
await wrapper.vm.navigateForward(partsOrQuestions);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
wrapper.vm.$route.name,
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
});
|
||||
|
|
@ -2137,12 +2124,10 @@ describe("vehicle-questions-mixin", () => {
|
|||
await wrapper.vm.navigateForward(partsOrQuestions);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
wrapper.vm.$route,
|
||||
{},
|
||||
{},
|
||||
wrapper.vm.$route.name,
|
||||
{ partsOrQuestions }
|
||||
);
|
||||
});
|
||||
|
|
@ -2315,7 +2300,7 @@ describe("vehicle-questions-mixin", () => {
|
|||
|
||||
test("current page is quote, there are no questions, and we have their vin => go to vin-lookup", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ fmgPage: fmgPageValues.QUOTE, hasVin: true });
|
||||
const { wrapper } = setupMocks({ fmgPage: routeData.QUOTE.name, hasVin: true });
|
||||
|
||||
// Act
|
||||
store.dispatch = jest.fn(() => {});
|
||||
|
|
@ -2324,13 +2309,13 @@ describe("vehicle-questions-mixin", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
{ query: { fmgPage: fmgPageValues.QUOTE } }
|
||||
routeData.QUOTE.name
|
||||
);
|
||||
});
|
||||
|
||||
test("current page is quote and there are capability questions => go to capability questions", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ fmgPage: fmgPageValues.QUOTE });
|
||||
const { wrapper } = setupMocks({ fmgPage: routeData.QUOTE.name });
|
||||
wrapper.vm.hasCapabilityQuestions = jest.fn().mockReturnValue(true);
|
||||
|
||||
// Act
|
||||
|
|
@ -2340,13 +2325,13 @@ describe("vehicle-questions-mixin", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS,
|
||||
{ query: { fmgPage: fmgPageValues.QUOTE } }
|
||||
routeData.QUOTE.name
|
||||
);
|
||||
});
|
||||
|
||||
test("current page is quote and there are part questions and molding questions => go to molding questions", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ fmgPage: fmgPageValues.QUOTE });
|
||||
const { wrapper } = setupMocks({ fmgPage: routeData.QUOTE.name });
|
||||
wrapper.vm.hasPartQuestions = jest.fn().mockReturnValue(true);
|
||||
wrapper.vm.hasChildPartQuestions = jest.fn().mockReturnValue(true);
|
||||
|
||||
|
|
@ -2356,13 +2341,13 @@ describe("vehicle-questions-mixin", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS,
|
||||
{ query: { fmgPage: fmgPageValues.QUOTE } }
|
||||
routeData.QUOTE.name
|
||||
);
|
||||
});
|
||||
|
||||
test("current page is molding questions and there are part questions, multiple parts to choose, and capability questions => go to vehicle-parts", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ fmgPage: fmgPageValues.MOLDING_QUESTIONS });
|
||||
const { wrapper } = setupMocks({ fmgPage: routeData.MOLDING_QUESTIONS.name });
|
||||
wrapper.vm.hasPartQuestions = jest.fn().mockReturnValue(true);
|
||||
wrapper.vm.hasGlassLocationWithMultipleParts = jest.fn().mockReturnValue(true);
|
||||
wrapper.vm.hasChildPartQuestions = jest.fn().mockReturnValue(true);
|
||||
|
|
@ -2375,13 +2360,13 @@ describe("vehicle-questions-mixin", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
{ query: { fmgPage: fmgPageValues.MOLDING_QUESTIONS } }
|
||||
routeData.MOLDING_QUESTIONS.name
|
||||
);
|
||||
});
|
||||
|
||||
test("current page is molding questions and there are part questions and capability questions => go to part-questions", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ fmgPage: fmgPageValues.MOLDING_QUESTIONS });
|
||||
const { wrapper } = setupMocks({ fmgPage: routeData.MOLDING_QUESTIONS.name });
|
||||
wrapper.vm.hasPartQuestions = jest.fn().mockReturnValue(true);
|
||||
wrapper.vm.hasGlassLocationWithMultipleParts = jest.fn().mockReturnValue(false);
|
||||
wrapper.vm.hasChildPartQuestions = jest.fn().mockReturnValue(true);
|
||||
|
|
@ -2394,13 +2379,13 @@ describe("vehicle-questions-mixin", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
{ query: { fmgPage: fmgPageValues.MOLDING_QUESTIONS } }
|
||||
routeData.MOLDING_QUESTIONS.name
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks({ fmgPage = fmgPageValues.VIN_LOOKUP, hasVin, carId }) {
|
||||
function setupMocks({ fmgPage = routeData.VIN_LOOKUP.name, hasVin, carId }) {
|
||||
const baseMixin = setupMocksForJsFiles({
|
||||
actionList: [
|
||||
{
|
||||
|
|
@ -2423,6 +2408,7 @@ function setupMocks({ fmgPage = fmgPageValues.VIN_LOOKUP, hasVin, carId }) {
|
|||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
navigateWithPageData: jest.fn(),
|
||||
},
|
||||
store: {
|
||||
commit: jest.fn(),
|
||||
|
|
@ -2436,9 +2422,7 @@ function setupMocks({ fmgPage = fmgPageValues.VIN_LOOKUP, hasVin, carId }) {
|
|||
},
|
||||
},
|
||||
route: {
|
||||
query: {
|
||||
fmgPage,
|
||||
},
|
||||
name: fmgPage,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ function setupMocks({ partsOrQuestions = [] }) {
|
|||
},
|
||||
},
|
||||
},
|
||||
route: {
|
||||
name: "vin-lookup",
|
||||
},
|
||||
});
|
||||
|
||||
const mockVinComponent = {
|
||||
|
|
|
|||
13
src/router/constants/auto-route-table.js
Normal file
13
src/router/constants/auto-route-table.js
Normal 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,
|
||||
];
|
||||
|
|
@ -13,6 +13,7 @@ const navigationScenarios = {
|
|||
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",
|
||||
|
|
@ -45,15 +46,24 @@ const navigationScenarios = {
|
|||
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 };
|
||||
3
src/router/constants/route-prefix.js
Normal file
3
src/router/constants/route-prefix.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export const ROUTE_PREFIX_TRIMMED = "fmg";
|
||||
|
||||
export const ROUTE_PREFIX_FULL = `/${ROUTE_PREFIX_TRIMMED}/`;
|
||||
123
src/router/constants/routes.js
Normal file
123
src/router/constants/routes.js
Normal 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;
|
||||
|
|
@ -1,542 +1,592 @@
|
|||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
|
||||
import store from "@/store";
|
||||
import { paymentMethods } from "@/constants/payment-method-constants";
|
||||
|
||||
// Get store from router/index.js instead of importing it here to get updated values
|
||||
const routingTable = function (store) {
|
||||
// Get as function to live-evaluate filters
|
||||
const routingTable = function () {
|
||||
return [
|
||||
{
|
||||
fmgPageValue: fmgPageValues.VEHICLE,
|
||||
pageName: routeData.VEHICLE.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
destinationPageData: routeData.VEHICLE_DAMAGE,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
fmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
pageName: routeData.VEHICLE_DAMAGE.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE,
|
||||
destinationPageData: routeData.VEHICLE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_VIN,
|
||||
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
|
||||
destinationPageData: routeData.VIN_LOOKUP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
destinationPageData: routeData.ESTIMATE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SKIP_VIN,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
|
||||
destinationPageData: routeData.SERVICE_ZIP,
|
||||
},
|
||||
{
|
||||
scenario:
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_REPAIR_AND_VERIFIED_INSURANCE,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
|
||||
destinationPageData: routeData.SERVICE_ZIP,
|
||||
},
|
||||
{
|
||||
scenario:
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_REPLACE_AND_VERIFIED_INSURANCE,
|
||||
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
|
||||
destinationPageData: routeData.VIN_LOOKUP,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.VIN_LOOKUP,
|
||||
pageName: routeData.VIN_LOOKUP.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
destinationPageData: routeData.ESTIMATE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
destinationPageData: routeData.VEHICLE_DAMAGE,
|
||||
params: {
|
||||
displayVehicleChangeAlert: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
destinationPageData: routeData.VEHICLE_DAMAGE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
destinationPageData: routeData.PART_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||
destinationPageData: routeData.VEHICLE_PARTS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
|
||||
destinationPageData: routeData.MOLDING_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationPageData: routeData.CAPABILITY_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_VIN_RETRY,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
destinationPageData: routeData.ESTIMATE,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.LICENSE_PLATE_LOOKUP,
|
||||
pageName: routeData.LICENSE_PLATE_LOOKUP.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
destinationPageData: routeData.ESTIMATE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
destinationPageData: routeData.VEHICLE_DAMAGE,
|
||||
params: {
|
||||
displayVehicleChangeAlert: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
destinationPageData: routeData.PART_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||
destinationPageData: routeData.VEHICLE_PARTS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
|
||||
destinationPageData: routeData.MOLDING_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationPageData: routeData.CAPABILITY_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_VIN_RETRY,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
destinationPageData: routeData.ESTIMATE,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.ADDRESS_LOOKUP,
|
||||
pageName: routeData.ADDRESS_LOOKUP.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
destinationPageData: routeData.ESTIMATE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
|
||||
destinationFmgPageValue: fmgPageValues.ADDRESS_VEHICLES,
|
||||
destinationPageData: routeData.ADDRESS_VEHICLES,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
destinationPageData: routeData.VEHICLE_DAMAGE,
|
||||
params: {
|
||||
displayVehicleChangeAlert: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
destinationPageData: routeData.PART_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||
destinationPageData: routeData.VEHICLE_PARTS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
|
||||
destinationPageData: routeData.MOLDING_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationPageData: routeData.CAPABILITY_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_VIN_RETRY,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
destinationPageData: routeData.ESTIMATE,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.ADDRESS_VEHICLES,
|
||||
pageName: routeData.ADDRESS_VEHICLES.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.ADDRESS_LOOKUP,
|
||||
destinationPageData: routeData.ADDRESS_LOOKUP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
destinationPageData: routeData.VEHICLE_DAMAGE,
|
||||
params: {
|
||||
displayVehicleChangeAlert: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
destinationPageData: routeData.PART_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||
destinationPageData: routeData.VEHICLE_PARTS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
|
||||
destinationPageData: routeData.MOLDING_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationPageData: routeData.CAPABILITY_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_VIN_RETRY,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
destinationPageData: routeData.ESTIMATE,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.ESTIMATE,
|
||||
pageName: routeData.ESTIMATE.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
destinationPageData: routeData.VEHICLE_DAMAGE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_MANUAL_VIN,
|
||||
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
|
||||
destinationPageData: routeData.VIN_LOOKUP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_LICENSE_PLATE,
|
||||
destinationFmgPageValue: fmgPageValues.LICENSE_PLATE_LOOKUP,
|
||||
destinationPageData: routeData.LICENSE_PLATE_LOOKUP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_HOME_ADDRESS,
|
||||
destinationFmgPageValue: fmgPageValues.ADDRESS_LOOKUP,
|
||||
destinationPageData: routeData.ADDRESS_LOOKUP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_NO_VIN,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
|
||||
destinationPageData: routeData.SERVICE_ZIP,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.SERVICE_ZIP,
|
||||
pageName: routeData.SERVICE_ZIP.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
destinationPageData: routeData.ESTIMATE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_SKIP_VIN,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
destinationPageData: routeData.VEHICLE_DAMAGE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
destinationPageData: routeData.PART_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||
destinationPageData: routeData.VEHICLE_PARTS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
|
||||
destinationPageData: routeData.MOLDING_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationPageData: routeData.CAPABILITY_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
pageName: routeData.PART_QUESTIONS.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
|
||||
destinationPageData: routeData.VIN_LOOKUP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
|
||||
destinationPageData: routeData.SERVICE_ZIP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||
destinationPageData: routeData.VEHICLE_PARTS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
|
||||
destinationPageData: routeData.MOLDING_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationPageData: routeData.CAPABILITY_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||
pageName: routeData.VEHICLE_PARTS.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
destinationPageData: routeData.PART_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
|
||||
destinationPageData: routeData.VIN_LOOKUP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
|
||||
destinationPageData: routeData.SERVICE_ZIP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
|
||||
destinationPageData: routeData.MOLDING_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationPageData: routeData.CAPABILITY_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
|
||||
pageName: routeData.MOLDING_QUESTIONS.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
|
||||
destinationPageData: routeData.VIN_LOOKUP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
|
||||
destinationPageData: routeData.SERVICE_ZIP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
destinationPageData: routeData.PART_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||
destinationPageData: routeData.VEHICLE_PARTS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationPageData: routeData.CAPABILITY_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
|
||||
pageName: routeData.CAPABILITY_QUESTIONS.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
|
||||
destinationPageData: routeData.VIN_LOOKUP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
|
||||
destinationPageData: routeData.SERVICE_ZIP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
destinationPageData: routeData.PART_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||
destinationPageData: routeData.VEHICLE_PARTS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
|
||||
destinationPageData: routeData.MOLDING_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.QUOTE,
|
||||
pageName: routeData.QUOTE.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
|
||||
destinationPageData: routeData.VIN_LOOKUP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
|
||||
destinationPageData: routeData.SERVICE_ZIP,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
destinationPageData: routeData.PART_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||
destinationPageData: routeData.VEHICLE_PARTS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
|
||||
destinationPageData: routeData.MOLDING_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationPageData: routeData.CAPABILITY_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CASH,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_LOCATION,
|
||||
destinationPageData: routeData.SERVICE_LOCATION,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_INSURANCE,
|
||||
destinationFmgPageValue: fmgPageValues.INSURANCE_COMPANY,
|
||||
destinationPageData: routeData.INSURANCE_COMPANY,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.INSURANCE_COMPANY,
|
||||
pageName: routeData.INSURANCE_COMPANY.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_PAY_ON_MY_OWN,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
params: {
|
||||
offer: "cash",
|
||||
},
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.INSURANCE_DETAILS,
|
||||
destinationPageData: routeData.INSURANCE_DETAILS,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.SERVICE_LOCATION,
|
||||
pageName: routeData.SERVICE_LOCATION.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.QUOTE,
|
||||
destinationPageData: routeData.QUOTE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.SCHEDULE,
|
||||
destinationPageData: routeData.SCHEDULE,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.SCHEDULE,
|
||||
pageName: routeData.SCHEDULE.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_LOCATION,
|
||||
destinationPageData: routeData.SERVICE_LOCATION,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.CUSTOMER_DETAILS,
|
||||
destinationPageData: routeData.CUSTOMER_DETAILS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_CHANGE_LOCATION,
|
||||
destinationFmgPageValue: fmgPageValues.SERVICE_LOCATION,
|
||||
destinationPageData: routeData.SERVICE_LOCATION,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.CUSTOMER_DETAILS,
|
||||
pageName: routeData.CUSTOMER_DETAILS.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.SCHEDULE,
|
||||
destinationPageData: routeData.SCHEDULE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.PAYMENT_METHOD,
|
||||
destinationPageData: routeData.PAYMENT_METHOD,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_PAY_NOW,
|
||||
destinationFmgPageValue: fmgPageValues.PAYMENT_METHOD,
|
||||
destinationPageData: routeData.PAYMENT_METHOD,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.PAYMENT_METHOD,
|
||||
pageName: routeData.PAYMENT_METHOD.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.CUSTOMER_DETAILS,
|
||||
destinationPageData: routeData.CUSTOMER_DETAILS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.CONFIRMATION,
|
||||
destinationPageData: routeData.CONFIRMATION,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_PAY_NOW,
|
||||
destinationFmgPageValue: fmgPageValues.PAYMENT,
|
||||
destinationPageData: routeData.PAYMENT,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_INSURANCE,
|
||||
destinationFmgPageValue: fmgPageValues.INSURANCE_COMPANY,
|
||||
destinationPageData: routeData.INSURANCE_COMPANY,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.PAYMENT,
|
||||
pageName: routeData.PAYMENT.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.PAYMENT_METHOD,
|
||||
destinationPageData: routeData.PAYMENT_METHOD,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.CONFIRMATION,
|
||||
destinationPageData: routeData.CONFIRMATION,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.PIA_ERROR,
|
||||
destinationPageData: routeData.PAYMENT_METHOD,
|
||||
params: {
|
||||
piaError: "true",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.PAYMENT_PIA_RETURN,
|
||||
pageName: routeData.PAYMENT_PIA_RETURN.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.PIA_ERROR,
|
||||
destinationFmgPageValue: fmgPageValues.PAYMENT_METHOD,
|
||||
destinationPageData: routeData.PAYMENT_METHOD,
|
||||
params: {
|
||||
piaError: "true",
|
||||
},
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.PIA_CC_ERROR,
|
||||
destinationFmgPageValue: fmgPageValues.PAYMENT,
|
||||
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,
|
||||
destinationFmgPageValue: fmgPageValues.CONFIRMATION,
|
||||
destinationPageData: routeData.CONFIRMATION,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
fmgPageValue: fmgPageValues.CONFIRMATION,
|
||||
pageName: routeData.CONFIRMATION.name,
|
||||
},
|
||||
// The destination page for return user does not matter. the router will invoke implicit navigation
|
||||
{
|
||||
fmgPageValue: fmgPageValues.RETURN_USER,
|
||||
pageName: routeData.RETURN_USER.name,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE,
|
||||
destinationPageData: routeData.LOAD_SESSION,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_RESTART,
|
||||
destinationPageData: routeData.RESTART,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -1,936 +1,41 @@
|
|||
// Supporting files
|
||||
import { routes } from "@/router/methods/routes";
|
||||
import { afterEach } from "@/router/methods/after-each";
|
||||
import { beforeEach } from "@/router/methods/before-each";
|
||||
import { bailout } from "@/router/methods/error";
|
||||
import {
|
||||
navigateWithoutSaving,
|
||||
navigateWithSaving,
|
||||
navigateWithPageData,
|
||||
navigateAndForceTopLevelNavigation,
|
||||
} from "@/router/methods/navigate";
|
||||
import { navigateToExternalUrl } from "@/router/methods/navigate-external";
|
||||
import { sendToReturnUser } from "@/router/methods/send-to-return-user";
|
||||
import { createWebHistory, createRouter } from "vue-router";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { storeMutations } from "../constants/store-mutations";
|
||||
import { sessionStorageKeyConstants } from "@/constants/session-storage.js";
|
||||
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
|
||||
import { routingTable } from "@/router/router-constants/routing-table.js";
|
||||
import { globalEvents, globalEventTypes } from "@/constants/events";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
import { getQuerystringParameter, buildQuerystringObject } from "@/helpers/querystring-helper";
|
||||
import { getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper";
|
||||
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
||||
import { fmgPageValues, funnelStartPageName } from "@/router/router-constants/fmgPage-values";
|
||||
import { externalParameterStatus } from "@/constants/external-parameters";
|
||||
|
||||
// Heritage integration
|
||||
import { isSavedSessionStillActive } from "@/helpers/heritage-integration/session-helper";
|
||||
import {
|
||||
updateOrCreateFunnelCookie,
|
||||
getFunnelCookie,
|
||||
updateSessionIdCookie,
|
||||
deleteFunnelCookie,
|
||||
getAffiliateCookies,
|
||||
setupAdvertiserTracking,
|
||||
} from "@/helpers/heritage-integration/cookie-helper";
|
||||
import { loadSessionIfPresent, saveSession } from "@/helpers/heritage-integration/order-helper";
|
||||
import {
|
||||
getPageToRouteExistingOrderTo,
|
||||
navigateToHeritageFunnel,
|
||||
getImplicitNavigation,
|
||||
} from "@/helpers/heritage-integration/navigation-helper";
|
||||
|
||||
import baseMixin from "@/mixins/base-mixin";
|
||||
import eventBus from "@/helpers/event-bus/event-bus";
|
||||
import store from "@/store";
|
||||
import analyticsMixin from "@/mixins/analytics-mixin";
|
||||
import { experimentTriggers } from "../constants/experiments";
|
||||
import { applicationConfig } from "../constants/application-config";
|
||||
import { shouldStripPromoQueryString } from "@/helpers/promotions-helper";
|
||||
import bailout from "@/layouts/bailout/bailout";
|
||||
import { nextTick } from "vue";
|
||||
import { getBoolFromString } from "@/helpers/boolean-helper";
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: "/bailout",
|
||||
name: "bailout",
|
||||
component: bailout,
|
||||
},
|
||||
{
|
||||
path: "/",
|
||||
name: "root",
|
||||
async beforeEnter(to, from, next) {
|
||||
// If we have no query string, or we don't have the FmgPage query string.
|
||||
try {
|
||||
log("------------- router index.js beforeEnter start -----------------");
|
||||
log(" --to: ", to);
|
||||
log(" --cookie: ", getFunnelCookie());
|
||||
log(` --from.redirectedFrom:>${JSON.stringify(from.redirectedFrom)}<`, "");
|
||||
|
||||
await analyticsMixin.methods.validateSession();
|
||||
var fromHeritage = getQuerystringParameter(queryStrings.FROM_HERITAGE);
|
||||
var offerQuote = getQuerystringParameter(queryStrings.OFFER_QUOTE);
|
||||
log(" --offerQuote: ", offerQuote);
|
||||
// after session is validated, remove the fromHeritage querystring if it exists so session expiration works
|
||||
if (to.query) {
|
||||
delete to.query[queryStrings.FROM_HERITAGE];
|
||||
}
|
||||
//remove offerquote querystring if it exists
|
||||
if (offerQuote) {
|
||||
delete to.query[queryStrings.OFFER_QUOTE];
|
||||
}
|
||||
|
||||
if (getFunnelCookie()?.SuppressConceptFunnel) {
|
||||
log(" --go to heritage suppressConceptFunnel: ");
|
||||
await navigateToHeritageFunnel({ shouldSaveSession: false });
|
||||
return next(false);
|
||||
}
|
||||
|
||||
// If the saved session has timed out, clear the session, execute 404 logic.
|
||||
if (getFunnelCookie() !== null && !isSavedSessionStillActive()) {
|
||||
log(" --save session timeout go to start");
|
||||
|
||||
const errorPayload = {
|
||||
cause: "expired session",
|
||||
currentPage: from?.query?.fmgPage,
|
||||
nextPage: to?.query?.fmgPage,
|
||||
};
|
||||
|
||||
await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
|
||||
deleteFunnelCookie();
|
||||
GoToFunnelStartOn404(next, errorPayload);
|
||||
return;
|
||||
}
|
||||
|
||||
const fromReturnUser = from?.name === fmgPageValues.RETURN_USER;
|
||||
const fromContentSite = getQuerystringParameter(queryStrings.START_TYPE) === "fmg";
|
||||
const toReturnUserPage = to.query?.fmgPage === fmgPageValues.RETURN_USER;
|
||||
log(" --fromReturnUser ", fromReturnUser);
|
||||
log(" --to.query.fmgPage ", to.query?.fmgPage);
|
||||
|
||||
// Intercept all navigation if a submitted order exists in storage
|
||||
if (
|
||||
window.sessionStorage.getItem(sessionStorageKeyConstants.SUBMITTED_STATE) !==
|
||||
null
|
||||
) {
|
||||
if (to.query.fmgPage !== funnelStartPageName) {
|
||||
to.query.fmgPage = fmgPageValues.CONFIRMATION;
|
||||
log(
|
||||
` --has ${sessionStorageKeyConstants.SUBMITTED_STATE} go to confirmation`
|
||||
);
|
||||
}
|
||||
}
|
||||
// On entering the funnel "fresh", read cookie information, decide what to do next.
|
||||
else if (from.redirectedFrom === undefined || fromReturnUser) {
|
||||
// if entering the funnel from the content site, check and see if there is already a vehicle year in vuex.
|
||||
// if so, send them to return-user page.
|
||||
if (
|
||||
fromContentSite &&
|
||||
!toReturnUserPage &&
|
||||
store.getters.order.vehicle?.year > 0
|
||||
) {
|
||||
log(" --from content site navigate to return user");
|
||||
var qso = {
|
||||
fmgPage: fmgPageValues.RETURN_USER,
|
||||
};
|
||||
|
||||
const newQueryString = buildQuerystringObject(qso, true);
|
||||
log(" -- returnUser add querystring: " + JSON.stringify(newQueryString));
|
||||
|
||||
router.push({
|
||||
path: "/",
|
||||
query: Object.assign({}, newQueryString),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// clear the saveSessionPromise - if it exists in the vuex store but a new instance was created
|
||||
// the saveSessionPromise will no longer point to a valid promise
|
||||
log(" --clear promise");
|
||||
baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
||||
|
||||
if (!to.query.fmgPage?.startsWith("payment")) {
|
||||
//payment pages used to return from safelitehop so exclude here
|
||||
// Remove the parameter after quote release
|
||||
|
||||
// for testing end to end locally, see if there is a referralNumber on the querystring
|
||||
// that could have changed in heritage and then stick it in the store and then update the cookie
|
||||
// so load-session runs properly. this can be removed when heritage goes away
|
||||
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();
|
||||
}
|
||||
|
||||
//Affiliate Cookies
|
||||
const affiliateCookies = getAffiliateCookies();
|
||||
if (affiliateCookies != null && affiliateCookies.length > 0) {
|
||||
store.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies);
|
||||
}
|
||||
setupAdvertiserTracking();
|
||||
log(" --load session start");
|
||||
const loadSessionResponse = await loadSessionIfPresent(
|
||||
to.query.isInsurance != null
|
||||
? to.query.isInsurance == "true"
|
||||
? true
|
||||
: false
|
||||
: null,
|
||||
to.query.fmgPage
|
||||
);
|
||||
log(" --load session end");
|
||||
|
||||
//Update external parameter state but not when returning from heritage
|
||||
if (!to.query.fmgPage?.startsWith("service-location") && !fromReturnUser) {
|
||||
updateExternalParameterState();
|
||||
}
|
||||
|
||||
//Update CASH tab when return from heritage and have offerQuote param
|
||||
if (offerQuote === "true" && fromHeritage === "true") {
|
||||
store.commit(storeMutations.UPDATE_IS_INSURANCE, false);
|
||||
}
|
||||
|
||||
// clear part related state because heritage selected a new vehicle
|
||||
if (
|
||||
to.query.fmgPage === fmgPageValues.VEHICLE &&
|
||||
getBoolFromString(getFunnelCookie()?.HasDelayedClaimRegistration) &&
|
||||
!fromReturnUser
|
||||
) {
|
||||
store.commit(storeMutations.RESET_GLASS_PARTS_STATE);
|
||||
}
|
||||
|
||||
// if coming from the return user page, clear the destination page so implicit navigation runs
|
||||
log(" --to.query ", JSON.stringify(to.query));
|
||||
if (fromReturnUser && to.query) {
|
||||
log(" --clear to.query");
|
||||
delete to.query[queryStrings.FMG_PAGE];
|
||||
|
||||
//to.query[queryStrings.FMG_PAGE] = "";
|
||||
log(" --to.query cleared ", JSON.stringify(to.query));
|
||||
}
|
||||
|
||||
const pageToRedirectTo = await getPageToRouteExistingOrderTo(to);
|
||||
log(" --pageToRedirectTo ", JSON.stringify(pageToRedirectTo));
|
||||
|
||||
// This logic may determine that the user should be sent to heritage -- if so, do that here.
|
||||
if (pageToRedirectTo === fmgPageValues.HERITAGE) {
|
||||
// prettier-ignore
|
||||
log(" --go to heritage pageToRedirectTo ", JSON.stringify(pageToRedirectTo));
|
||||
await navigateToHeritageFunnel({ shouldSaveSession: false });
|
||||
return next(false);
|
||||
}
|
||||
|
||||
// Assign our fmgPage so it will load normally like the other pages.
|
||||
to.query.fmgPage = pageToRedirectTo;
|
||||
log(" --assign to: ", JSON.stringify(pageToRedirectTo));
|
||||
}
|
||||
}
|
||||
|
||||
// Reroute around pages that should not be available.
|
||||
|
||||
// Exception 1: Integrated Users should not see vehicle or quote pages.
|
||||
if (
|
||||
store.getters.payment?.insuranceCoverage?.isVerified ||
|
||||
store.getters.order?.referralNumber?.length === 6
|
||||
) {
|
||||
if (to.query.fmgPage === fmgPageValues.VEHICLE) {
|
||||
to.query.fmgPage = fmgPageValues.VEHICLE_DAMAGE;
|
||||
} else if (
|
||||
to.query.fmgPage === fmgPageValues.QUOTE ||
|
||||
to.query.fmgPage === fmgPageValues.INSURANCE_COMPANY
|
||||
) {
|
||||
log(" --block quote page for integrated clients - go to heritage");
|
||||
// Push to heritage if going to quote & integrated.
|
||||
await navigateToHeritageFunnel({ shouldSaveSession: false });
|
||||
return next(false);
|
||||
}
|
||||
}
|
||||
|
||||
await runExperiments(to.query.fmgPage);
|
||||
|
||||
//Affiliate Cookies
|
||||
const affiliateCookies = getAffiliateCookies();
|
||||
if (affiliateCookies != null && affiliateCookies.length > 0) {
|
||||
store.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies);
|
||||
}
|
||||
setupAdvertiserTracking();
|
||||
// Process funnel cookie.
|
||||
updateOrCreateFunnelCookie();
|
||||
|
||||
// If we already have our route, go to it.
|
||||
if (router.hasRoute(to.query.fmgPage)) {
|
||||
// Since our route is already in scope, we can grab the component from it and call the arePagePrerequisitesValid function.
|
||||
let component = router
|
||||
.getRoutes()
|
||||
.filter((x) => x.name === to.query.fmgPage)[0].components;
|
||||
|
||||
// If the component hasn't been loaded fully, load it before we check prerequisites.
|
||||
if (component.default.methods === undefined) {
|
||||
component = await component.default();
|
||||
}
|
||||
|
||||
if (!arePagePrerequisitesValid(component)) {
|
||||
console.log("Page prereq error: " + component.default.name);
|
||||
|
||||
if (to.query.fmgPage === fmgPageValues.PAYMENT) {
|
||||
await store.getters.applicationUser.saveSessionPromise;
|
||||
window.location = applicationConfig.PIA_CANCEL_URL;
|
||||
return;
|
||||
}
|
||||
|
||||
const errorPayload = {
|
||||
cause: "invalid page prerequisites for page",
|
||||
currentPage: from?.query?.fmgPage,
|
||||
nextPage: to?.query?.fmgPage,
|
||||
};
|
||||
|
||||
GoToFunnelStartOn404(next, errorPayload);
|
||||
return;
|
||||
}
|
||||
|
||||
log(" --has route:", to.query.fmgPage);
|
||||
return next({ name: to.query.fmgPage, query: to.query, params: to.params });
|
||||
}
|
||||
|
||||
if (!isExistingFmgPageName(to.query.fmgPage)) {
|
||||
const errorPayload = {
|
||||
cause: "invalid page name",
|
||||
currentPage: from?.query?.fmgPage,
|
||||
nextPage: to?.query?.fmgPage,
|
||||
};
|
||||
|
||||
GoToFunnelStartOn404(next, errorPayload);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get route info for the given url. Names will have a 1:1 relationship with names in the Cms.
|
||||
const routeData = GetRouteInfoFromPageName(to.query.fmgPage);
|
||||
log("--routeData:", routeData);
|
||||
|
||||
// Add our dynamic route.
|
||||
router.addRoute({
|
||||
path: routeData[0].path, // Always the same path, because we control it with query strings.
|
||||
name: routeData[0].name,
|
||||
component: routeData[0].component,
|
||||
});
|
||||
|
||||
// Call the next components arePagePrerequisitesValid method before load.
|
||||
// If it returns false, use the 404 logic.
|
||||
const nextComponent = await router
|
||||
.getRoutes()
|
||||
.filter((x) => x.name === routeData[0].name)[0]
|
||||
.components.default();
|
||||
|
||||
if (!arePagePrerequisitesValid(nextComponent)) {
|
||||
// prettier-ignore
|
||||
console.log("Page Prereqs not valid for next component: " + nextComponent.default.name);
|
||||
|
||||
const errorPayload = {
|
||||
cause: "invalid page prerequisites for page",
|
||||
currentPage: from?.query?.fmgPage,
|
||||
nextPage: to?.query?.fmgPage,
|
||||
};
|
||||
|
||||
GoToFunnelStartOn404(next, errorPayload);
|
||||
return;
|
||||
}
|
||||
|
||||
log("------------- router index.js beforeEnter end -----------------");
|
||||
|
||||
// Assign current query string parameters, as well as our fmgPage one.
|
||||
next({
|
||||
name: routeData[0].name,
|
||||
query: Object.assign(to.query, { fmgPage: routeData[0].name }),
|
||||
params: to.params,
|
||||
});
|
||||
} catch (error) {
|
||||
global.$logger.logError(`Routing ${error.stack}`);
|
||||
|
||||
if (to.query?.fmgPage === funnelStartPageName) {
|
||||
deleteFunnelCookie();
|
||||
await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
|
||||
}
|
||||
|
||||
console.log(new Date() + " Exception in beforeEnter:" + JSON.stringify(error));
|
||||
|
||||
// If we don't have a route, go to our 404 page.
|
||||
const errorPayload = {
|
||||
cause: "uncaught error in beforeEnter",
|
||||
currentPage: from?.query?.fmgPage,
|
||||
nextPage: to?.query?.fmgPage,
|
||||
fullError: error,
|
||||
errorStack: error?.stack,
|
||||
};
|
||||
|
||||
GoToFunnelStartOn404(next, errorPayload);
|
||||
return;
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
import { ROUTE_PREFIX_FULL } from "@/router/constants/route-prefix";
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory("/fmg/"),
|
||||
history: createWebHistory(ROUTE_PREFIX_FULL),
|
||||
routes,
|
||||
//Cause "page" to begin at the top when route chanages.
|
||||
// Scroll to top on navigation.
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
// always scroll to top
|
||||
return { top: 0 };
|
||||
},
|
||||
});
|
||||
|
||||
//---------------------------------------------------------- Router Functions ----------------------------------------------------------
|
||||
// Set guards
|
||||
router.afterEach(async (to, from) => afterEach(to, from));
|
||||
router.beforeEach(async (to, from) => beforeEach(to, from));
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
log("------------- router index.js beforeEach start -----------------");
|
||||
// set lastNavigationPage here to capture state before API calls for analytics.
|
||||
// use current page url query string name when to.name is "root" (due to unresolved navigation in beforeEach)
|
||||
router.lastNavigationPage = to.name == "root" ? analyticsMixin.methods.getPageName() : to.name;
|
||||
// Bind methods for external use
|
||||
router.navigateWithSaving = navigateWithSaving;
|
||||
router.navigateWithoutSaving = navigateWithoutSaving;
|
||||
router.navigateWithPageData = navigateWithPageData;
|
||||
router.navigateAndForceTopLevelNavigation = navigateAndForceTopLevelNavigation;
|
||||
|
||||
const fromQueryPage = from.query?.fmgPage;
|
||||
if (fromQueryPage === undefined) {
|
||||
showFmgLoadingModal(true);
|
||||
}
|
||||
router.bailout = bailout;
|
||||
|
||||
const toQueryPage = to.query?.fmgPage;
|
||||
const notToPIAReturn = toQueryPage != fmgPageValues.PAYMENT_PIA_RETURN;
|
||||
const isInIframe = window !== window.top;
|
||||
router.navigateToExternalUrl = navigateToExternalUrl;
|
||||
|
||||
if (store.getters.externalParameterState?.isExternalParameter) {
|
||||
// Check if alert event is on the bus
|
||||
const alertEvent = eventBus.readEventFromBus(
|
||||
globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.PAGE_NOT_FOUND
|
||||
);
|
||||
//Uknown alerts most likely were added by a failed api call in global-methods
|
||||
const unknownAlertEvent = eventBus.readEventFromBus(
|
||||
globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.UNKNOWN_ERROR
|
||||
);
|
||||
// If alert event is on the bus, then display the alert
|
||||
if (alertEvent !== undefined || unknownAlertEvent !== undefined) {
|
||||
store.commit(
|
||||
storeMutations.UPDATE_IS_EXTERNAL_PARAMETER,
|
||||
externalParameterStatus.INACTIVE
|
||||
);
|
||||
}
|
||||
}
|
||||
// fromPaymentToConfirmation workaround for navigating from an iframe but
|
||||
// isInIframe evaluates to false for some reason when navigating from payment to confirmation
|
||||
const fromPaymentToConfirmation =
|
||||
fromQueryPage === fmgPageValues.PAYMENT && toQueryPage === fmgPageValues.CONFIRMATION;
|
||||
|
||||
if ((isInIframe && notToPIAReturn) || fromPaymentToConfirmation) {
|
||||
const newUrl = `${window.top.location.origin}${to.href}`;
|
||||
window.top.location.href = newUrl;
|
||||
next(false);
|
||||
|
||||
// Refresh page if navigating to self to prevent locking.
|
||||
// For now only carved out for vehicle; all modals are opened through anchor tags at the moment,
|
||||
// which also self navigate, but relied on the page remaining the same on self-navigation.
|
||||
} else if (toQueryPage === fromQueryPage && toQueryPage === getRedirectedStartPage()) {
|
||||
router.go(0);
|
||||
next(false);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
log("------------- router index.js beforeEach end -----------------");
|
||||
});
|
||||
|
||||
router.afterEach(async (to, from) => {
|
||||
// Update lastPageVisited in the store
|
||||
store.commit(storeMutations.UPDATE_LAST_PAGE_VISITED, to.name);
|
||||
|
||||
// If saving on navigation is requested, check for saved SessionId or EmailAddress to determine if saving is appropriate
|
||||
if (getBoolFromString(window.history.state.isSavingNavigation)) {
|
||||
if (
|
||||
store.getters.applicationUser.savedSessionId ||
|
||||
store.getters.order.customer?.emailAddress
|
||||
) {
|
||||
await saveSession({ pageNameToLog: to.query.fmgPage });
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
if (to.query.fmgPage == fmgPageValues.CONFIRMATION) {
|
||||
//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();
|
||||
}
|
||||
});
|
||||
|
||||
router.navigateWithoutSaving = (
|
||||
scenario,
|
||||
currentRoute,
|
||||
optionalQuery = {},
|
||||
optionalParams = {},
|
||||
optionalPageData = {}
|
||||
) => {
|
||||
navigate(scenario, currentRoute, false, optionalQuery, optionalParams, optionalPageData);
|
||||
};
|
||||
|
||||
router.navigateWithSaving = (
|
||||
scenario,
|
||||
currentRoute,
|
||||
optionalQuery = {},
|
||||
optionalParams = {},
|
||||
optionalPageData = {}
|
||||
) => {
|
||||
navigate(scenario, currentRoute, true, optionalQuery, optionalParams, optionalPageData);
|
||||
};
|
||||
|
||||
router.navigateToExternalUrl = (url, optionalQuery = {}) => {
|
||||
log("------------- router navigateToExternalUrl -----------------");
|
||||
log("url:", url);
|
||||
navigateToUrl(url, optionalQuery);
|
||||
};
|
||||
|
||||
router.navigateError = (errorPayload = null) => {
|
||||
DisplayPageError(errorPayload);
|
||||
};
|
||||
|
||||
//Use this navigation when you need to call next() explicitly. beforeRouteEnter is a good example.
|
||||
router.overrideNavigation = (
|
||||
scenario,
|
||||
currentRoute,
|
||||
next,
|
||||
isSavingNavigation,
|
||||
optionalQuery = {},
|
||||
optionalParams = {},
|
||||
optionalPageData
|
||||
) => {
|
||||
log("------------- router overrideNavigation -----------------");
|
||||
log("scenario:", scenario);
|
||||
log("currentRoute:", currentRoute);
|
||||
log("isSavingNavigation:", isSavingNavigation);
|
||||
log("optionalQuery:", optionalQuery);
|
||||
log("optionalParams:", optionalParams);
|
||||
log("optionalPageData:", optionalPageData);
|
||||
navigate(
|
||||
scenario,
|
||||
currentRoute,
|
||||
isSavingNavigation,
|
||||
optionalQuery,
|
||||
optionalParams,
|
||||
optionalPageData
|
||||
);
|
||||
next();
|
||||
};
|
||||
|
||||
router.getNextPage = () => nextPageName;
|
||||
|
||||
// PRIVATE VARIABLES
|
||||
|
||||
var nextPageName;
|
||||
|
||||
// PRIVATE FUNCTIONS
|
||||
|
||||
// Navigate to the next route, depending on the scenario.
|
||||
async function navigate(
|
||||
scenario,
|
||||
currentRoute,
|
||||
isSavingNavigation,
|
||||
optionalQuery = {},
|
||||
optionalParams = {},
|
||||
optionalPageData = {}
|
||||
) {
|
||||
if (!scenario) {
|
||||
console.error("No scenario provided. Please review the routing table.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Match our maps up and navigate if we have a destination.
|
||||
const matchingScenarioMap = getNavigationMap(scenario, currentRoute);
|
||||
const destinationFmgPageValue = matchingScenarioMap.destinationFmgPageValue;
|
||||
|
||||
if (destinationFmgPageValue !== undefined) {
|
||||
// We're always pushing the same path, just changing query strings. Make sure our optional query strings get combined with our fmgPage one.
|
||||
|
||||
nextPageName = destinationFmgPageValue;
|
||||
|
||||
// Update page data to the store for next page if provided. Otherwise, keep existing page data or set to empty object
|
||||
const existingPageDataForPage = store.getters.pageData(destinationFmgPageValue);
|
||||
baseMixin.methods.savePageDataToStore(
|
||||
destinationFmgPageValue,
|
||||
Object.keys(optionalPageData).length > 0
|
||||
? optionalPageData
|
||||
: (existingPageDataForPage ?? {})
|
||||
);
|
||||
|
||||
optionalParams.isSavingNavigation = isSavingNavigation;
|
||||
|
||||
// add querystring params to the route. if they are already in the store then no need to add them
|
||||
var queryStringsObject = {
|
||||
fmgPage: destinationFmgPageValue,
|
||||
};
|
||||
|
||||
const hasZip = getQuerystringParameter(queryStrings.ZIP_CODE);
|
||||
const zip = getQuerystringParameter(queryStrings.ZIP_CODE);
|
||||
const promo = getQuerystringParameter(queryStrings.PROMO);
|
||||
const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR);
|
||||
const logQs = getQuerystringParameter(queryStrings.LOG);
|
||||
baseMixin.methods.dispatchStoreAction(storeActions.SAVE_LOGGING_OPTION, logQs, false);
|
||||
|
||||
log("------------- router index.js navigate start -----------------");
|
||||
log(" --scenario: ", scenario);
|
||||
log(" --isSavingNavigation: ", isSavingNavigation);
|
||||
log(" --optionalQuery: ", optionalQuery);
|
||||
log(" --optionalParams: ", optionalParams);
|
||||
log(" --optionalPageData: ", optionalPageData);
|
||||
log(" --nextPageName: ", nextPageName);
|
||||
|
||||
if (
|
||||
hasZip &&
|
||||
(store.getters.order.serviceLocation.zipCode === undefined ||
|
||||
store.getters.order.serviceLocation.zipCode == null) &&
|
||||
(store.getters.order.vehicle.registration.zipCode === undefined ||
|
||||
store.getters.order.vehicle.registration.zipCode == null)
|
||||
) {
|
||||
queryStringsObject[queryStrings.ZIP_CODE] = zip;
|
||||
}
|
||||
|
||||
if (promo && !shouldStripPromoQueryString(currentRoute.query.fmgPage)) {
|
||||
queryStringsObject[queryStrings.PROMO] = promo;
|
||||
}
|
||||
|
||||
if (pageError) {
|
||||
queryStringsObject[queryStrings.PAGE_ERROR] = pageError;
|
||||
}
|
||||
|
||||
if (logQs) {
|
||||
queryStringsObject[queryStrings.LOG] = logQs;
|
||||
}
|
||||
|
||||
log(" querystrings: ", queryStringsObject);
|
||||
log("------------- router index.js navigate end -----------------");
|
||||
|
||||
router.push({
|
||||
name: "root",
|
||||
query: Object.assign(optionalQuery, queryStringsObject),
|
||||
state: optionalParams,
|
||||
});
|
||||
} else if (matchingScenarioMap.destinationUrl !== undefined) {
|
||||
navigateToUrl(matchingScenarioMap.destinationUrl, optionalQuery);
|
||||
}
|
||||
}
|
||||
|
||||
// Get navigation map depending on the scenario and the current 'page' you're on.
|
||||
function getNavigationMap(scenario, currentRoute) {
|
||||
const fmgPageValue = currentRoute.query.fmgPage;
|
||||
log("------------- router index.js getNavigationMap start -----------------");
|
||||
log("fmgPage: " + fmgPageValue + " scenario: " + scenario, "");
|
||||
log("------------- router index.js getNavigationMap end -----------------");
|
||||
const matchedQueryValue = routingTable(store)
|
||||
.filter(
|
||||
(item) =>
|
||||
item.fmgPageValue === fmgPageValue &&
|
||||
item.maps.filter((map) => map.scenario === scenario).length > 0
|
||||
)
|
||||
.map((m) => m.maps.filter((map) => map.scenario === scenario))[0]
|
||||
.filter((x) => x.filter === true || x.filter === undefined);
|
||||
|
||||
return matchedQueryValue[0];
|
||||
}
|
||||
|
||||
function log(message, data) {
|
||||
const log = getQuerystringParameter(queryStrings.LOG);
|
||||
baseMixin.methods.dispatchStoreAction(storeActions.SAVE_LOGGING_OPTION, log, false);
|
||||
|
||||
data = data ?? "";
|
||||
const outData = typeof data === "object" ? JSON.stringify(data) : data;
|
||||
|
||||
if (log === "true" || store.getters.applicationUser.loggingOption) {
|
||||
console.log(new Date() + message + outData);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------- Private Functions ----------------------------------------------------------
|
||||
|
||||
// Navigate to an external url.
|
||||
function navigateToUrl(url, optionalQuery = {}) {
|
||||
// possibly show some loading screen in the future here.
|
||||
var externalUrl = new URL(url);
|
||||
|
||||
for (const queryKey in optionalQuery) {
|
||||
externalUrl.searchParams.append(queryKey, optionalQuery[queryKey]);
|
||||
}
|
||||
|
||||
window.location.assign(externalUrl);
|
||||
}
|
||||
|
||||
// Get route information by page name.
|
||||
// This will no longer reach out to the Cms. There is a 1:1 relationship between page names and route names and layouts.
|
||||
function GetRouteInfoFromPageName(pageName) {
|
||||
// check if pagename is a valid route/component
|
||||
if (!isExistingFmgPageName(pageName)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const routeData = [
|
||||
{
|
||||
path: "/",
|
||||
name: pageName,
|
||||
component: lazyLoadComponent(pageName),
|
||||
},
|
||||
];
|
||||
|
||||
return routeData;
|
||||
}
|
||||
|
||||
// Go to our start page on a 404.
|
||||
function GoToFunnelStartOn404(next, errorPayload = null) {
|
||||
if (errorPayload !== null) {
|
||||
errorPayload.type = "GoToFunnelStartOn404";
|
||||
analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload);
|
||||
|
||||
console.log(
|
||||
"%cGoToFunnelStartOn404()... errorPayload",
|
||||
"color: white; background-color: blue; padding: 5px;",
|
||||
errorPayload
|
||||
);
|
||||
}
|
||||
|
||||
// Put item on the bus
|
||||
eventBus.addEventToBus(
|
||||
globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.PAGE_NOT_FOUND,
|
||||
{
|
||||
isDismissible: true,
|
||||
messageCopy: "You can get a quote by starting on this page.",
|
||||
messageHeadline: "We're sorry, something went wrong.",
|
||||
type: globalEventTypes.Danger,
|
||||
}
|
||||
);
|
||||
|
||||
next({
|
||||
path: "/",
|
||||
query: { fmgPage: funnelStartPageName },
|
||||
});
|
||||
}
|
||||
|
||||
async function DisplayPageError(errorPayload = null) {
|
||||
console.log("%c running DisplayPageError()... ", "font-size: 20px; color: purple;");
|
||||
|
||||
if (errorPayload !== null) {
|
||||
errorPayload.type = "DisplayPageError";
|
||||
analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload);
|
||||
} else {
|
||||
// very cautiously to avoid additional errors:
|
||||
var currentPage = "";
|
||||
try {
|
||||
currentPage = getQuerystringParameter(queryStrings.FMG_PAGE);
|
||||
} catch (e) {
|
||||
// pass
|
||||
}
|
||||
errorPayload = {
|
||||
type: "DisplayPageError",
|
||||
cause: "Unknown page error",
|
||||
currentPage: currentPage,
|
||||
};
|
||||
analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload);
|
||||
}
|
||||
|
||||
// Put item on the bus
|
||||
eventBus.addEventToBus(
|
||||
globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.UNKNOWN_ERROR,
|
||||
{
|
||||
isDismissible: true,
|
||||
messageCopy: "",
|
||||
messageHeadline: "We're sorry, something went wrong.",
|
||||
type: globalEventTypes.Danger,
|
||||
}
|
||||
);
|
||||
if (
|
||||
store.getters.externalParameterState?.isExternalParameter == externalParameterStatus.ACTIVE
|
||||
) {
|
||||
store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, externalParameterStatus.INACTIVE);
|
||||
}
|
||||
baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
||||
const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR);
|
||||
|
||||
// we use the pageError querystring as a counter to how many times a user has experienced an error and been routed here.
|
||||
// once they receive more than 1 pageerrors, we'll reset their state to hopefully correct any issues they may be having.
|
||||
var navPage = fmgPageValues.VEHICLE;
|
||||
if (store.getters.payment?.insuranceCoverage?.isVerified) {
|
||||
navPage = fmgPageValues.VEHICLE_DAMAGE;
|
||||
}
|
||||
|
||||
if (pageError) {
|
||||
var errorCount = Number(pageError);
|
||||
if (errorCount > 1) {
|
||||
deleteFunnelCookie();
|
||||
await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
|
||||
|
||||
router.push({
|
||||
path: "/",
|
||||
query: { fmgPage: navPage },
|
||||
});
|
||||
} else {
|
||||
errorCount++;
|
||||
router.push({
|
||||
path: "/",
|
||||
query: { fmgPage: navPage, pageError: errorCount },
|
||||
});
|
||||
}
|
||||
} else {
|
||||
router.push({
|
||||
path: "/",
|
||||
query: { fmgPage: navPage, pageError: "1" },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function isExistingFmgPageName(pageName) {
|
||||
const names = Object.values(fmgPageValues);
|
||||
|
||||
return names.some((name) => name === pageName);
|
||||
}
|
||||
|
||||
// Checks arePagePrerequisitesValid on the component passed in.
|
||||
function arePagePrerequisitesValid(component) {
|
||||
return component.default.methods.arePagePrerequisitesValid();
|
||||
}
|
||||
|
||||
// Run SiteEntry and PageEntry triggers for experiments
|
||||
async function runExperiments(nextPage) {
|
||||
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,
|
||||
},
|
||||
nextPage
|
||||
);
|
||||
}
|
||||
|
||||
await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
storeActions.RUN_EXPERIMENTS_FOR_TRIGGER,
|
||||
{
|
||||
deviceId: getDeviceIdValue(),
|
||||
triggerEvent: experimentTriggers.PAGE_ENTRY,
|
||||
triggerValue: nextPage,
|
||||
},
|
||||
nextPage
|
||||
);
|
||||
}
|
||||
|
||||
function getRedirectedStartPage() {
|
||||
if (store.getters.payment?.insuranceCoverage?.isVerified) {
|
||||
return fmgPageValues.VEHICLE_DAMAGE;
|
||||
} else {
|
||||
return funnelStartPageName;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
router.sendToReturnUser = sendToReturnUser;
|
||||
|
||||
export default router;
|
||||
|
|
|
|||
12
src/router/methods/after-each.js
Normal file
12
src/router/methods/after-each.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import analyticsMixin from "@/mixins/analytics-mixin";
|
||||
|
||||
export async function afterEach(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();
|
||||
}
|
||||
106
src/router/methods/before-each.js
Normal file
106
src/router/methods/before-each.js
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import { sessionStorageKeyConstants } from "@/constants/session-storage";
|
||||
import {
|
||||
getFunnelCookie,
|
||||
updateOrCreateFunnelCookie,
|
||||
} from "@/helpers/heritage-integration/cookie-helper";
|
||||
import { isSavedSessionStillActive } from "@/helpers/heritage-integration/session-helper";
|
||||
import analyticsMixin from "@/mixins/analytics-mixin";
|
||||
import { routeData, FUNNEL_START_PAGE } from "@/router/constants/routes";
|
||||
import { runExperiments } from "@/router/methods/helpers/run-experiments";
|
||||
|
||||
import { bailout } from "@/router/methods/error";
|
||||
import { checkPagePrerequisites } from "@/router/methods/page-prerequisites";
|
||||
import { checkLogParam } from "@/helpers/debug-log-helper";
|
||||
import { debugLog } from "@/helpers/debug-log-helper";
|
||||
import { handleHeritageReturn } from "@/router/methods/helpers/handle-heritage-return";
|
||||
|
||||
export async function beforeEach(to, from) {
|
||||
try {
|
||||
await analyticsMixin.methods.validateSession();
|
||||
|
||||
// prettier-ignore
|
||||
{
|
||||
debugLog(`--- before-each.js ${from?.name} start ---`);
|
||||
debugLog(" funnel cookie init: ", getFunnelCookie());
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Special logic when returning from insurance flow.
|
||||
await handleHeritageReturn(to, from);
|
||||
|
||||
// prettier-ignore
|
||||
{
|
||||
debugLog(`--- before-each.js ${from?.name} mid ---`);
|
||||
debugLog(" funnel cookie after load: ", getFunnelCookie());
|
||||
}
|
||||
|
||||
// Process funnel cookie.
|
||||
updateOrCreateFunnelCookie();
|
||||
|
||||
// prettier-ignore
|
||||
{
|
||||
debugLog(`--- before-each.js ${from?.name} end ---`);
|
||||
debugLog(" funnel cookie after update: ", getFunnelCookie());
|
||||
}
|
||||
|
||||
// Update if logging is enabled.
|
||||
checkLogParam();
|
||||
|
||||
// Ensure page-prerequisites are fulfilled
|
||||
const arePagePrerequisitesValid = await checkPagePrerequisites(to.name);
|
||||
|
||||
if (!arePagePrerequisitesValid) {
|
||||
const errorPayload = {
|
||||
cause: "invalid page prerequisites for page",
|
||||
currentPage: from?.name,
|
||||
nextPage: to?.name,
|
||||
};
|
||||
|
||||
bailout(errorPayload);
|
||||
return;
|
||||
}
|
||||
|
||||
await runExperiments(to.name);
|
||||
|
||||
// prettier-ignore
|
||||
{
|
||||
debugLog("--- before-each.js end ---");
|
||||
}
|
||||
} catch (error) {
|
||||
const errorPayload = {
|
||||
cause: "Uncaught exception in `beforeEach`.",
|
||||
currentPage: from?.name,
|
||||
nextPage: to?.name,
|
||||
};
|
||||
|
||||
console.log(error);
|
||||
|
||||
bailout(errorPayload);
|
||||
return;
|
||||
}
|
||||
}
|
||||
17
src/router/methods/error.js
Normal file
17
src/router/methods/error.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import analyticsMixin from "@/mixins/analytics-mixin";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
import router from "@/router";
|
||||
|
||||
export async function bailout(errorPayload, forceRestart = false) {
|
||||
analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload);
|
||||
|
||||
if (forceRestart) {
|
||||
router.push({
|
||||
name: routeData.RESTART.name,
|
||||
});
|
||||
} else {
|
||||
router.push({
|
||||
name: routeData.ERROR.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
5
src/router/methods/get-route.js
Normal file
5
src/router/methods/get-route.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import router from "@/router";
|
||||
|
||||
export function getRoute(pageName) {
|
||||
return router.getRoutes().find((r) => r.name === pageName);
|
||||
}
|
||||
27
src/router/methods/helpers/build-manual-url.js
Normal file
27
src/router/methods/helpers/build-manual-url.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { ROUTE_PREFIX_TRIMMED } from "@/router/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;
|
||||
}
|
||||
|
||||
export 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 "";
|
||||
}
|
||||
18
src/router/methods/helpers/consume-referral-info.js
Normal file
18
src/router/methods/helpers/consume-referral-info.js
Normal 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();
|
||||
}
|
||||
}
|
||||
39
src/router/methods/helpers/create-route.js
Normal file
39
src/router/methods/helpers/create-route.js
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import { lazyLoadComponent } from "@/router/methods/helpers/lazy-load-component";
|
||||
import { routeData } from "@/router/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,
|
||||
};
|
||||
}
|
||||
18
src/router/methods/helpers/get-destination.js
Normal file
18
src/router/methods/helpers/get-destination.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { routingTable } from "@/router/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,
|
||||
};
|
||||
}
|
||||
16
src/router/methods/helpers/handle-heritage-return.js
Normal file
16
src/router/methods/helpers/handle-heritage-return.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { queryStrings } from "@/constants/query-strings";
|
||||
import { consumeReferralQuerystrings } from "@/router/methods/helpers/consume-referral-info";
|
||||
import { loadSessionIfPresent } from "@/helpers/heritage-integration/order-helper";
|
||||
import { routeData } from "@/router/constants/routes";
|
||||
|
||||
export async function handleHeritageReturn(to, from) {
|
||||
const fromHeritageFlag = to.query[queryStrings.FROM_HERITAGE];
|
||||
|
||||
if (fromHeritageFlag) {
|
||||
// Get new referral info from querystring in case passed there.
|
||||
await consumeReferralQuerystrings();
|
||||
|
||||
// load session with new cookie
|
||||
await loadSessionIfPresent(true, routeData.SERVICE_LOCATION.name);
|
||||
}
|
||||
}
|
||||
121
src/router/methods/helpers/initialize-from-querystrings.js
Normal file
121
src/router/methods/helpers/initialize-from-querystrings.js
Normal 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
export function lazyLoadComponent(componentName) {
|
||||
return () => import(`@/layouts/${componentName}/${componentName}.vue`); // /src/layouts/folder/component.vue
|
||||
return () => import(`@/layouts/${componentName}/${componentName}.vue`);
|
||||
}
|
||||
58
src/router/methods/helpers/querystring-stash.js
Normal file
58
src/router/methods/helpers/querystring-stash.js
Normal 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 = [];
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue