Merge branch 'develop' into bug/chloeherd/analytics-mismatch
This commit is contained in:
commit
5c38498a23
36 changed files with 1157 additions and 988 deletions
|
|
@ -2,6 +2,7 @@ const queryStrings = {
|
||||||
FMG_PAGE: "fmgPage",
|
FMG_PAGE: "fmgPage",
|
||||||
START_TYPE: "start_type",
|
START_TYPE: "start_type",
|
||||||
ZIP_CODE: "zipcode",
|
ZIP_CODE: "zipcode",
|
||||||
|
PROMO: "promo",
|
||||||
};
|
};
|
||||||
|
|
||||||
export { queryStrings };
|
export { queryStrings };
|
||||||
|
|
|
||||||
|
|
@ -192,9 +192,9 @@ export default {
|
||||||
classes = "d-flex flex-row p-0";
|
classes = "d-flex flex-row p-0";
|
||||||
break;
|
break;
|
||||||
case "listCard":
|
case "listCard":
|
||||||
classes = "row g-2 justify-content-center mb-1";
|
classes = "row g-2 g-md-5 justify-content-center mb-1";
|
||||||
if (this.isWide) {
|
if (this.isWide) {
|
||||||
classes += " flex-column";
|
classes += "flex-column";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "radio":
|
case "radio":
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,10 @@ export default {
|
||||||
&:focus {
|
&:focus {
|
||||||
box-shadow: 0 0 0 2.5px $blue;
|
box-shadow: 0 0 0 2.5px $blue;
|
||||||
}
|
}
|
||||||
|
&:checked[type="checkbox"] {
|
||||||
|
background-color: $blue;
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23ffffff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
.form-check-input {
|
.form-check-input {
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@
|
||||||
:answerKey="questionsDatum.answerKey"
|
:answerKey="questionsDatum.answerKey"
|
||||||
:validationRules="validationRules" />
|
:validationRules="validationRules" />
|
||||||
</div>
|
</div>
|
||||||
<funnel-footer
|
<navbar
|
||||||
ref="funnelFooter"
|
ref="navbar"
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
:isForwardActionDisabled="!isMetaValid"
|
:isForwardActionDisabled="!isMetaValid"
|
||||||
@back-clicked="handleBackButtonAction"
|
@back-clicked="handleBackButtonAction"
|
||||||
|
|
@ -40,7 +40,7 @@ import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
import questionChain from "@/digital-components/question-chain/question-chain";
|
import questionChain from "@/digital-components/question-chain/question-chain";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -88,7 +88,7 @@ export default {
|
||||||
alert,
|
alert,
|
||||||
questionChain,
|
questionChain,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
loadingModal,
|
loadingModal,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { mount } from "@vue/test-utils";
|
import { mount } from "@vue/test-utils";
|
||||||
import funnelFooter from "./funnel-footer";
|
import navbar from "./nav-bar";
|
||||||
|
|
||||||
describe("funnel-footer.vue", () => {
|
describe("nav-bar.vue", () => {
|
||||||
test("Should emit ForwardClicked on button click", async () => {
|
test("Should emit ForwardClicked on button click", async () => {
|
||||||
// Act
|
// Act
|
||||||
const wrapper = mount(funnelFooter, {
|
const wrapper = mount(navbar, {
|
||||||
mixins: [mockMixin],
|
mixins: [mockMixin],
|
||||||
});
|
});
|
||||||
wrapper.vm.buttonClick();
|
wrapper.vm.buttonClick();
|
||||||
|
|
@ -14,7 +14,7 @@ describe("funnel-footer.vue", () => {
|
||||||
|
|
||||||
test("Should emit BackClicked on link click", async () => {
|
test("Should emit BackClicked on link click", async () => {
|
||||||
// Act
|
// Act
|
||||||
const wrapper = mount(funnelFooter, {
|
const wrapper = mount(navbar, {
|
||||||
mixins: [mockMixin],
|
mixins: [mockMixin],
|
||||||
});
|
});
|
||||||
wrapper.vm.linkClick();
|
wrapper.vm.linkClick();
|
||||||
|
|
@ -24,7 +24,7 @@ describe("funnel-footer.vue", () => {
|
||||||
|
|
||||||
test("Should change button text when update button text is called", async () => {
|
test("Should change button text when update button text is called", async () => {
|
||||||
// Act
|
// Act
|
||||||
const wrapper = mount(funnelFooter, {
|
const wrapper = mount(navbar, {
|
||||||
mixins: [mockMixin],
|
mixins: [mockMixin],
|
||||||
});
|
});
|
||||||
wrapper.vm.updateButtonText("newText");
|
wrapper.vm.updateButtonText("newText");
|
||||||
|
|
@ -35,7 +35,7 @@ describe("funnel-footer.vue", () => {
|
||||||
|
|
||||||
test("should run removeLoader fn on buttonMain and return false for onkeydown fn", async () => {
|
test("should run removeLoader fn on buttonMain and return false for onkeydown fn", async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const wrapper = mount(funnelFooter, {
|
const wrapper = mount(navbar, {
|
||||||
mixins: [mockMixin],
|
mixins: [mockMixin],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="row"></div>
|
<div class="row"></div>
|
||||||
<footer class="footer container-fluid g-5 my-5 px-0" id="infoBox">
|
<div class="nav-bar container-fluid g-5 my-5 px-0" id="infoBox">
|
||||||
<div class="row d-flex flex-row-reverse align-items-center vw-100">
|
<div class="row d-flex flex-row-reverse align-items-center vw-100">
|
||||||
<div class="col button-col d-flex" id="stacked">
|
<div class="col button-col d-flex" id="stacked">
|
||||||
<buttonMain
|
<buttonMain
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
:isDisabled="isForwardActionDisabled"
|
:isDisabled="isForwardActionDisabled"
|
||||||
@click-event="buttonClick"
|
@click-event="buttonClick"
|
||||||
data-bs-target="#footerModal"
|
data-bs-target="#footerModal"
|
||||||
data-test-id="funnel-footer-main-button"
|
data-test-id="nav-bar-main-button"
|
||||||
data-bs-dismiss="modal" />
|
data-bs-dismiss="modal" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!isBackButtonHidden" class="col-auto link-col py-1 text-break">
|
<div v-if="!isBackButtonHidden" class="col-auto link-col py-1 text-break">
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
data-bs-dismiss="modal" />
|
data-bs-dismiss="modal" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -35,7 +35,7 @@ import textLink from "@/ux-components/text-link/text-link";
|
||||||
import buttonMain from "@/ux-components/button-main/button-main";
|
import buttonMain from "@/ux-components/button-main/button-main";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "funnelFooter",
|
name: "navbar",
|
||||||
emits: ["BackClicked", "ForwardClicked"], // <--- should remove oodles of warnings in dev tools
|
emits: ["BackClicked", "ForwardClicked"], // <--- should remove oodles of warnings in dev tools
|
||||||
props: {
|
props: {
|
||||||
isForwardActionDisabled: Boolean,
|
isForwardActionDisabled: Boolean,
|
||||||
|
|
@ -90,7 +90,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.footer {
|
.nav-bar {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
display: flex;
|
display: flex;
|
||||||
a {
|
a {
|
||||||
10
src/helpers/date-helper.js
Normal file
10
src/helpers/date-helper.js
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
export function getDateDifferenceInDays(startDate, endDate) {
|
||||||
|
var date1 = new Date(endDate);
|
||||||
|
date1.setHours(0, 0, 0, 0);
|
||||||
|
var date2 = new Date(startDate);
|
||||||
|
date2.setHours(0, 0, 0, 0);
|
||||||
|
// To calculate the time difference of two dates
|
||||||
|
var Difference_In_Time = date1.getTime() - date2.getTime();
|
||||||
|
// To calculate the no. of days between two dates
|
||||||
|
return Difference_In_Time / (1000 * 3600 * 24);
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { queryStrings } from "@/constants/query-strings";
|
import { queryStrings } from "@/constants/query-strings";
|
||||||
|
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||||
import { externalUrls } from "@/router/router-constants/externalUrl-values";
|
import { externalUrls } from "@/router/router-constants/externalUrl-values";
|
||||||
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
|
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
|
||||||
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
|
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
|
||||||
|
|
@ -16,15 +17,11 @@ import router from "@/router";
|
||||||
drop them so they don't start at the beginning again. This method will return 'heritage' if
|
drop them so they don't start at the beginning again. This method will return 'heritage' if
|
||||||
the user has an existing order and they come back in from the Safelite.com CTA.
|
the user has an existing order and they come back in from the Safelite.com CTA.
|
||||||
*/
|
*/
|
||||||
export async function getPageToRouteExistingOrderTo(toRoute = {}, existingHeritageOrder = false) {
|
export async function getPageToRouteExistingOrderTo(toRoute = {}) {
|
||||||
// If the user is coming in via the Safelite.Com CTA
|
// If the user is coming in via the Safelite.Com CTA
|
||||||
if (toRoute.query[queryStrings.START_TYPE] === "fmg") {
|
if (toRoute.query[queryStrings.START_TYPE] === "fmg") {
|
||||||
// If they have an existing order, return 'heritage' for the page name.
|
const latestPageRoute = await getLatestPageForRedirection();
|
||||||
if (existingHeritageOrder) {
|
return latestPageRoute;
|
||||||
return fmgPageValues.HERITAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return await getLatestPageForRedirection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If navigating to a specific page, and that page is not part of the vin pages.
|
// If navigating to a specific page, and that page is not part of the vin pages.
|
||||||
|
|
@ -41,7 +38,6 @@ export async function getPageToRouteExistingOrderTo(toRoute = {}, existingHerita
|
||||||
// If this is not a direct link to a page using fmgPage, not from Safelite.com CTA or this is a vin related page.
|
// If this is not a direct link to a page using fmgPage, not from Safelite.com CTA or this is a vin related page.
|
||||||
// Get the latest page for redirection.
|
// Get the latest page for redirection.
|
||||||
const latestPageRoute = await getLatestPageForRedirection();
|
const latestPageRoute = await getLatestPageForRedirection();
|
||||||
|
|
||||||
return latestPageRoute;
|
return latestPageRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,7 +45,7 @@ export async function getPageToRouteExistingOrderTo(toRoute = {}, existingHerita
|
||||||
Used to navigate to the heritage funnel with the correct query string and url.
|
Used to navigate to the heritage funnel with the correct query string and url.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export async function navigateToHeritageFunnel({ shouldSaveSession = true, loadingModal }) {
|
export async function navigateToHeritageFunnel({ shouldSaveSession, loadingModal }) {
|
||||||
// Create the order (or save existing order) when navigating to Heritage Funnel.
|
// Create the order (or save existing order) when navigating to Heritage Funnel.
|
||||||
if (shouldSaveSession) {
|
if (shouldSaveSession) {
|
||||||
await saveSession({ shouldAwaitSaveSessionQueue: true });
|
await saveSession({ shouldAwaitSaveSessionQueue: true });
|
||||||
|
|
@ -59,21 +55,31 @@ export async function navigateToHeritageFunnel({ shouldSaveSession = true, loadi
|
||||||
loadingModal.showModal();
|
loadingModal.showModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
router.navigateToExternalUrl(externalUrls.HERITAGE_FUNNEL, {
|
var heritageParms = {
|
||||||
corid: store.getters.order.referralCorrelationId,
|
corid: store.getters.order.referralCorrelationId,
|
||||||
src: "concept-funnel",
|
src: "concept-funnel",
|
||||||
conceptsqid: store.getters.applicationUser.savedSessionId,
|
conceptsqid: store.getters.applicationUser.savedSessionId,
|
||||||
isInsurance: store.getters.payment.isInsurance,
|
isInsurance: store.getters.payment.isInsurance,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const promo = getQuerystringParameter(queryStrings.PROMO);
|
||||||
|
|
||||||
|
if (promo) {
|
||||||
|
heritageParms["promo"] = promo;
|
||||||
|
}
|
||||||
|
|
||||||
|
router.navigateToExternalUrl(externalUrls.HERITAGE_FUNNEL, heritageParms);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function skipVinLookup() {
|
export async function skipVinLookup() {
|
||||||
|
if (store.getters.damage.isRepair) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
const isVinOptionalVehicle = store.getters.order.vehicle.make
|
const isVinOptionalVehicle = store.getters.order.vehicle.make
|
||||||
? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
|
? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
store.getters.damage.isRepair ||
|
|
||||||
isVinOptionalVehicle ||
|
isVinOptionalVehicle ||
|
||||||
!includesWindshieldReplacement() ||
|
!includesWindshieldReplacement() ||
|
||||||
experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true")
|
experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true")
|
||||||
|
|
@ -81,18 +87,18 @@ export async function skipVinLookup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function skipVinLookupNotRepair() {
|
export async function skipVinLookupNotRepair() {
|
||||||
|
if (store.getters.damage.isRepair) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const isVinOptionalVehicle = store.getters.order.vehicle.make
|
const isVinOptionalVehicle = store.getters.order.vehicle.make
|
||||||
? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
|
? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
!store.getters.damage.isRepair &&
|
isVinOptionalVehicle ||
|
||||||
(isVinOptionalVehicle ||
|
!includesWindshieldReplacement() ||
|
||||||
!includesWindshieldReplacement() ||
|
experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true")
|
||||||
experimentMixin.methods.hasSettingEqualTo(
|
|
||||||
experimentSettings.SUPPRESS_VIN_CAPTURE,
|
|
||||||
"true"
|
|
||||||
))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ describe("getPageToRouteExistingOrderTo", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await getPageToRouteExistingOrderTo(toRoute, false);
|
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(result).toBe(fmgPageValues.VEHICLE);
|
expect(result).toBe(fmgPageValues.VEHICLE);
|
||||||
|
|
@ -59,7 +59,7 @@ describe("getPageToRouteExistingOrderTo", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await getPageToRouteExistingOrderTo(toRoute, false);
|
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(result).toBe(fmgPageValues.VEHICLE_DAMAGE);
|
expect(result).toBe(fmgPageValues.VEHICLE_DAMAGE);
|
||||||
|
|
@ -97,7 +97,7 @@ describe("getPageToRouteExistingOrderTo", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await getPageToRouteExistingOrderTo(toRoute, false);
|
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(result).toBe(fmgPageValues.ESTIMATE);
|
expect(result).toBe(fmgPageValues.ESTIMATE);
|
||||||
|
|
@ -125,7 +125,7 @@ describe("getPageToRouteExistingOrderTo", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await getPageToRouteExistingOrderTo(toRoute, false);
|
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(result).toBe(fmgPageValues.ESTIMATE);
|
expect(result).toBe(fmgPageValues.ESTIMATE);
|
||||||
|
|
@ -153,7 +153,7 @@ describe("getPageToRouteExistingOrderTo", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await getPageToRouteExistingOrderTo(toRoute, false);
|
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(result).toBe(fmgPageValues.CAPABILITY_QUESTIONS);
|
expect(result).toBe(fmgPageValues.CAPABILITY_QUESTIONS);
|
||||||
|
|
@ -181,7 +181,7 @@ describe("getPageToRouteExistingOrderTo", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await getPageToRouteExistingOrderTo(toRoute, false);
|
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(result).toBe(fmgPageValues.MOLDING_QUESTIONS);
|
expect(result).toBe(fmgPageValues.MOLDING_QUESTIONS);
|
||||||
|
|
@ -209,7 +209,7 @@ describe("getPageToRouteExistingOrderTo", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await getPageToRouteExistingOrderTo(toRoute, false);
|
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(result).toBe(fmgPageValues.VEHICLE_PARTS);
|
expect(result).toBe(fmgPageValues.VEHICLE_PARTS);
|
||||||
|
|
@ -237,29 +237,11 @@ describe("getPageToRouteExistingOrderTo", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await getPageToRouteExistingOrderTo(toRoute, false);
|
const result = await getPageToRouteExistingOrderTo(toRoute);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(result).toBe(fmgPageValues.PART_QUESTIONS);
|
expect(result).toBe(fmgPageValues.PART_QUESTIONS);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("existing order > should return heritage", async () => {
|
|
||||||
// Arrange
|
|
||||||
const toRoute = {
|
|
||||||
query: {
|
|
||||||
[queryStrings.START_TYPE]: "fmg",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
|
|
||||||
store.commit(storeMutations.UPDATE_MAKE, "acura");
|
|
||||||
|
|
||||||
// Act
|
|
||||||
const result = await getPageToRouteExistingOrderTo(toRoute, true);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
expect(result).toBe(fmgPageValues.HERITAGE);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("navigateToHeritageFunnel", () => {
|
describe("navigateToHeritageFunnel", () => {
|
||||||
|
|
@ -295,7 +277,7 @@ describe("navigateToHeritageFunnel", () => {
|
||||||
router.navigateToExternalUrl = jest.fn();
|
router.navigateToExternalUrl = jest.fn();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await navigateToHeritageFunnel({});
|
await navigateToHeritageFunnel({ loadingModal: null, shouldSaveSession: true });
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(saveSessionFunction).toHaveBeenCalled();
|
expect(saveSessionFunction).toHaveBeenCalled();
|
||||||
|
|
|
||||||
|
|
@ -727,8 +727,8 @@ function setupMocks({
|
||||||
|
|
||||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => "");
|
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => "");
|
||||||
wrapper.vm.setCmsContent = jest.fn();
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
||||||
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
|
||||||
|
|
||||||
return { wrapper };
|
return { wrapper };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,75 +5,92 @@
|
||||||
ref="theForm"
|
ref="theForm"
|
||||||
v-slot="{ meta }"
|
v-slot="{ meta }"
|
||||||
autocomplete="off">
|
autocomplete="off">
|
||||||
<div class="page-container-grouped-styles">
|
<div class="container-fluid">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
<div class="row">
|
||||||
<vehicleBanner
|
<div class="col">
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
||||||
ref="vehicleBanner"
|
</div>
|
||||||
:displayGenericVehicleImage="false" />
|
</div>
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" ref="funnelSubHeader" />
|
<div class="row justify-content-md-center">
|
||||||
<div class="fade-on-route-transition sub-container make-tall">
|
<div class="col-md-6 col-xl-4">
|
||||||
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
|
<vehicleBanner
|
||||||
<alert
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
ref="alertVinNotFound"
|
ref="vehicleBanner"
|
||||||
v-if="displayVinNotFoundAlert"
|
:displayGenericVehicleImage="false" />
|
||||||
class="mb-4"
|
|
||||||
cmsWidgetName="AlertVinNotFoundWidget"
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" ref="funnelSubHeader" />
|
||||||
alertClass="alert-danger"
|
|
||||||
v-bind:isDismissible="false" />
|
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
|
||||||
<alert
|
|
||||||
ref="alertMatchedDifferentVehicle"
|
<alert
|
||||||
v-if="displayMatchedDifferentVehicleAlert"
|
ref="alertVinNotFound"
|
||||||
class="mb-4"
|
v-if="displayVinNotFoundAlert"
|
||||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
class="mb-4"
|
||||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
cmsWidgetName="AlertVinNotFoundWidget"
|
||||||
alertClass="alert-warning"
|
alertClass="alert-danger"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
<alert
|
|
||||||
ref="alertInvalidZip"
|
<alert
|
||||||
v-if="displayInvalidZipAlert"
|
ref="alertMatchedDifferentVehicle"
|
||||||
class="mb-4"
|
v-if="displayMatchedDifferentVehicleAlert"
|
||||||
cmsWidgetName="AlertInvalidZipWidget"
|
class="mb-4"
|
||||||
alertClass="alert-danger"
|
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||||
v-bind:isDismissible="false" />
|
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||||
<alert
|
alertClass="alert-warning"
|
||||||
ref="alertNonServiceableZip"
|
v-bind:isDismissible="false" />
|
||||||
v-if="displayNonServiceableZipAlert"
|
|
||||||
class="mb-4"
|
<alert
|
||||||
alertClass="alert-danger"
|
ref="alertInvalidZip"
|
||||||
:manualHeadline="AlertNonServiceableZipHeader"
|
v-if="displayInvalidZipAlert"
|
||||||
:manualCopy="AlertNonServiceableZipBody"
|
class="mb-4"
|
||||||
v-bind:isDismissible="false" />
|
cmsWidgetName="AlertInvalidZipWidget"
|
||||||
<alert
|
alertClass="alert-danger"
|
||||||
ref="alertVinLookupsByHomeAddressNotAllowed"
|
v-bind:isDismissible="false" />
|
||||||
v-if="displayVinLookupByHomeAddressNotAllowedAlert"
|
|
||||||
class="mb-4"
|
<alert
|
||||||
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
ref="alertNonServiceableZip"
|
||||||
alertClass="alert-danger"
|
v-if="displayNonServiceableZipAlert"
|
||||||
v-bind:isDismissible="false" />
|
class="mb-4"
|
||||||
<transition name="fade" mode="out-in">
|
alertClass="alert-danger"
|
||||||
<div class="service-zip-field" v-if="showServiceZipField" aria-live="polite">
|
:manualHeadline="AlertNonServiceableZipHeader"
|
||||||
<div class="row mt-4 mb-1">
|
:manualCopy="AlertNonServiceableZipBody"
|
||||||
<div class="col">
|
v-bind:isDismissible="false" />
|
||||||
<textboxQuestion
|
|
||||||
cmsWidgetName="ServiceZipQuestionWidget"
|
<alert
|
||||||
v-model="serviceZipCode"
|
ref="alertVinLookupsByHomeAddressNotAllowed"
|
||||||
ref="serviceZip"
|
v-if="displayVinLookupByHomeAddressNotAllowedAlert"
|
||||||
customInputId="serviceZip"
|
class="mb-4"
|
||||||
aria-haspopup=""
|
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
||||||
mask="#####"
|
alertClass="alert-danger"
|
||||||
validationRules="service-zip-required|service-zip-format" />
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
|
<transition name="fade" mode="out-in">
|
||||||
|
<div
|
||||||
|
class="service-zip-field"
|
||||||
|
v-if="showServiceZipField"
|
||||||
|
aria-live="polite">
|
||||||
|
<div class="row mt-4 mb-1">
|
||||||
|
<div class="col">
|
||||||
|
<textboxQuestion
|
||||||
|
cmsWidgetName="ServiceZipQuestionWidget"
|
||||||
|
v-model="serviceZipCode"
|
||||||
|
ref="serviceZip"
|
||||||
|
customInputId="serviceZip"
|
||||||
|
aria-haspopup=""
|
||||||
|
mask="#####"
|
||||||
|
validationRules="service-zip-required|service-zip-format" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</transition>
|
||||||
</transition>
|
<navbar
|
||||||
<funnel-footer
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
ref="navbar"
|
||||||
ref="funnelFooter"
|
:isDisabled="!meta.valid"
|
||||||
:isDisabled="!meta.valid"
|
@ForwardClicked="forwardButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@back-clicked="backButtonAction"
|
:isForwardActionDisabled="!meta.valid" />
|
||||||
:isForwardActionDisabled="!meta.valid" />
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -82,7 +99,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import customerQuestions from "@/layouts/address-lookup/customer-questions/customer-questions";
|
import customerQuestions from "@/layouts/address-lookup/customer-questions/customer-questions";
|
||||||
|
|
@ -250,14 +267,14 @@ export default {
|
||||||
if (!resultMap.vinLookupResponse.isStatePermissible) {
|
if (!resultMap.vinLookupResponse.isStatePermissible) {
|
||||||
// State Restrictions forbid lookup by address
|
// State Restrictions forbid lookup by address
|
||||||
this.displayVinLookupByHomeAddressNotAllowedAlert = true;
|
this.displayVinLookupByHomeAddressNotAllowedAlert = true;
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a Service Zip is entered and it is an invalid zip code (ex. 11111) then show an alert
|
// If a Service Zip is entered and it is an invalid zip code (ex. 11111) then show an alert
|
||||||
const isZipValid = resultMap.serviceZipValidationResponse.isValid;
|
const isZipValid = resultMap.serviceZipValidationResponse.isValid;
|
||||||
if (this.serviceZipCode && !isZipValid) {
|
if (this.serviceZipCode && !isZipValid) {
|
||||||
this.displayInvalidZipAlert = true;
|
this.displayInvalidZipAlert = true;
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
this.displayInvalidZipAlert = false;
|
this.displayInvalidZipAlert = false;
|
||||||
|
|
||||||
|
|
@ -281,10 +298,10 @@ export default {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update button "Continue with..."
|
// Update button "Continue with..."
|
||||||
this.$refs.funnelFooter.updateButtonText(
|
this.$refs.navbar.updateButtonText(
|
||||||
`Continue with ${carFound.year} ${carFound.make} ${carFound.model}`
|
`Continue with ${carFound.year} ${carFound.make} ${carFound.model}`
|
||||||
);
|
);
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
// update data if the zip or service zip is serviceable
|
// update data if the zip or service zip is serviceable
|
||||||
|
|
@ -304,7 +321,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
// No VINS found.
|
// No VINS found.
|
||||||
this.displayVinNotFoundAlert = true;
|
this.displayVinNotFoundAlert = true;
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the either the registration zip code or service zip code are not serviceable
|
// If the either the registration zip code or service zip code are not serviceable
|
||||||
|
|
@ -312,7 +329,7 @@ export default {
|
||||||
if (!this.isZipServiceable) {
|
if (!this.isZipServiceable) {
|
||||||
this.displayNonServiceableZipAlert = true;
|
this.displayNonServiceableZipAlert = true;
|
||||||
this.showServiceZipField = true;
|
this.showServiceZipField = true;
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the registration zip code is serviceable and nothing was entered for the service zip code
|
// If the registration zip code is serviceable and nothing was entered for the service zip code
|
||||||
|
|
@ -430,7 +447,7 @@ export default {
|
||||||
customerQuestions: {
|
customerQuestions: {
|
||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
// if they modify one of the lookup fields (address, city, state, zipCode, or lastName), then modify the button text back to "Get my personalized quote"
|
// if they modify one of the lookup fields (address, city, state, zipCode, or lastName), then modify the button text back to "Get my personalized quote"
|
||||||
this.$refs.funnelFooter.updateButtonText(
|
this.$refs.navbar.updateButtonText(
|
||||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||||
);
|
);
|
||||||
this.showServiceZipField = false;
|
this.showServiceZipField = false;
|
||||||
|
|
@ -455,7 +472,7 @@ export default {
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
customerQuestions,
|
customerQuestions,
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,8 @@ describe("addressVehicles.vue", () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// the following has to be set BEFORE changing the data which is being watched, and requires updateButtonText to be mocked
|
// the following has to be set BEFORE changing the data which is being watched, and requires updateButtonText to be mocked
|
||||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
||||||
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
|
||||||
wrapper.vm.lookupVin = jest.fn(() => Promise.resolve(lookupVinResponse));
|
wrapper.vm.lookupVin = jest.fn(() => Promise.resolve(lookupVinResponse));
|
||||||
wrapper.vm.$router.navigate = jest.fn();
|
wrapper.vm.$router.navigate = jest.fn();
|
||||||
wrapper.vm.updateCustomerInfo = jest.fn().mockImplementation(() => {});
|
wrapper.vm.updateCustomerInfo = jest.fn().mockImplementation(() => {});
|
||||||
|
|
@ -106,8 +106,8 @@ describe("addressVehicles.vue", () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// the following has to be set BEFORE changing the data which is being watched, and requires updateButtonText to be mocked
|
// the following has to be set BEFORE changing the data which is being watched, and requires updateButtonText to be mocked
|
||||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
||||||
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
|
||||||
wrapper.vm.lookupVin = jest.fn(() => Promise.reject(lookupVinResponse));
|
wrapper.vm.lookupVin = jest.fn(() => Promise.reject(lookupVinResponse));
|
||||||
wrapper.vm.$router.navigateWithSaving = jest.fn();
|
wrapper.vm.$router.navigateWithSaving = jest.fn();
|
||||||
wrapper.vm.updateCustomerInfo = jest.fn().mockImplementation(() => {});
|
wrapper.vm.updateCustomerInfo = jest.fn().mockImplementation(() => {});
|
||||||
|
|
@ -128,7 +128,7 @@ describe("addressVehicles.vue", () => {
|
||||||
test("Should navigate to CLICKED_FORWARD scenario if carId is different and selected glass not available for vehicle on navigateForward", async () => {
|
test("Should navigate to CLICKED_FORWARD scenario if carId is different and selected glass not available for vehicle on navigateForward", async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
||||||
wrapper.vm.$router.navigateWithSaving = jest.fn();
|
wrapper.vm.$router.navigateWithSaving = jest.fn();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -148,7 +148,7 @@ describe("addressVehicles.vue", () => {
|
||||||
test("carId is not different on navigateForward (car was found) => Should handle navigating forward with car match", async () => {
|
test("carId is not different on navigateForward (car was found) => Should handle navigating forward with car match", async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
||||||
navigateToHeritage.navigateToHeritageFunnel = jest.fn();
|
navigateToHeritage.navigateToHeritageFunnel = jest.fn();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -224,7 +224,7 @@ function setupMocks({}) {
|
||||||
|
|
||||||
const wrapper = shallowMount(addressVehicles, mountOptions);
|
const wrapper = shallowMount(addressVehicles, mountOptions);
|
||||||
|
|
||||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
||||||
wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();
|
wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();
|
||||||
|
|
||||||
return { wrapper };
|
return { wrapper };
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@
|
||||||
class="mb-3"
|
class="mb-3"
|
||||||
marginTopSizeOverride="3" />
|
marginTopSizeOverride="3" />
|
||||||
</div>
|
</div>
|
||||||
<funnelFooter
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="funnelFooter"
|
ref="navbar"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
|
|
@ -169,7 +169,7 @@ export default {
|
||||||
},
|
},
|
||||||
"address-vehicles"
|
"address-vehicles"
|
||||||
).catch(() => {
|
).catch(() => {
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.navbar.removeLoader();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!vinLookup) {
|
if (!vinLookup) {
|
||||||
|
|
@ -215,11 +215,11 @@ export default {
|
||||||
this.isCarIdDifferent =
|
this.isCarIdDifferent =
|
||||||
this.selectedVehicle?.vehicle.carId !== store.getters.vehicle.carId;
|
this.selectedVehicle?.vehicle.carId !== store.getters.vehicle.carId;
|
||||||
if (this.isCarIdDifferent) {
|
if (this.isCarIdDifferent) {
|
||||||
this.$refs.funnelFooter.updateButtonText(
|
this.$refs.navbar.updateButtonText(
|
||||||
`Continue with ${this.selectedVehicle.vehicle.year} ${this.selectedVehicle.vehicle.make} ${this.selectedVehicle.vehicle.model}`
|
`Continue with ${this.selectedVehicle.vehicle.year} ${this.selectedVehicle.vehicle.make} ${this.selectedVehicle.vehicle.model}`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.$refs.funnelFooter.updateButtonText(
|
this.$refs.navbar.updateButtonText(
|
||||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -234,7 +234,7 @@ export default {
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
alert,
|
alert,
|
||||||
funnelFooter,
|
navbar,
|
||||||
addressVehiclesQuestion,
|
addressVehiclesQuestion,
|
||||||
textBlock,
|
textBlock,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,57 +1,72 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<div class="page-container-grouped-styles">
|
<div class="container-fluid">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<div class="row">
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="my-5" />
|
<div class="col">
|
||||||
<textboxQuestion
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
class="mb-4"
|
</div>
|
||||||
cmsWidgetName="FirstNameWidget"
|
</div>
|
||||||
v-model="firstName"
|
<div class="row justify-content-md-center">
|
||||||
ref="firstName"
|
<div class="col-md-6 col-xl-4">
|
||||||
customInputId="firstName"
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="my-5" />
|
||||||
validationRules="first-name-required" />
|
<textboxQuestion
|
||||||
<textboxQuestion
|
class="mb-4"
|
||||||
class="mb-4"
|
cmsWidgetName="FirstNameWidget"
|
||||||
cmsWidgetName="LastNameWidget"
|
v-model="firstName"
|
||||||
v-model="lastName"
|
ref="firstName"
|
||||||
ref="lastName"
|
customInputId="firstName"
|
||||||
customInputId="lastName"
|
validationRules="first-name-required" />
|
||||||
validationRules="last-name-required" />
|
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
class="mb-4"
|
class="mb-4"
|
||||||
cmsWidgetName="emailQuestionWidget"
|
cmsWidgetName="LastNameWidget"
|
||||||
v-model="emailAddress"
|
v-model="lastName"
|
||||||
inputId="email"
|
ref="lastName"
|
||||||
validationRules="email-address-required|email-address-format" />
|
customInputId="lastName"
|
||||||
<phoneNumberQuestion
|
validationRules="last-name-required" />
|
||||||
class="mb-4"
|
|
||||||
cmsWidgetName="PhoneNumberQuestionWidget"
|
<textboxQuestion
|
||||||
v-model="phoneNumber"
|
class="mb-4"
|
||||||
isRequired
|
cmsWidgetName="emailQuestionWidget"
|
||||||
validationRules="phone-number-required" />
|
v-model="emailAddress"
|
||||||
<checkboxQuestion
|
inputId="email"
|
||||||
class="mb-5"
|
validationRules="email-address-required|email-address-format" />
|
||||||
cmsWidgetName="TextMeQuestionWidget"
|
|
||||||
v-model="isSmsOptIn" />
|
<phoneNumberQuestion
|
||||||
<textareaQuestion
|
class="mb-4"
|
||||||
class="mb-4"
|
cmsWidgetName="PhoneNumberQuestionWidget"
|
||||||
v-model="techNotes"
|
v-model="phoneNumber"
|
||||||
cmsWidgetName="TextAreaContentWidget"
|
isRequired
|
||||||
maxLength="250" />
|
validationRules="phone-number-required" />
|
||||||
<textBlock cmsWidgetName="DisclaimerCopyWidget" typeStyle="caption" />
|
|
||||||
<funnel-footer
|
<checkboxQuestion
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
class="mb-5"
|
||||||
ref="funnelFooter"
|
cmsWidgetName="TextMeQuestionWidget"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
v-model="isSmsOptIn" />
|
||||||
@back-clicked="backButtonAction"
|
|
||||||
@ForwardClicked="forwardButtonAction" />
|
<textareaQuestion
|
||||||
|
class="mb-4"
|
||||||
|
v-model="techNotes"
|
||||||
|
cmsWidgetName="TextAreaContentWidget"
|
||||||
|
maxLength="250" />
|
||||||
|
|
||||||
|
<textBlock cmsWidgetName="DisclaimerCopyWidget" typeStyle="caption" />
|
||||||
|
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import textareaQuestion from "@/digital-components/textarea-question/textarea-question";
|
import textareaQuestion from "@/digital-components/textarea-question/textarea-question";
|
||||||
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
|
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
|
||||||
|
|
@ -172,7 +187,7 @@ export default {
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
textareaQuestion,
|
textareaQuestion,
|
||||||
textboxQuestion,
|
textboxQuestion,
|
||||||
funnelFooter,
|
navbar,
|
||||||
Form,
|
Form,
|
||||||
textBlock,
|
textBlock,
|
||||||
phoneNumberQuestion,
|
phoneNumberQuestion,
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,7 @@ function setupMocks({
|
||||||
{ Name: "Provide my license plate # Most accurate VIN match" },
|
{ Name: "Provide my license plate # Most accurate VIN match" },
|
||||||
{ Name: "Provide my home address Most convenient VIN match" },
|
{ Name: "Provide my home address Most convenient VIN match" },
|
||||||
],
|
],
|
||||||
funnelFooterWidget = { ForwardButtonText: "test txt" },
|
FunnelFooterWidget = { ForwardButtonText: "test txt" },
|
||||||
mountOptionsMockData = {
|
mountOptionsMockData = {
|
||||||
router: {
|
router: {
|
||||||
navigate: jest.fn(),
|
navigate: jest.fn(),
|
||||||
|
|
@ -271,7 +271,7 @@ function setupMocks({
|
||||||
groupName: groupName,
|
groupName: groupName,
|
||||||
QuestionText: cmsQuestionText,
|
QuestionText: cmsQuestionText,
|
||||||
Answers: cmsAnswers,
|
Answers: cmsAnswers,
|
||||||
FunnelFooterWidget: funnelFooterWidget,
|
FunnelFooterWidget: FunnelFooterWidget,
|
||||||
};
|
};
|
||||||
|
|
||||||
const apiPromise = Promise.resolve({ cmsContent });
|
const apiPromise = Promise.resolve({ cmsContent });
|
||||||
|
|
|
||||||
|
|
@ -1,79 +1,84 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<div class="page-container-grouped-styles">
|
<loadingModal ref="loadingModal" />
|
||||||
<loadingModal ref="loadingModal" />
|
<div class="container-fluid">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<div class="row">
|
||||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" />
|
<div class="col">
|
||||||
<funnelSubHeader class="pb-4" cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<div class="fade-on-route-transition sub-container make-tall">
|
|
||||||
<div v-if="!skipVin">
|
|
||||||
<div class="vinlookupquestion" v-html="this.VinLookupQuestionText"></div>
|
|
||||||
<buttonQuestion
|
|
||||||
cmsWidgetName="VinLookupMethod"
|
|
||||||
:answers="answersFromCms"
|
|
||||||
groupName="vinLookupMethodOption"
|
|
||||||
buttonTypeString="listButton"
|
|
||||||
v-model="selectedVinLookupMethod"
|
|
||||||
isRequired
|
|
||||||
validationRules="option-required"
|
|
||||||
:logDisplayedValuesEvent="true" />
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
</div>
|
||||||
<alert
|
<div class="row justify-content-md-center">
|
||||||
class="my-4"
|
<div class="col-md-6 col-xl-4">
|
||||||
:cmsWidgetName="alertInfo"
|
<vehicleBanner cmsWidgetName="VehicleBannerWidget" />
|
||||||
alertClass="alert-info"
|
<funnelSubHeader class="pb-4" cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
v-bind:isDismissible="false" />
|
<div v-if="!skipVin">
|
||||||
<div class="row my-2">
|
<div class="vinlookupquestion" v-html="this.VinLookupQuestionText"></div>
|
||||||
<div class="col">
|
<buttonQuestion
|
||||||
<textboxQuestion
|
cmsWidgetName="VinLookupMethod"
|
||||||
cmsWidgetName="ServiceZipQuestionWidget"
|
:answers="answersFromCms"
|
||||||
v-model="serviceZipCode"
|
groupName="vinLookupMethodOption"
|
||||||
inputId="serviceZipCode"
|
buttonTypeString="listButton"
|
||||||
mask="#####"
|
v-model="selectedVinLookupMethod"
|
||||||
isRequired
|
isRequired
|
||||||
validationRules="zip-required|zip-format" />
|
validationRules="option-required"
|
||||||
</div>
|
:logDisplayedValuesEvent="true" />
|
||||||
|
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-2">
|
|
||||||
<div class="col">
|
<div v-else>
|
||||||
<textboxQuestion
|
<alert
|
||||||
cmsWidgetName="EmailAddressQuestionWidget"
|
class="my-4"
|
||||||
v-model="emailAddress"
|
:cmsWidgetName="alertInfo"
|
||||||
inputId="emailAddress"
|
alertClass="alert-info"
|
||||||
isRequired
|
v-bind:isDismissible="false" />
|
||||||
disableAutoFill
|
|
||||||
validationRules="email-address-required|email-address-format" />
|
<textboxQuestion
|
||||||
</div>
|
cmsWidgetName="ServiceZipQuestionWidget"
|
||||||
|
v-model="serviceZipCode"
|
||||||
|
inputId="serviceZipCode"
|
||||||
|
mask="#####"
|
||||||
|
isRequired
|
||||||
|
validationRules="zip-required|zip-format" />
|
||||||
|
|
||||||
|
<textboxQuestion
|
||||||
|
cmsWidgetName="EmailAddressQuestionWidget"
|
||||||
|
v-model="emailAddress"
|
||||||
|
inputId="emailAddress"
|
||||||
|
isRequired
|
||||||
|
disableAutoFill
|
||||||
|
validationRules="email-address-required|email-address-format" />
|
||||||
|
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
ref="alertInvalidZip"
|
||||||
|
v-if="displayInvalidZipAlert"
|
||||||
|
class="my-4"
|
||||||
|
cmsWidgetName="AlertInvalidZipWidget"
|
||||||
|
alertClass="alert-danger"
|
||||||
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
class="my-4"
|
||||||
|
:manualHeadline="AlertNonServiceableZipHeader"
|
||||||
|
:manualCopy="AlertNonServiceableZipBody"
|
||||||
|
v-model="customAlertData"
|
||||||
|
v-if="displayNonServiceableZipAlert"
|
||||||
|
alertClass="alert-danger" />
|
||||||
|
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-2">
|
|
||||||
<div class="col">
|
|
||||||
<textBlock
|
|
||||||
cmsWidgetName="QuoteEmailTextBlockWidget"
|
|
||||||
typeStyle="caption" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<alert
|
|
||||||
ref="alertInvalidZip"
|
|
||||||
v-if="displayInvalidZipAlert"
|
|
||||||
class="my-4"
|
|
||||||
cmsWidgetName="AlertInvalidZipWidget"
|
|
||||||
alertClass="alert-danger"
|
|
||||||
v-bind:isDismissible="false" />
|
|
||||||
<alert
|
|
||||||
class="my-4"
|
|
||||||
:manualHeadline="AlertNonServiceableZipHeader"
|
|
||||||
:manualCopy="AlertNonServiceableZipBody"
|
|
||||||
v-model="customAlertData"
|
|
||||||
v-if="displayNonServiceableZipAlert"
|
|
||||||
alertClass="alert-danger" />
|
|
||||||
</div>
|
</div>
|
||||||
<funnel-footer
|
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
|
||||||
ref="funnelFooter"
|
|
||||||
:isForwardActionDisabled="!meta.valid"
|
|
||||||
@back-clicked="backButtonAction"
|
|
||||||
@ForwardClicked="forwardButtonAction" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -82,7 +87,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import buttonQuestion from "@/digital-components/button-question/button-question";
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||||
|
|
@ -239,13 +244,13 @@ export default {
|
||||||
|
|
||||||
if (!zipCodeData.isValid) {
|
if (!zipCodeData.isValid) {
|
||||||
this.displayInvalidZipAlert = true;
|
this.displayInvalidZipAlert = true;
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
this.displayInvalidZipAlert = false;
|
this.displayInvalidZipAlert = false;
|
||||||
|
|
||||||
if (!zipCodeData.isServiceable) {
|
if (!zipCodeData.isServiceable) {
|
||||||
this.displayNonServiceableZipAlert = true;
|
this.displayNonServiceableZipAlert = true;
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
this.displayNonServiceableZipAlert = false;
|
this.displayNonServiceableZipAlert = false;
|
||||||
|
|
||||||
|
|
@ -253,7 +258,10 @@ export default {
|
||||||
const vehicleChangedDuringPolicyLookupInHeritage =
|
const vehicleChangedDuringPolicyLookupInHeritage =
|
||||||
payment.isInsurance && payment.insuranceCoverage.coverageStatus;
|
payment.isInsurance && payment.insuranceCoverage.coverageStatus;
|
||||||
if (vehicleChangedDuringPolicyLookupInHeritage) {
|
if (vehicleChangedDuringPolicyLookupInHeritage) {
|
||||||
navigateToHeritageFunnel({ loadingModal: this.$refs.loadingModal });
|
navigateToHeritageFunnel({
|
||||||
|
shouldSaveSession: true,
|
||||||
|
loadingModal: this.$refs.loadingModal,
|
||||||
|
});
|
||||||
} else if (this.$store.getters.order.referralNumber?.length === 6) {
|
} else if (this.$store.getters.order.referralNumber?.length === 6) {
|
||||||
await this.navigateForwardWithSingleCarMatch();
|
await this.navigateForwardWithSingleCarMatch();
|
||||||
} else if (this.isRepair) {
|
} else if (this.isRepair) {
|
||||||
|
|
@ -346,7 +354,7 @@ export default {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
buttonQuestion,
|
buttonQuestion,
|
||||||
Form,
|
Form,
|
||||||
alert,
|
alert,
|
||||||
|
|
@ -361,6 +369,10 @@ export default {
|
||||||
.vinlookupquestion p {
|
.vinlookupquestion p {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
.vinlookupquestion strong {
|
||||||
|
font-weight: 500;
|
||||||
|
color: $black;
|
||||||
|
}
|
||||||
.vinlookupquestion p:nth-child(2) {
|
.vinlookupquestion p:nth-child(2) {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
|
|
||||||
|
|
@ -315,7 +315,7 @@ describe("license-plate-lookup.vue", () => {
|
||||||
await wrapper.vm.$nextTick();
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled();
|
expect(wrapper.vm.$refs.navbar.updateButtonText).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Button Text should revert to initial value when registrationZip textfield has new text", async () => {
|
test("Button Text should revert to initial value when registrationZip textfield has new text", async () => {
|
||||||
|
|
@ -330,7 +330,7 @@ describe("license-plate-lookup.vue", () => {
|
||||||
await wrapper.vm.$nextTick();
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled();
|
expect(wrapper.vm.$refs.navbar.updateButtonText).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Button Text should revert to initial value when serviceZip textfield has new text", async () => {
|
test("Button Text should revert to initial value when serviceZip textfield has new text", async () => {
|
||||||
|
|
@ -345,7 +345,7 @@ describe("license-plate-lookup.vue", () => {
|
||||||
await wrapper.vm.$nextTick();
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled();
|
expect(wrapper.vm.$refs.navbar.updateButtonText).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -703,8 +703,8 @@ function setupMocks({
|
||||||
|
|
||||||
wrapper.vm.setCmsContent = jest.fn();
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => "");
|
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => "");
|
||||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
||||||
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
|
||||||
|
|
||||||
return { wrapper, apiPromise };
|
return { wrapper, apiPromise };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,88 +1,89 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<div class="page-container-grouped-styles">
|
<div class="container-fluid">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<div class="row">
|
||||||
<vehicleBanner
|
<div class="col">
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
:displayGenericVehicleImage="false" />
|
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
|
||||||
<div class="fade-on-route-transition sub-container make-tall">
|
|
||||||
<div class="row mt-2 mb-4">
|
|
||||||
<div class="col">
|
|
||||||
<textboxQuestion
|
|
||||||
cmsWidgetName="LicensePlateNumberQuestionWidget"
|
|
||||||
v-model="licensePlate"
|
|
||||||
isRequired
|
|
||||||
customInputId="licensePlate"
|
|
||||||
validationRules="license-plate-required" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-0 mb-4">
|
</div>
|
||||||
<div class="col">
|
<div class="row justify-content-md-center">
|
||||||
<textboxQuestion
|
<div class="col-md-6 col-xl-4">
|
||||||
cmsWidgetName="RegistrationZipQuestionWidget"
|
<vehicleBanner
|
||||||
v-model="registrationZipCode"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
customInputId="zip"
|
:displayGenericVehicleImage="false" />
|
||||||
mask="#####"
|
|
||||||
validationRules="registration-zip-required|zip-format" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
|
|
||||||
|
<textboxQuestion
|
||||||
|
cmsWidgetName="LicensePlateNumberQuestionWidget"
|
||||||
|
v-model="licensePlate"
|
||||||
|
isRequired
|
||||||
|
customInputId="licensePlate"
|
||||||
|
validationRules="license-plate-required" />
|
||||||
|
|
||||||
|
<textboxQuestion
|
||||||
|
cmsWidgetName="RegistrationZipQuestionWidget"
|
||||||
|
v-model="registrationZipCode"
|
||||||
|
customInputId="zip"
|
||||||
|
mask="#####"
|
||||||
|
validationRules="registration-zip-required|zip-format" />
|
||||||
|
|
||||||
|
<textboxQuestion
|
||||||
|
cmsWidgetName="EmailAddressQuestionWidget"
|
||||||
|
v-model="email"
|
||||||
|
customInputId="email"
|
||||||
|
validationRules="email-address-required|email-address-format" />
|
||||||
|
|
||||||
|
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
v-if="displayInvalidZipAlert"
|
||||||
|
class="my-3"
|
||||||
|
cmsWidgetName="AlertInvalidZipWidget"
|
||||||
|
alertClass="alert-danger"
|
||||||
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
v-if="displayNonServiceableZipAlert"
|
||||||
|
class="my-3"
|
||||||
|
:manualHeadline="AlertNonServiceableZipHeader"
|
||||||
|
:manualCopy="AlertNonServiceableZipBody"
|
||||||
|
alertClass="alert-danger"
|
||||||
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
|
<div class="row mt-2" v-if="showServiceZipField">
|
||||||
|
<div class="col mb-1">
|
||||||
|
<textboxQuestion
|
||||||
|
cmsWidgetName="ServiceZipQuestionWidget"
|
||||||
|
v-model="serviceZipCode"
|
||||||
|
inputId="serviceZipCode"
|
||||||
|
validationRules="zip-required|zip-format"
|
||||||
|
mask="#####" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<alert
|
||||||
|
v-if="displayVinNotFoundAlert"
|
||||||
|
class="my-3"
|
||||||
|
cmsWidgetName="AlertVinNotFoundWidget"
|
||||||
|
alertClass="alert-danger"
|
||||||
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
v-if="displayMatchedDifferentVehicleAlert"
|
||||||
|
class="my-3"
|
||||||
|
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||||
|
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||||
|
alertClass="alert-warning"
|
||||||
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
|
<navbar
|
||||||
|
ref="navbar"
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-0">
|
|
||||||
<div class="col">
|
|
||||||
<textboxQuestion
|
|
||||||
cmsWidgetName="EmailAddressQuestionWidget"
|
|
||||||
v-model="email"
|
|
||||||
customInputId="email"
|
|
||||||
validationRules="email-address-required|email-address-format" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-2">
|
|
||||||
<div class="col">
|
|
||||||
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<alert
|
|
||||||
v-if="displayInvalidZipAlert"
|
|
||||||
class="my-3"
|
|
||||||
cmsWidgetName="AlertInvalidZipWidget"
|
|
||||||
alertClass="alert-danger"
|
|
||||||
v-bind:isDismissible="false" />
|
|
||||||
<alert
|
|
||||||
v-if="displayNonServiceableZipAlert"
|
|
||||||
class="my-3"
|
|
||||||
:manualHeadline="AlertNonServiceableZipHeader"
|
|
||||||
:manualCopy="AlertNonServiceableZipBody"
|
|
||||||
alertClass="alert-danger"
|
|
||||||
v-bind:isDismissible="false" />
|
|
||||||
<div class="row mt-2" v-if="showServiceZipField">
|
|
||||||
<div class="col mb-1">
|
|
||||||
<textboxQuestion
|
|
||||||
cmsWidgetName="ServiceZipQuestionWidget"
|
|
||||||
v-model="serviceZipCode"
|
|
||||||
inputId="serviceZipCode"
|
|
||||||
validationRules="zip-required|zip-format"
|
|
||||||
mask="#####" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<alert
|
|
||||||
v-if="displayVinNotFoundAlert"
|
|
||||||
class="my-3"
|
|
||||||
cmsWidgetName="AlertVinNotFoundWidget"
|
|
||||||
alertClass="alert-danger"
|
|
||||||
v-bind:isDismissible="false" />
|
|
||||||
<alert
|
|
||||||
v-if="displayMatchedDifferentVehicleAlert"
|
|
||||||
class="my-3"
|
|
||||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
|
||||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
|
||||||
alertClass="alert-warning"
|
|
||||||
v-bind:isDismissible="false" />
|
|
||||||
<funnelFooter
|
|
||||||
ref="funnelFooter"
|
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
|
||||||
:isForwardActionDisabled="!meta.valid"
|
|
||||||
@back-clicked="backButtonAction"
|
|
||||||
@ForwardClicked="forwardButtonAction" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -91,7 +92,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
|
|
@ -235,7 +236,7 @@ export default {
|
||||||
).catch(() => {
|
).catch(() => {
|
||||||
// No VIN found.
|
// No VIN found.
|
||||||
this.displayVinNotFoundAlert = true;
|
this.displayVinNotFoundAlert = true;
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
});
|
});
|
||||||
// If no VIN was found, stop processing after displaying alert
|
// If no VIN was found, stop processing after displaying alert
|
||||||
if (!vinLookup) {
|
if (!vinLookup) {
|
||||||
|
|
@ -246,7 +247,7 @@ export default {
|
||||||
const isZipValid = resultMap.serviceZipValidationResponse.isValid;
|
const isZipValid = resultMap.serviceZipValidationResponse.isValid;
|
||||||
if (this.serviceZipCode && !isZipValid) {
|
if (this.serviceZipCode && !isZipValid) {
|
||||||
this.displayInvalidZipAlert = true;
|
this.displayInvalidZipAlert = true;
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
this.displayInvalidZipAlert = false;
|
this.displayInvalidZipAlert = false;
|
||||||
|
|
||||||
|
|
@ -270,10 +271,10 @@ export default {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update button "Continue with..."
|
// Update button "Continue with..."
|
||||||
this.$refs.funnelFooter.updateButtonText(
|
this.$refs.navbar.updateButtonText(
|
||||||
`Continue with ${vinLookup.data.vehicle.year} ${vinLookup.data.vehicle.make} ${vinLookup.data.vehicle.model}`
|
`Continue with ${vinLookup.data.vehicle.year} ${vinLookup.data.vehicle.make} ${vinLookup.data.vehicle.model}`
|
||||||
);
|
);
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the either the registration zip code or service zip code are not serviceable
|
// If the either the registration zip code or service zip code are not serviceable
|
||||||
|
|
@ -281,7 +282,7 @@ export default {
|
||||||
if (!this.isZipServiceable) {
|
if (!this.isZipServiceable) {
|
||||||
this.displayNonServiceableZipAlert = true;
|
this.displayNonServiceableZipAlert = true;
|
||||||
this.showServiceZipField = true;
|
this.showServiceZipField = true;
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the registration zip code is serviceable and nothing was entered for the service zip code
|
// If the registration zip code is serviceable and nothing was entered for the service zip code
|
||||||
|
|
@ -374,26 +375,26 @@ export default {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
licensePlate() {
|
licensePlate() {
|
||||||
this.$refs.funnelFooter.updateButtonText(
|
this.$refs.navbar.updateButtonText(
|
||||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
registrationZipCode() {
|
registrationZipCode() {
|
||||||
this.$refs.funnelFooter.updateButtonText(
|
this.$refs.navbar.updateButtonText(
|
||||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
serviceZipCode() {
|
serviceZipCode() {
|
||||||
// If they modify the service zip code, then hide the error message.
|
// If they modify the service zip code, then hide the error message.
|
||||||
this.displayNonServiceableZipAlert = false;
|
this.displayNonServiceableZipAlert = false;
|
||||||
this.$refs.funnelFooter.updateButtonText(
|
this.$refs.navbar.updateButtonText(
|
||||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
textboxQuestion,
|
textboxQuestion,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<funnelSubHeader class="mb-5" cmsWidgetName="FunnelSubHeaderWidget" leftAlignHeader />
|
<funnelSubHeader class="mb-5" cmsWidgetName="FunnelSubHeaderWidget" leftAlignHeader />
|
||||||
<hr class="mt-0" />
|
<hr class="mt-0" />
|
||||||
<div class="fade-on-route-transition sub-container make-tall">
|
<div class="fade-on-route-transition sub-container make-tall">
|
||||||
<funnel-footer
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
:isBackButtonHidden="shouldHideBackButton"
|
:isBackButtonHidden="shouldHideBackButton"
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
|
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
|
@ -63,7 +63,7 @@ export default {
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
Form,
|
Form,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,56 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<div class="page-container-grouped-styles">
|
<loadingModal ref="loadingModal" />
|
||||||
<loadingModal ref="loadingModal" />
|
<div class="container-fluid">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<div class="row">
|
||||||
<vehicleBanner
|
<div class="col">
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
:displayGenericVehicleImage="false" />
|
</div>
|
||||||
<funnelSubHeader class="mb-5" cmsWidgetName="FunnelSubHeaderWidget" />
|
</div>
|
||||||
<div class="fade-on-route-transition sub-container make-tall">
|
<div class="row justify-content-md-center">
|
||||||
<cashOrInsuranceQuestion
|
<div class="col-md-6 col-xl-4">
|
||||||
ref="cashOrInsurance"
|
<vehicleBanner
|
||||||
cmsWidgetName="CashOrInsuranceQuestionWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
v-model="isInsuranceSelected"
|
:displayGenericVehicleImage="false" />
|
||||||
groupName="CashOrInsuranceQuestion" />
|
|
||||||
<servicePackageQuestion
|
|
||||||
ref="servicePackage"
|
|
||||||
cashCmsWidgetName="CashServicePackageQuestionWidget"
|
|
||||||
insuranceCmsWidgetName="InsuranceServicePackageQuestionWidget"
|
|
||||||
groupName="ServicePackageQuestion"
|
|
||||||
:availableLineItems="availableLineItems"
|
|
||||||
:isInsuranceSelected="isInsuranceSelected"
|
|
||||||
@vapsItemsSelected="vapsItemsSelectedAction"
|
|
||||||
v-on="{ 'buttonEvent.openModal': openModalAction }"
|
|
||||||
validationRules="option-required"
|
|
||||||
isRequired />
|
|
||||||
|
|
||||||
<textBlock
|
<funnelSubHeader class="mb-5" cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
cmsWidgetName="quoteDisclaimer"
|
|
||||||
justifyText="left"
|
<cashOrInsuranceQuestion
|
||||||
typeStyle="caption"
|
ref="cashOrInsurance"
|
||||||
class="mt-4" />
|
cmsWidgetName="CashOrInsuranceQuestionWidget"
|
||||||
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
|
v-model="isInsuranceSelected"
|
||||||
<contentGroupModal ref="FrontWiperModal" cmsWidgetName="FrontWiperModal" />
|
groupName="CashOrInsuranceQuestion" />
|
||||||
<contentGroupModal ref="RearWiperModal" cmsWidgetName="RearWiperModal" />
|
|
||||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
<servicePackageQuestion
|
||||||
<funnel-footer
|
ref="servicePackage"
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cashCmsWidgetName="CashServicePackageQuestionWidget"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
insuranceCmsWidgetName="InsuranceServicePackageQuestionWidget"
|
||||||
:isBackButtonHidden="shouldHideBackButton"
|
groupName="ServicePackageQuestion"
|
||||||
@back-clicked="backButtonAction"
|
:availableLineItems="availableLineItems"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
:isInsuranceSelected="isInsuranceSelected"
|
||||||
|
@vapsItemsSelected="vapsItemsSelectedAction"
|
||||||
|
v-on="{ 'buttonEvent.openModal': openModalAction }"
|
||||||
|
validationRules="option-required"
|
||||||
|
isRequired />
|
||||||
|
|
||||||
|
<textBlock
|
||||||
|
cmsWidgetName="quoteDisclaimer"
|
||||||
|
justifyText="left"
|
||||||
|
typeStyle="caption"
|
||||||
|
class="mt-4" />
|
||||||
|
|
||||||
|
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
|
||||||
|
<contentGroupModal ref="FrontWiperModal" cmsWidgetName="FrontWiperModal" />
|
||||||
|
<contentGroupModal ref="RearWiperModal" cmsWidgetName="RearWiperModal" />
|
||||||
|
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||||
|
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
:isBackButtonHidden="shouldHideBackButton"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -48,7 +59,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import cashOrInsuranceQuestion from "./cash-or-insurance-question/cash-or-insurance-question";
|
import cashOrInsuranceQuestion from "./cash-or-insurance-question/cash-or-insurance-question";
|
||||||
|
|
@ -121,6 +132,12 @@ export default {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
baseMixin.methods.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_SUPPORTING_ITEMS,
|
||||||
|
resultMap.supportingItems,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
|
|
@ -213,17 +230,14 @@ export default {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dispatchStoreAction(
|
|
||||||
this.storeActions.SAVE_SUPPORTING_ITEMS,
|
|
||||||
this.supportingItems,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false);
|
this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false);
|
||||||
|
|
||||||
const payment = this.$store.getters.payment;
|
const payment = this.$store.getters.payment;
|
||||||
if (payment.isInsurance) {
|
if (payment.isInsurance) {
|
||||||
navigateToHeritageFunnel({ loadingModal: this.$refs.loadingModal });
|
navigateToHeritageFunnel({
|
||||||
|
shouldSaveSession: true,
|
||||||
|
loadingModal: this.$refs.loadingModal,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.$router.navigateWithSaving(
|
this.$router.navigateWithSaving(
|
||||||
this.navigationScenarios.CLICKED_FORWARD_WITH_CASH,
|
this.navigationScenarios.CLICKED_FORWARD_WITH_CASH,
|
||||||
|
|
@ -234,7 +248,7 @@ export default {
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
Form,
|
Form,
|
||||||
|
|
|
||||||
|
|
@ -1,105 +1,113 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
|
||||||
<!-- When customer-details is added: v-slot="{ meta }" -->
|
<!-- When customer-details is added: v-slot="{ meta }" -->
|
||||||
<div class="page-container-grouped-styles">
|
<div class="container-fluid">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<div class="row">
|
||||||
<vehicleBanner
|
<div class="col">
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
:displayGenericVehicleImage="false" />
|
</div>
|
||||||
|
|
||||||
<textBlock
|
|
||||||
:customText="subHeaderTitle"
|
|
||||||
typeStyle="h5"
|
|
||||||
justifyText="center"
|
|
||||||
margin="mt-1"
|
|
||||||
class="dark-header" />
|
|
||||||
<textBlock
|
|
||||||
:customText="subHeaderBody"
|
|
||||||
typeStyle="body"
|
|
||||||
justifyText="left"
|
|
||||||
margin="mt-0 mb-2" />
|
|
||||||
|
|
||||||
<buttonMain
|
|
||||||
ref="buttonMain"
|
|
||||||
isPrimary
|
|
||||||
:buttonText="forwardButtonText"
|
|
||||||
loaderColor="white"
|
|
||||||
class="mb-2"
|
|
||||||
@click-event="forwardButtonAction" />
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<hr />
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row justify-content-md-center">
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
|
<vehicleBanner
|
||||||
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
|
:displayGenericVehicleImage="false" />
|
||||||
|
|
||||||
<textBlock
|
<textBlock
|
||||||
customText="Appointment Details"
|
:customText="subHeaderTitle"
|
||||||
typeStyle="label bold"
|
typeStyle="h5"
|
||||||
justifyText="justify-text-left"
|
justifyText="center"
|
||||||
margin="mt-0"
|
margin="mt-1"
|
||||||
class="dark-header" />
|
class="dark-header" />
|
||||||
|
<textBlock
|
||||||
|
:customText="subHeaderBody"
|
||||||
|
typeStyle="body"
|
||||||
|
justifyText="left"
|
||||||
|
margin="mt-0 mb-2" />
|
||||||
|
|
||||||
<div class="px-4">
|
<buttonMain
|
||||||
<vehicleReview
|
ref="buttonMain"
|
||||||
cmsWidgetName="VehicleReviewWidget"
|
isPrimary
|
||||||
:vehicle="vehicleInfo"
|
:buttonText="forwardButtonText"
|
||||||
@edit-clicked="editVehicle" />
|
loaderColor="white"
|
||||||
|
class="mb-2"
|
||||||
|
@click-event="forwardButtonAction" />
|
||||||
|
|
||||||
<hr class="my-0" />
|
<div>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
|
||||||
<damageReview
|
<textBlock
|
||||||
cmsWidgetName="DamageReviewWidget"
|
customText="Appointment Details"
|
||||||
damageLocationsWidgetName="DamageLocationsWidget"
|
typeStyle="label bold"
|
||||||
:damage="damageInfo"
|
justifyText="justify-text-left"
|
||||||
@edit-clicked="editDamage" />
|
margin="mt-0"
|
||||||
|
class="dark-header" />
|
||||||
|
|
||||||
<hr class="my-0" />
|
<div class="px-4">
|
||||||
|
<vehicleReview
|
||||||
|
cmsWidgetName="VehicleReviewWidget"
|
||||||
|
:vehicle="vehicleInfo"
|
||||||
|
@edit-clicked="editVehicle" />
|
||||||
|
|
||||||
<servicePackageReview
|
<hr class="my-0" />
|
||||||
ref="servicePackageReview"
|
|
||||||
servicePackageOptionsCmsName="ServicePackageTitle"
|
|
||||||
defaultPackageItemsCmsName="DefaultPackageItemDescriptions"
|
|
||||||
vapsItemsCmsName="VapsItemDescriptions"
|
|
||||||
:damage="damageInfo"
|
|
||||||
:lineItems="lineItems"
|
|
||||||
@edit-clicked="editServicePackage" />
|
|
||||||
|
|
||||||
<hr class="my-0" />
|
<damageReview
|
||||||
|
cmsWidgetName="DamageReviewWidget"
|
||||||
|
damageLocationsWidgetName="DamageLocationsWidget"
|
||||||
|
:damage="damageInfo"
|
||||||
|
@edit-clicked="editDamage" />
|
||||||
|
|
||||||
<serviceLocationReview
|
<hr class="my-0" />
|
||||||
cmsWidgetName="ServiceLocationTitleWidget"
|
|
||||||
:serviceLocation="serviceLocationInfo"
|
|
||||||
@edit-clicked="editServiceLocation" />
|
|
||||||
|
|
||||||
<hr class="my-0" />
|
<servicePackageReview
|
||||||
|
ref="servicePackageReview"
|
||||||
|
servicePackageOptionsCmsName="ServicePackageTitle"
|
||||||
|
defaultPackageItemsCmsName="DefaultPackageItemDescriptions"
|
||||||
|
vapsItemsCmsName="VapsItemDescriptions"
|
||||||
|
:damage="damageInfo"
|
||||||
|
:lineItems="lineItems"
|
||||||
|
@edit-clicked="editServicePackage" />
|
||||||
|
|
||||||
<scheduleReview
|
<hr class="my-0" />
|
||||||
cmsWidgetName="ScheduleWidget"
|
|
||||||
:appointmentType="appointmentType"
|
|
||||||
@edit-clicked="editSchedule" />
|
|
||||||
|
|
||||||
<hr class="my-0" />
|
<serviceLocationReview
|
||||||
|
cmsWidgetName="ServiceLocationTitleWidget"
|
||||||
|
:serviceLocation="serviceLocationInfo"
|
||||||
|
@edit-clicked="editServiceLocation" />
|
||||||
|
|
||||||
<customerReview
|
<hr class="my-0" />
|
||||||
cmsWidgetName="CustomerReviewWidget"
|
|
||||||
:customer="customerInfo"
|
<scheduleReview
|
||||||
@edit-clicked="editCustomerDetails" />
|
cmsWidgetName="ScheduleWidget"
|
||||||
|
:appointmentType="appointmentType"
|
||||||
|
@edit-clicked="editSchedule" />
|
||||||
|
|
||||||
|
<hr class="my-0" />
|
||||||
|
|
||||||
|
<customerReview
|
||||||
|
cmsWidgetName="CustomerReviewWidget"
|
||||||
|
:customer="customerInfo"
|
||||||
|
@edit-clicked="editCustomerDetails" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<hr class="my-0" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
<hr class="my-0" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<funnelFooter
|
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
|
||||||
@back-clicked="backButtonAction"
|
|
||||||
@ForwardClicked="forwardButtonAction" />
|
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
import buttonMain from "@/ux-components/button-main/button-main";
|
import buttonMain from "@/ux-components/button-main/button-main";
|
||||||
import textBlock from "@/digital-components/text-block/text-block";
|
import textBlock from "@/digital-components/text-block/text-block";
|
||||||
|
|
@ -292,7 +300,7 @@ export default {
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
buttonMain,
|
buttonMain,
|
||||||
textBlock,
|
textBlock,
|
||||||
|
|
|
||||||
|
|
@ -623,7 +623,7 @@ function setupMocks({ customMountOptions }) {
|
||||||
wrapper.vm.setCmsContent = jest.fn();
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
wrapper.vm.$refs.datePicker.initializeComponent = jest.fn();
|
wrapper.vm.$refs.datePicker.initializeComponent = jest.fn();
|
||||||
wrapper.vm.$refs.locationAlerts.initializeComponent = jest.fn();
|
wrapper.vm.$refs.locationAlerts.initializeComponent = jest.fn();
|
||||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
||||||
wrapper.vm.$refs.timeSlotModalQuestion.openModal = jest.fn();
|
wrapper.vm.$refs.timeSlotModalQuestion.openModal = jest.fn();
|
||||||
|
|
||||||
return { wrapper };
|
return { wrapper };
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,62 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<div class="page-container-grouped-styles">
|
<loadingModal ref="loadingModal" />
|
||||||
<loadingModal ref="loadingModal" />
|
<div class="container-fluid">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<div class="row">
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-5" />
|
<div class="col">
|
||||||
<template v-if="ChangeShopLink.length">
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<textBlock
|
</div>
|
||||||
cmsWidgetName="ChangeShopLink"
|
</div>
|
||||||
justifyText="center"
|
<div class="row justify-content-md-center">
|
||||||
class="mb-3 text-link-small"
|
<div class="col-md-6 col-xl-4">
|
||||||
marginTopSizeOverride="1" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-5" />
|
||||||
</template>
|
<template v-if="ChangeShopLink.length">
|
||||||
<locationAlerts cmsWidgetPrefix="LocationAlert-" ref="locationAlerts" />
|
<textBlock
|
||||||
<datePicker
|
cmsWidgetName="ChangeShopLink"
|
||||||
customComponentId="dateQuestion"
|
justifyText="center"
|
||||||
selectableDatesSetting="custom"
|
class="mb-3 text-link-small"
|
||||||
ref="datePicker"
|
marginTopSizeOverride="1" />
|
||||||
v-model="selectedDate"
|
</template>
|
||||||
class="text-link-small"
|
<locationAlerts cmsWidgetPrefix="LocationAlert-" ref="locationAlerts" />
|
||||||
:customSelectableDatesCallback="getAvailableDatesMethod"
|
<datePicker
|
||||||
validationRules="date-required"
|
customComponentId="dateQuestion"
|
||||||
@date-clicked="openInshopTimeSlotsModal" />
|
selectableDatesSetting="custom"
|
||||||
<timeSlotModalQuestion
|
ref="datePicker"
|
||||||
ref="timeSlotModalQuestion"
|
v-model="selectedDate"
|
||||||
customComponentId="timeSlotModalQuestion"
|
class="text-link-small"
|
||||||
v-model="selectedTimeSlotInfo"
|
:customSelectableDatesCallback="getAvailableDatesMethod"
|
||||||
cmsWidgetName="TimeSlotModalQuestion"
|
validationRules="date-required"
|
||||||
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
@date-clicked="openInshopTimeSlotsModal" />
|
||||||
mobileCmsWidgetName="MobileTimeSlotModal"
|
<timeSlotModalQuestion
|
||||||
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
ref="timeSlotModalQuestion"
|
||||||
sameDayDropOffCmsWidgetName="SameDayDropOffTimeSlotModal"
|
customComponentId="timeSlotModalQuestion"
|
||||||
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
v-model="selectedTimeSlotInfo"
|
||||||
:selectedDate="selectedDate"
|
cmsWidgetName="TimeSlotModalQuestion"
|
||||||
:appointmentType="appointmentType"
|
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
||||||
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
mobileCmsWidgetName="MobileTimeSlotModal"
|
||||||
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
||||||
:estimatedServiceMinutesMinimum="selectableDatesData.estimatedServiceMinutesMinimum"
|
sameDayDropOffCmsWidgetName="SameDayDropOffTimeSlotModal"
|
||||||
:estimatedServiceMinutesMaximum="selectableDatesData.estimatedServiceMinutesMaximum"
|
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
||||||
@time-slot-modal-closed="timeSlotModalClosed"
|
:selectedDate="selectedDate"
|
||||||
validationRules="time-slot-selection-required" />
|
:appointmentType="appointmentType"
|
||||||
<funnel-footer
|
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
||||||
ref="funnelFooter"
|
:estimatedServiceMinutesMinimum="
|
||||||
:isForwardActionDisabled="!meta.valid"
|
selectableDatesData.estimatedServiceMinutesMinimum
|
||||||
@back-clicked="backButtonAction"
|
"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
:estimatedServiceMinutesMaximum="
|
||||||
|
selectableDatesData.estimatedServiceMinutesMaximum
|
||||||
|
"
|
||||||
|
@time-slot-modal-closed="timeSlotModalClosed"
|
||||||
|
validationRules="time-slot-selection-required" />
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -52,7 +64,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form, defineRule } from "vee-validate";
|
||||||
|
|
@ -352,23 +364,23 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateFooterButtonText(timeSlotInfo) {
|
updateFooterButtonText(timeSlotInfo) {
|
||||||
let funnelFooterButtonText;
|
let navbarButtonText;
|
||||||
if (!timeSlotInfo || !timeSlotInfo.timeSlot.date) {
|
if (!timeSlotInfo || !timeSlotInfo.timeSlot.date) {
|
||||||
funnelFooterButtonText = "Continue";
|
navbarButtonText = "Continue";
|
||||||
} else {
|
} else {
|
||||||
funnelFooterButtonText = `Select ${this.convertSelectedDateToShortMonthAndDay(
|
navbarButtonText = `Select ${this.convertSelectedDateToShortMonthAndDay(
|
||||||
timeSlotInfo.timeSlot.date
|
timeSlotInfo.timeSlot.date
|
||||||
)}`;
|
)}`;
|
||||||
|
|
||||||
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||||
funnelFooterButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||||
timeSlotInfo.timeSlot.startTime
|
timeSlotInfo.timeSlot.startTime
|
||||||
)}`;
|
)}`;
|
||||||
} else if (
|
} else if (
|
||||||
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
||||||
!timeSlotInfo.isPremiumAppointment
|
!timeSlotInfo.isPremiumAppointment
|
||||||
) {
|
) {
|
||||||
funnelFooterButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||||
timeSlotInfo.timeSlot.startTime,
|
timeSlotInfo.timeSlot.startTime,
|
||||||
true
|
true
|
||||||
)} - ${this.getDisplayTextForMilitaryTime(
|
)} - ${this.getDisplayTextForMilitaryTime(
|
||||||
|
|
@ -377,7 +389,7 @@ export default {
|
||||||
)}`;
|
)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.$refs.funnelFooter.updateButtonText(funnelFooterButtonText);
|
this.$refs.navbar.updateButtonText(navbarButtonText);
|
||||||
},
|
},
|
||||||
convertSelectedDateToShortMonthAndDay(selectedDate) {
|
convertSelectedDateToShortMonthAndDay(selectedDate) {
|
||||||
// This conversion ensures we don't get get GMT induced date changes
|
// This conversion ensures we don't get get GMT induced date changes
|
||||||
|
|
@ -483,7 +495,7 @@ export default {
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
Form,
|
Form,
|
||||||
loadingModal,
|
loadingModal,
|
||||||
|
|
|
||||||
|
|
@ -1,87 +1,106 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<div class="page-container-grouped-styles">
|
<loadingModal ref="loadingModal" />
|
||||||
<loadingModal ref="loadingModal" />
|
<div class="container-fluid">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<div class="row">
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-5" />
|
<div class="col">
|
||||||
<serviceZipModalQuestion
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
v-model="serviceZipCodeQuestion"
|
</div>
|
||||||
ref="serviceZipCodeQuestion"
|
</div>
|
||||||
:mobileFeePart="mobileFeePart"
|
<div class="row justify-content-md-center">
|
||||||
@updated-mobile-fee-part="setMobileFeePart"
|
<div class="col-md-6 col-xl-4">
|
||||||
@updated-serviceability="setServiceabilityDetails"
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-5" />
|
||||||
@updated-contains-military-base="setContainsMilitaryBase"
|
|
||||||
linkWidgetName="ServiceZipLinkWidget"
|
<serviceZipModalQuestion
|
||||||
modalWidgetName="ServiceZipModalWidget"
|
v-model="serviceZipCodeQuestion"
|
||||||
:onZipUpdateCallback="reloadShopData" />
|
ref="serviceZipCodeQuestion"
|
||||||
<alert
|
:mobileFeePart="mobileFeePart"
|
||||||
ref="alertMilitaryBaseZip"
|
@updated-mobile-fee-part="setMobileFeePart"
|
||||||
class="my-5"
|
@updated-serviceability="setServiceabilityDetails"
|
||||||
cmsWidgetName="AlertMilitaryBaseZipWidget"
|
@updated-contains-military-base="setContainsMilitaryBase"
|
||||||
v-if="displayMilitaryZipAlert"
|
linkWidgetName="ServiceZipLinkWidget"
|
||||||
alertClass="alert-warning" />
|
modalWidgetName="ServiceZipModalWidget"
|
||||||
<alert
|
:onZipUpdateCallback="reloadShopData" />
|
||||||
ref="alertMobileOnly"
|
|
||||||
class="my-5"
|
<alert
|
||||||
cmsWidgetName="AlertMobileOnlyWidget"
|
ref="alertMilitaryBaseZip"
|
||||||
v-if="displayServiceableMobileOnly"
|
class="my-5"
|
||||||
alertClass="alert-warning" />
|
cmsWidgetName="AlertMilitaryBaseZipWidget"
|
||||||
<alert
|
v-if="displayMilitaryZipAlert"
|
||||||
ref="alertRecalNoMobile"
|
alertClass="alert-warning" />
|
||||||
class="my-5"
|
|
||||||
cmsWidgetName="AlertRecalNoMobileWidget"
|
<alert
|
||||||
v-if="displayRecalibrationWarning"
|
ref="alertMobileOnly"
|
||||||
@text-link-clicked="openModalAction"
|
class="my-5"
|
||||||
alertClass="alert-warning" />
|
cmsWidgetName="AlertMobileOnlyWidget"
|
||||||
<alert
|
v-if="displayServiceableMobileOnly"
|
||||||
ref="alertInshopOnly"
|
alertClass="alert-warning" />
|
||||||
class="my-5"
|
|
||||||
cmsWidgetName="AlertInshopOnlyWidget"
|
<alert
|
||||||
v-if="displayServiceableInshopOnly"
|
ref="alertRecalNoMobile"
|
||||||
alertClass="alert-warning" />
|
class="my-5"
|
||||||
<alert
|
cmsWidgetName="AlertRecalNoMobileWidget"
|
||||||
ref="alertNoShops"
|
v-if="displayRecalibrationWarning"
|
||||||
class="my-5"
|
@text-link-clicked="openModalAction"
|
||||||
cmsWidgetName="AlertNoShopsWidget"
|
alertClass="alert-warning" />
|
||||||
v-if="displayNoShopsAlert"
|
|
||||||
alertClass="alert-warning" />
|
<alert
|
||||||
<appointmentTypeQuestion
|
ref="alertInshopOnly"
|
||||||
v-model="selectedAppointmentType"
|
class="my-5"
|
||||||
v-show="isAppointmentTypeDisplayed"
|
cmsWidgetName="AlertInshopOnlyWidget"
|
||||||
:isServiceableMobile="isServiceableMobile"
|
v-if="displayServiceableInshopOnly"
|
||||||
:isServiceableInshop="isServiceableInshop"
|
alertClass="alert-warning" />
|
||||||
:isDisplayed="isAppointmentTypeDisplayed"
|
|
||||||
ref="appointmentTypeQuestion"
|
<alert
|
||||||
groupName="appointmentTypeQuestion"
|
ref="alertNoShops"
|
||||||
cmsWidgetName="AppointmentTypeQuestionWidget"
|
class="my-5"
|
||||||
validationRules="option-required" />
|
cmsWidgetName="AlertNoShopsWidget"
|
||||||
<mobileLocationModalQuestions
|
v-if="displayNoShopsAlert"
|
||||||
customComponentId="mobileLocationQuestions"
|
alertClass="alert-warning" />
|
||||||
v-if="selectedAppointmentType === 'Mobile'"
|
|
||||||
v-model="mobileLocationQuestions"
|
<appointmentTypeQuestion
|
||||||
:mobileFeePart="mobileFeePart"
|
v-model="selectedAppointmentType"
|
||||||
@updated-mobile-fee-part="setMobileFeePart"
|
v-show="isAppointmentTypeDisplayed"
|
||||||
@updated-serviceability="setServiceabilityDetails"
|
:isServiceableMobile="isServiceableMobile"
|
||||||
@updated-contains-military-base="setContainsMilitaryBase"
|
:isServiceableInshop="isServiceableInshop"
|
||||||
validationRules="mobile-location-required"
|
:isDisplayed="isAppointmentTypeDisplayed"
|
||||||
ref="mobileLocationQuestions"
|
ref="appointmentTypeQuestion"
|
||||||
linkWidgetName="MobileLocationLinkWidget"
|
groupName="appointmentTypeQuestion"
|
||||||
modalWidgetName="MobileLocationModalWidget"
|
cmsWidgetName="AppointmentTypeQuestionWidget"
|
||||||
:onZipUpdateCallback="reloadShopData" />
|
validationRules="option-required" />
|
||||||
<shopQuestion
|
|
||||||
ref="shopQuestion"
|
<mobileLocationModalQuestions
|
||||||
v-show="isShopQuestionDisplayed"
|
customComponentId="mobileLocationQuestions"
|
||||||
v-model="selectedProvider"
|
v-if="selectedAppointmentType === 'Mobile'"
|
||||||
:selectedAppointmentType="selectedAppointmentType"
|
v-model="mobileLocationQuestions"
|
||||||
:isDisplayed="isShopQuestionDisplayed"
|
:mobileFeePart="mobileFeePart"
|
||||||
cmsWidgetName="ShopQuestionWidget" />
|
@updated-mobile-fee-part="setMobileFeePart"
|
||||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
@updated-serviceability="setServiceabilityDetails"
|
||||||
<funnel-footer
|
@updated-contains-military-base="setContainsMilitaryBase"
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
validationRules="mobile-location-required"
|
||||||
ref="funnelFooter"
|
ref="mobileLocationQuestions"
|
||||||
:isForwardActionDisabled="!meta.valid || displayNoShopsAlert"
|
linkWidgetName="MobileLocationLinkWidget"
|
||||||
@back-clicked="backButtonAction"
|
modalWidgetName="MobileLocationModalWidget"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
:onZipUpdateCallback="reloadShopData" />
|
||||||
|
|
||||||
|
<shopQuestion
|
||||||
|
ref="shopQuestion"
|
||||||
|
v-show="isShopQuestionDisplayed"
|
||||||
|
v-model="selectedProvider"
|
||||||
|
:selectedAppointmentType="selectedAppointmentType"
|
||||||
|
:isDisplayed="isShopQuestionDisplayed"
|
||||||
|
cmsWidgetName="ShopQuestionWidget" />
|
||||||
|
|
||||||
|
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||||
|
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
|
:isForwardActionDisabled="!meta.valid || displayNoShopsAlert"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -95,7 +114,7 @@ import appointmentTypeQuestion from "@/layouts/service-location/appointment-type
|
||||||
import shopQuestion from "@/layouts/service-location/shop-question/shop-question";
|
import shopQuestion from "@/layouts/service-location/shop-question/shop-question";
|
||||||
|
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||||
import { Form } from "vee-validate";
|
import { Form } from "vee-validate";
|
||||||
|
|
@ -116,6 +135,8 @@ import store from "@/store";
|
||||||
import { defineRule } from "vee-validate";
|
import { defineRule } from "vee-validate";
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
import { errorMessages } from "@/constants/error-messages";
|
||||||
|
|
||||||
|
const MOBILE_FEE_PART_TYPE = "MOBILE FEE";
|
||||||
|
|
||||||
// DEFINE VALIDATION RULES
|
// DEFINE VALIDATION RULES
|
||||||
defineRule("mobile-location-required", (value) => {
|
defineRule("mobile-location-required", (value) => {
|
||||||
if (
|
if (
|
||||||
|
|
@ -375,6 +396,43 @@ export default {
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
},
|
},
|
||||||
|
updateAndSaveSupportingItems() {
|
||||||
|
const supportingItems = store.getters.lineItems.supportingItems;
|
||||||
|
// if we have a mobile fee, then save/update supporting items
|
||||||
|
if (this.selectedAppointmentType == "Mobile") {
|
||||||
|
const mobileFeeIndex = supportingItems.findIndex(
|
||||||
|
(item) => item.partType == MOBILE_FEE_PART_TYPE
|
||||||
|
);
|
||||||
|
// If it already exists, update the price with latest data
|
||||||
|
if (mobileFeeIndex >= 0) {
|
||||||
|
supportingItems[mobileFeeIndex].laborAmount = this.mobileFeePart.laborAmount;
|
||||||
|
supportingItems[mobileFeeIndex].selingPrice = this.mobileFeePart.selingPrice;
|
||||||
|
supportingItems[mobileFeeIndex].kitPrice = this.mobileFeePart.kitPrice;
|
||||||
|
} else {
|
||||||
|
supportingItems.push(this.mobileFeePart);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dispatchStoreAction(
|
||||||
|
this.storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
|
||||||
|
supportingItems,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// if it's not a mobile, then make sure we remove any that may have been added
|
||||||
|
const removeMobileFeeIndex = supportingItems.findIndex(
|
||||||
|
(item) => item.partType == MOBILE_FEE_PART_TYPE
|
||||||
|
);
|
||||||
|
|
||||||
|
if (removeMobileFeeIndex >= 0) {
|
||||||
|
supportingItems.splice(removeMobileFeeIndex, 1);
|
||||||
|
this.dispatchStoreAction(
|
||||||
|
this.storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
|
||||||
|
supportingItems,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
async forwardButtonAction() {
|
async forwardButtonAction() {
|
||||||
await this.dispatchStoreAction(
|
await this.dispatchStoreAction(
|
||||||
this.storeActions.SAVE_SERVICE_LOCATION,
|
this.storeActions.SAVE_SERVICE_LOCATION,
|
||||||
|
|
@ -401,6 +459,7 @@ export default {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.updateAndSaveSupportingItems();
|
||||||
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
||||||
},
|
},
|
||||||
openModalAction(modalName) {
|
openModalAction(modalName) {
|
||||||
|
|
@ -416,7 +475,7 @@ export default {
|
||||||
appointmentTypeQuestion,
|
appointmentTypeQuestion,
|
||||||
mobileLocationModalQuestions,
|
mobileLocationModalQuestions,
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
Form,
|
Form,
|
||||||
loadingModal,
|
loadingModal,
|
||||||
|
|
|
||||||
|
|
@ -1,56 +1,76 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<div class="page-container-grouped-styles">
|
<div class="container-fluid">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<div class="row">
|
||||||
<vehicleBanner
|
<div class="col">
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
:displayGenericVehicleImage="false" />
|
</div>
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
</div>
|
||||||
<div class="fade-on-route-transition sub-container make-tall">
|
<div class="row justify-content-md-center">
|
||||||
<alert
|
<div class="col-md-6 col-xl-4">
|
||||||
ref="vehicleChangeAlert"
|
<vehicleBanner
|
||||||
v-if="shouldDisplayVehicleChangeAlert"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
class="mt-5 mb-0"
|
:displayGenericVehicleImage="false" />
|
||||||
cmsWidgetName="VehicleChangeAlert"
|
|
||||||
alertClass="alert-warning"
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
:isDismissible="false" />
|
|
||||||
<damageLocationQuestion
|
<alert
|
||||||
ref="damageLocation"
|
ref="vehicleChangeAlert"
|
||||||
cmsWidgetName="DamageLocationQuestion"
|
v-if="shouldDisplayVehicleChangeAlert"
|
||||||
v-model="selectedDamageLocations"
|
class="mt-5 mb-0"
|
||||||
groupName="DamageLocationQuestion" />
|
cmsWidgetName="VehicleChangeAlert"
|
||||||
<windshieldOptions
|
alertClass="alert-warning"
|
||||||
ref="windshieldOptions"
|
:isDismissible="false" />
|
||||||
v-model="selectedWindshieldOptions"
|
</div>
|
||||||
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
</div>
|
||||||
:hasSplitSingleConflict="hasSplitSingleConflict"
|
<div class="row justify-content-md-center">
|
||||||
:selectedDamageLocations="selectedDamageLocations" />
|
<div class="col-md-8 col-xl-6">
|
||||||
<alert
|
<damageLocationQuestion
|
||||||
v-if="hasRepairReplaceConflict"
|
ref="damageLocation"
|
||||||
class="my-5"
|
cmsWidgetName="DamageLocationQuestion"
|
||||||
cmsWidgetName="HasReplacementConflict"
|
v-model="selectedDamageLocations"
|
||||||
alertClass="alert-danger"
|
groupName="DamageLocationQuestion" />
|
||||||
:isDismissible="false" />
|
|
||||||
<sideDoorOptions
|
<windshieldOptions
|
||||||
ref="sideDoorOptions"
|
ref="windshieldOptions"
|
||||||
cmsWidgetName="SideDoorSideQuestion"
|
v-model="selectedWindshieldOptions"
|
||||||
groupName="SideDoorSideQuestion"
|
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
||||||
v-model="sideDoorOptionsData"
|
:hasSplitSingleConflict="hasSplitSingleConflict"
|
||||||
v-show="!hasRepairReplaceConflict"
|
:selectedDamageLocations="selectedDamageLocations" />
|
||||||
:selectedDamageLocations="selectedDamageLocations" />
|
|
||||||
<replaceOptionsQuestion
|
<alert
|
||||||
ref="backGlassOptions"
|
v-if="hasRepairReplaceConflict"
|
||||||
cmsWidgetName="RearReplaceOptionsQuestion"
|
class="my-5"
|
||||||
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
|
cmsWidgetName="HasReplacementConflict"
|
||||||
v-model="selectedRearReplaceOptions"
|
alertClass="alert-danger"
|
||||||
groupName="BackGlassReplaceOptionsQuestion"
|
:isDismissible="false" />
|
||||||
validationRules="replace-options-required" />
|
|
||||||
<funnel-footer
|
<sideDoorOptions
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
ref="sideDoorOptions"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
cmsWidgetName="SideDoorSideQuestion"
|
||||||
:isBackButtonHidden="shouldHideBackButton"
|
groupName="SideDoorSideQuestion"
|
||||||
@back-clicked="backButtonAction"
|
v-model="sideDoorOptionsData"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
v-show="!hasRepairReplaceConflict"
|
||||||
|
:selectedDamageLocations="selectedDamageLocations" />
|
||||||
|
|
||||||
|
<replaceOptionsQuestion
|
||||||
|
ref="backGlassOptions"
|
||||||
|
cmsWidgetName="RearReplaceOptionsQuestion"
|
||||||
|
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
|
||||||
|
v-model="selectedRearReplaceOptions"
|
||||||
|
groupName="BackGlassReplaceOptionsQuestion"
|
||||||
|
validationRules="replace-options-required" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-md-center">
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
:isBackButtonHidden="shouldHideBackButton"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -59,7 +79,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import sideDoorOptions from "@/layouts/vehicle-damage/side-door-options/side-door-options";
|
import sideDoorOptions from "@/layouts/vehicle-damage/side-door-options/side-door-options";
|
||||||
|
|
@ -512,7 +532,7 @@ export default {
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
sideDoorOptions,
|
sideDoorOptions,
|
||||||
|
|
|
||||||
|
|
@ -542,7 +542,7 @@ function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {}
|
||||||
partQuestionRearWrapper.vm.initializeComponent = glassPartQuestion.methods.initializeComponent;
|
partQuestionRearWrapper.vm.initializeComponent = glassPartQuestion.methods.initializeComponent;
|
||||||
|
|
||||||
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
|
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
|
||||||
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
|
||||||
wrapper.vm.$refs.loadingModal.showModal = jest.fn();
|
wrapper.vm.$refs.loadingModal.showModal = jest.fn();
|
||||||
// wrapper.vm.$refs.onSubmit = jest.fn();
|
// wrapper.vm.$refs.onSubmit = jest.fn();
|
||||||
// wrapper.vm.$refs.onInvalidSubmit = jest.fn();
|
// wrapper.vm.$refs.onInvalidSubmit = jest.fn();
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,54 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
|
||||||
<div class="page-container-grouped-styles vehicle-parts small-question-text">
|
<div class="vehicle-parts small-question-text">
|
||||||
<loadingModal ref="loadingModal" />
|
<loadingModal ref="loadingModal" />
|
||||||
<funnelHeader ref="funnelHeader" cmsWidgetName="FunnelHeaderWidget" />
|
<div class="container-fluid">
|
||||||
<vehicleBanner
|
<div class="row">
|
||||||
ref="vehicleBanner"
|
<div class="col">
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
:displayGenericVehicleImage="false" />
|
|
||||||
<funnelSubHeader ref="funnelSubHeader" cmsWidgetName="FunnelSubHeaderWidget" />
|
|
||||||
<div class="fade-on-route-transition sub-container make-tall">
|
|
||||||
<div class="prevent-squish my-5">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col pb-0">
|
|
||||||
<alert
|
|
||||||
class="rounded border-0 shadow-sm"
|
|
||||||
alertClass="alert-warning"
|
|
||||||
cmsWidgetName="AlertWidget"
|
|
||||||
:isDismissible="false" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="(item, i) in PartsOrQuestions" :key="i">
|
<div class="row justify-content-md-center">
|
||||||
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
<div class="col-md-6 col-lg-4">
|
||||||
<hr v-if="i > 0" />
|
<vehicleBanner
|
||||||
<glassPartQuestion
|
ref="vehicleBanner"
|
||||||
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
v-model="selectedGlassParts[item.glassLocation + '-' + item.glassName]"
|
:displayGenericVehicleImage="false" />
|
||||||
:glassLocation="item.glassLocation"
|
<funnelSubHeader
|
||||||
:glassName="item.glassName"
|
ref="funnelSubHeader"
|
||||||
:colorAnswers="item.colorAnswers"
|
cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
|
<div class="prevent-squish my-5">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col pb-0">
|
||||||
|
<alert
|
||||||
|
class="rounded border-0 shadow-sm"
|
||||||
|
alertClass="alert-warning"
|
||||||
|
cmsWidgetName="AlertWidget"
|
||||||
|
:isDismissible="false" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-for="(item, i) in PartsOrQuestions" :key="i">
|
||||||
|
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
||||||
|
<hr v-if="i > 0" />
|
||||||
|
<glassPartQuestion
|
||||||
|
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
||||||
|
v-model="
|
||||||
|
selectedGlassParts[item.glassLocation + '-' + item.glassName]
|
||||||
|
"
|
||||||
|
:glassLocation="item.glassLocation"
|
||||||
|
:glassName="item.glassName"
|
||||||
|
:colorAnswers="item.colorAnswers"
|
||||||
|
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
|
||||||
|
</div>
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
|
:isForwardActionDisabled="isForwardActionDisabled"
|
||||||
|
@back-clicked="navigateBack"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<funnelFooter
|
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
|
||||||
ref="funnelFooter"
|
|
||||||
:isForwardActionDisabled="isForwardActionDisabled"
|
|
||||||
@back-clicked="navigateBack"
|
|
||||||
@ForwardClicked="forwardButtonAction" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -48,7 +60,7 @@ import glassPartQuestion from "@/layouts/vehicle-parts/glass-part-question/glass
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||||
// Supporting Files
|
// Supporting Files
|
||||||
|
|
@ -178,7 +190,7 @@ export default {
|
||||||
}
|
}
|
||||||
// If no parts could be matched, throw an error (isForwardActionDisabled is based off of matchedParts)
|
// If no parts could be matched, throw an error (isForwardActionDisabled is based off of matchedParts)
|
||||||
if (this.isForwardActionDisabled) {
|
if (this.isForwardActionDisabled) {
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.navbar.removeLoader();
|
||||||
throw new Error("Could not match any parts to the selected parts");
|
throw new Error("Could not match any parts to the selected parts");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,9 +233,19 @@ export default {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
alert,
|
alert,
|
||||||
loadingModal,
|
loadingModal,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.vehicle-parts {
|
||||||
|
label {
|
||||||
|
&.list-card {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,73 +1,68 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<div class="page-container-grouped-styles position-relative">
|
<div class="container-fluid">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<div class="row">
|
||||||
<div class="select-car">
|
<div class="col">
|
||||||
<div class="container-fluid pb-2">
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<div class="row">
|
</div>
|
||||||
<div class="col">
|
</div>
|
||||||
<div class="select-car-form rounded">
|
<div class="row justify-content-md-center">
|
||||||
<funnelSubHeader
|
<div class="col-md-6 col-xl-4">
|
||||||
cmsWidgetName="FunnelSubHeaderWidget"
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="siteSubHeader" />
|
||||||
class="siteSubHeader" />
|
<vehicleQuestion
|
||||||
|
ref="vehicleYearQuestion"
|
||||||
|
v-model="selectedYear"
|
||||||
|
:isDisabled="!yearOptions.length"
|
||||||
|
:options="yearOptions"
|
||||||
|
cmsWidgetName="VehicleYearQuestion"
|
||||||
|
validationRules="year-required"
|
||||||
|
placeHolderText="Select year"
|
||||||
|
inputId="yearQuestionField" />
|
||||||
|
|
||||||
<vehicleQuestion
|
<vehicleQuestion
|
||||||
ref="vehicleYearQuestion"
|
ref="vehicleMakeQuestion"
|
||||||
v-model="selectedYear"
|
v-model="selectedMake"
|
||||||
:isDisabled="!yearOptions.length"
|
:isDisabled="!makeOptions.length"
|
||||||
:options="yearOptions"
|
:options="makeOptions"
|
||||||
cmsWidgetName="VehicleYearQuestion"
|
cmsWidgetName="VehicleMakeQuestion"
|
||||||
validationRules="year-required"
|
validationRules="make-required"
|
||||||
placeHolderText="Select year"
|
placeHolderText="Select make"
|
||||||
inputId="yearQuestionField" />
|
inputId="makeQuestionField" />
|
||||||
|
|
||||||
<vehicleQuestion
|
<vehicleQuestion
|
||||||
ref="vehicleMakeQuestion"
|
ref="vehicleModelQuestion"
|
||||||
v-model="selectedMake"
|
v-model="selectedModel"
|
||||||
:isDisabled="!makeOptions.length"
|
cmsWidgetName="VehicleModelQuestion"
|
||||||
:options="makeOptions"
|
:isDisabled="!modelOptions.length"
|
||||||
cmsWidgetName="VehicleMakeQuestion"
|
:options="modelOptions"
|
||||||
validationRules="make-required"
|
validationRules="model-required"
|
||||||
placeHolderText="Select make"
|
placeHolderText="Select model"
|
||||||
inputId="makeQuestionField" />
|
inputId="modelQuestionField" />
|
||||||
|
|
||||||
<vehicleQuestion
|
<vehicleQuestion
|
||||||
ref="vehicleModelQuestion"
|
ref="vehicleStyleQuestion"
|
||||||
v-model="selectedModel"
|
v-model="selectedStyle"
|
||||||
cmsWidgetName="VehicleModelQuestion"
|
cmsWidgetName="VehicleStyleQuestion"
|
||||||
:isDisabled="!modelOptions.length"
|
:isDisabled="!styleOptions.length"
|
||||||
:options="modelOptions"
|
:options="styleOptions"
|
||||||
validationRules="model-required"
|
validationRules="style-required"
|
||||||
placeHolderText="Select model"
|
placeHolderText="Select style"
|
||||||
inputId="modelQuestionField" />
|
inputId="styleQuestionField" />
|
||||||
|
<div class="col-md-3"> </div>
|
||||||
|
<vehicleBanner
|
||||||
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
|
:displayGenericVehicleImage="displayGeneric"
|
||||||
|
:displayVehicleImage="imageUrl"
|
||||||
|
:vehicleCategory="category"
|
||||||
|
:displayUnmatchedVehicleIcon="unmatchedVehicleIcon"
|
||||||
|
class="mt-5 vehicle-footer"
|
||||||
|
ref="banner" />
|
||||||
|
|
||||||
<vehicleQuestion
|
<navbar
|
||||||
ref="vehicleStyleQuestion"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
v-model="selectedStyle"
|
@ForwardClicked="forwardButtonAction"
|
||||||
cmsWidgetName="VehicleStyleQuestion"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
:isDisabled="!styleOptions.length"
|
ref="navbar" />
|
||||||
:options="styleOptions"
|
|
||||||
validationRules="style-required"
|
|
||||||
placeHolderText="Select style"
|
|
||||||
inputId="styleQuestionField" />
|
|
||||||
|
|
||||||
<vehicleBanner
|
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
|
||||||
:displayGenericVehicleImage="displayGeneric"
|
|
||||||
:displayVehicleImage="imageUrl"
|
|
||||||
:vehicleCategory="category"
|
|
||||||
:displayUnmatchedVehicleIcon="unmatchedVehicleIcon"
|
|
||||||
class="mt-5 vehicle-footer"
|
|
||||||
ref="banner" />
|
|
||||||
|
|
||||||
<funnelFooter
|
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
|
||||||
@ForwardClicked="forwardButtonAction"
|
|
||||||
:isForwardActionDisabled="!meta.valid"
|
|
||||||
ref="funnelFooter" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -77,7 +72,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
import vehicleQuestion from "@/layouts/vehicle/vehicle-question/vehicle-question";
|
import vehicleQuestion from "@/layouts/vehicle/vehicle-question/vehicle-question";
|
||||||
|
|
@ -413,7 +408,7 @@ export default {
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
Form,
|
Form,
|
||||||
|
|
@ -423,10 +418,6 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.select-car-form {
|
|
||||||
margin-left: 0.75rem;
|
|
||||||
margin-right: 0.75rem;
|
|
||||||
}
|
|
||||||
.vehicle-footer {
|
.vehicle-footer {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,14 +47,14 @@ jest.mock("@/helpers/damage-helper", () => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe("vin-lookup.vue", () => {
|
describe("vin-lookup.vue", () => {
|
||||||
it("Should update the funnel-footer forward button when VIN is changed", (done) => {
|
it("Should update the nav-bar forward button when VIN is changed", (done) => {
|
||||||
//Arrange
|
//Arrange
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
//Act
|
//Act
|
||||||
wrapper.setData({ vin: "newValue" });
|
wrapper.setData({ vin: "newValue" });
|
||||||
//Assert
|
//Assert
|
||||||
wrapper.vm.$nextTick(() => {
|
wrapper.vm.$nextTick(() => {
|
||||||
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toBeCalled();
|
expect(wrapper.vm.$refs.navbar.updateButtonText).toBeCalled();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -368,8 +368,8 @@ function mockOutPromises({ carId, isZipValid = true, isZipServiceable = true })
|
||||||
}
|
}
|
||||||
|
|
||||||
function mockOutStubFunctions(wrapper) {
|
function mockOutStubFunctions(wrapper) {
|
||||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
wrapper.vm.$refs.navbar.updateButtonText = jest.fn();
|
||||||
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
|
||||||
wrapper.vm.getZipCodeData = jest
|
wrapper.vm.getZipCodeData = jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockReturnValue({ isValid: true, isServiceable: true, state: "OH" });
|
.mockReturnValue({ isValid: true, isServiceable: true, state: "OH" });
|
||||||
|
|
|
||||||
|
|
@ -1,131 +1,125 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<div class="page-container-grouped-styles">
|
<loadingModal ref="loadingModal" />
|
||||||
<loadingModal ref="loadingModal" />
|
<div class="container-fluid">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<div class="row">
|
||||||
<vehicleBanner
|
<div class="col">
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
:displayGenericVehicleImage="false" />
|
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
|
||||||
<div class="fade-on-route-transition sub-container make-tall">
|
|
||||||
<div class="row mb-2">
|
|
||||||
<div class="col">
|
|
||||||
<textboxQuestion
|
|
||||||
cmsWidgetName="VinNumberQuestionWidget"
|
|
||||||
v-model="vin"
|
|
||||||
customInputId="vin"
|
|
||||||
isRequired
|
|
||||||
:validationRules="
|
|
||||||
!vinPopulatedOnPageLoad ? 'vin-required|vin-format' : ''
|
|
||||||
"
|
|
||||||
:isDisabled="vinPopulatedOnPageLoad"
|
|
||||||
maxLength="17"
|
|
||||||
:mask="vinMask"
|
|
||||||
includeImageQuestion
|
|
||||||
:imageQuestionSubmitHandler="getVinFromImage"
|
|
||||||
:maxFileSize="imageUploadMaxFileSize"
|
|
||||||
@image-lookup-error="displayVinScanAlert"
|
|
||||||
@image-validity-error="displayVinScanAlert"
|
|
||||||
data-test="vin-lookup-field"
|
|
||||||
ref="vinLookupQuestion" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
</div>
|
||||||
<div class="col">
|
<div class="row justify-content-md-center">
|
||||||
<alert
|
<div class="col-md-6 col-xl-4">
|
||||||
cmsWidgetName="AlertVinScanFailed"
|
<vehicleBanner
|
||||||
v-if="displayVinScanFailedAlert"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
alertClass="alert-danger" />
|
:displayGenericVehicleImage="false" />
|
||||||
</div>
|
|
||||||
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
|
|
||||||
|
<textboxQuestion
|
||||||
|
cmsWidgetName="VinNumberQuestionWidget"
|
||||||
|
v-model="vin"
|
||||||
|
customInputId="vin"
|
||||||
|
isRequired
|
||||||
|
:validationRules="!vinPopulatedOnPageLoad ? 'vin-required|vin-format' : ''"
|
||||||
|
:isDisabled="vinPopulatedOnPageLoad"
|
||||||
|
maxLength="17"
|
||||||
|
:mask="vinMask"
|
||||||
|
includeImageQuestion
|
||||||
|
:imageQuestionSubmitHandler="getVinFromImage"
|
||||||
|
:maxFileSize="imageUploadMaxFileSize"
|
||||||
|
@image-lookup-error="displayVinScanAlert"
|
||||||
|
@image-validity-error="displayVinScanAlert"
|
||||||
|
data-test="vin-lookup-field"
|
||||||
|
ref="vinLookupQuestion" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
cmsWidgetName="AlertVinScanFailed"
|
||||||
|
v-if="displayVinScanFailedAlert"
|
||||||
|
alertClass="alert-danger" />
|
||||||
|
|
||||||
|
<vinInformation />
|
||||||
|
|
||||||
|
<textboxQuestion
|
||||||
|
cmsWidgetName="ServiceZipQuestionWidget"
|
||||||
|
v-model="serviceZipCode"
|
||||||
|
customInputId="serviceZipCode"
|
||||||
|
mask="#####"
|
||||||
|
isRequired
|
||||||
|
validationRules="zip-required|zip-format" />
|
||||||
|
|
||||||
|
<textboxQuestion
|
||||||
|
cmsWidgetName="EmailAddressQuestionWidget"
|
||||||
|
v-model="emailAddress"
|
||||||
|
customInputId="emailAddress"
|
||||||
|
isRequired
|
||||||
|
validationRules="email-address-required|email-address-format" />
|
||||||
|
|
||||||
|
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
ref="alertInvalidZip"
|
||||||
|
v-if="displayInvalidZipAlert"
|
||||||
|
class="my-4"
|
||||||
|
cmsWidgetName="AlertInvalidZipWidget"
|
||||||
|
alertClass="alert-danger"
|
||||||
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
class="my-4"
|
||||||
|
:manualHeadline="AlertPerfectMatchInsuranceVerifiedHeader"
|
||||||
|
:manualCopy="AlertPerfectMatchInsuranceVerifiedBody"
|
||||||
|
v-model="customAlertData"
|
||||||
|
v-if="
|
||||||
|
vinPopulatedOnPageLoad &&
|
||||||
|
isInsuranceVerified &&
|
||||||
|
!displayInvalidZipAlert &&
|
||||||
|
!displayNonServiceableZipAlert
|
||||||
|
"
|
||||||
|
alertClass="alert-success" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
class="my-4"
|
||||||
|
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||||
|
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||||
|
v-model="customAlertData"
|
||||||
|
v-if="displayMatchedDifferentVehicleAlert"
|
||||||
|
alertClass="alert-warning" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
class="my-4"
|
||||||
|
:manualHeadline="AlertNonServiceableZipHeader"
|
||||||
|
:manualCopy="AlertNonServiceableZipBody"
|
||||||
|
v-model="customAlertData"
|
||||||
|
v-if="displayNonServiceableZipAlert"
|
||||||
|
alertClass="alert-danger" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
class="my-4"
|
||||||
|
v-model="customAlertData"
|
||||||
|
v-if="displayVinNotFoundAlert"
|
||||||
|
alertClass="alert-danger"
|
||||||
|
cmsWidgetName="AlertVinNotFoundWidget" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
class="my-4"
|
||||||
|
:manualHeadline="AlertPerfectMatchInsuranceNotVerifiedHeader"
|
||||||
|
:manualCopy="AlertPerfectMatchInsuranceNotVerifiedBody"
|
||||||
|
v-model="customAlertData"
|
||||||
|
v-if="
|
||||||
|
vinPopulatedOnPageLoad &&
|
||||||
|
!isInsuranceVerified &&
|
||||||
|
!displayInvalidZipAlert &&
|
||||||
|
!displayNonServiceableZipAlert
|
||||||
|
"
|
||||||
|
alertClass="alert-success" />
|
||||||
|
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<vinInformation />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-0 mt-4">
|
|
||||||
<div class="col">
|
|
||||||
<textboxQuestion
|
|
||||||
cmsWidgetName="ServiceZipQuestionWidget"
|
|
||||||
v-model="serviceZipCode"
|
|
||||||
customInputId="serviceZipCode"
|
|
||||||
mask="#####"
|
|
||||||
isRequired
|
|
||||||
validationRules="zip-required|zip-format" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mt-4">
|
|
||||||
<div class="col">
|
|
||||||
<textboxQuestion
|
|
||||||
cmsWidgetName="EmailAddressQuestionWidget"
|
|
||||||
v-model="emailAddress"
|
|
||||||
customInputId="emailAddress"
|
|
||||||
isRequired
|
|
||||||
validationRules="email-address-required|email-address-format" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-0">
|
|
||||||
<div class="col">
|
|
||||||
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<alert
|
|
||||||
ref="alertInvalidZip"
|
|
||||||
v-if="displayInvalidZipAlert"
|
|
||||||
class="my-4"
|
|
||||||
cmsWidgetName="AlertInvalidZipWidget"
|
|
||||||
alertClass="alert-danger"
|
|
||||||
v-bind:isDismissible="false" />
|
|
||||||
<alert
|
|
||||||
class="my-4"
|
|
||||||
:manualHeadline="AlertPerfectMatchInsuranceVerifiedHeader"
|
|
||||||
:manualCopy="AlertPerfectMatchInsuranceVerifiedBody"
|
|
||||||
v-model="customAlertData"
|
|
||||||
v-if="
|
|
||||||
vinPopulatedOnPageLoad &&
|
|
||||||
isInsuranceVerified &&
|
|
||||||
!displayInvalidZipAlert &&
|
|
||||||
!displayNonServiceableZipAlert
|
|
||||||
"
|
|
||||||
alertClass="alert-success" />
|
|
||||||
<alert
|
|
||||||
class="my-4"
|
|
||||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
|
||||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
|
||||||
v-model="customAlertData"
|
|
||||||
v-if="displayMatchedDifferentVehicleAlert"
|
|
||||||
alertClass="alert-warning" />
|
|
||||||
<alert
|
|
||||||
class="my-4"
|
|
||||||
:manualHeadline="AlertNonServiceableZipHeader"
|
|
||||||
:manualCopy="AlertNonServiceableZipBody"
|
|
||||||
v-model="customAlertData"
|
|
||||||
v-if="displayNonServiceableZipAlert"
|
|
||||||
alertClass="alert-danger" />
|
|
||||||
<alert
|
|
||||||
class="my-4"
|
|
||||||
v-model="customAlertData"
|
|
||||||
v-if="displayVinNotFoundAlert"
|
|
||||||
alertClass="alert-danger"
|
|
||||||
cmsWidgetName="AlertVinNotFoundWidget" />
|
|
||||||
<alert
|
|
||||||
class="my-4"
|
|
||||||
:manualHeadline="AlertPerfectMatchInsuranceNotVerifiedHeader"
|
|
||||||
:manualCopy="AlertPerfectMatchInsuranceNotVerifiedBody"
|
|
||||||
v-model="customAlertData"
|
|
||||||
v-if="
|
|
||||||
vinPopulatedOnPageLoad &&
|
|
||||||
!isInsuranceVerified &&
|
|
||||||
!displayInvalidZipAlert &&
|
|
||||||
!displayNonServiceableZipAlert
|
|
||||||
"
|
|
||||||
alertClass="alert-success" />
|
|
||||||
<funnelFooter
|
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
|
||||||
ref="funnelFooter"
|
|
||||||
:isForwardActionDisabled="!meta.valid"
|
|
||||||
@back-clicked="backButtonAction"
|
|
||||||
@ForwardClicked="forwardButtonAction" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
@ -134,7 +128,7 @@
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
|
|
@ -279,7 +273,7 @@ export default {
|
||||||
const isZipValid = resultMap.zipCodeData.isValid;
|
const isZipValid = resultMap.zipCodeData.isValid;
|
||||||
if (this.serviceZipCode && !isZipValid) {
|
if (this.serviceZipCode && !isZipValid) {
|
||||||
this.displayInvalidZipAlert = true;
|
this.displayInvalidZipAlert = true;
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
this.displayInvalidZipAlert = false;
|
this.displayInvalidZipAlert = false;
|
||||||
|
|
||||||
|
|
@ -296,7 +290,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove loader and stop processing the page.
|
// Remove loader and stop processing the page.
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the CarId is different from the lookup vs what is in state currently.
|
// Check if the CarId is different from the lookup vs what is in state currently.
|
||||||
|
|
@ -317,10 +311,10 @@ export default {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update button "Continue with..."
|
// Update button "Continue with..."
|
||||||
this.$refs.funnelFooter.updateButtonText(
|
this.$refs.navbar.updateButtonText(
|
||||||
`Continue with ${resultMap.vehicleLookupResponse.year} ${resultMap.vehicleLookupResponse.make} ${resultMap.vehicleLookupResponse.model}`
|
`Continue with ${resultMap.vehicleLookupResponse.year} ${resultMap.vehicleLookupResponse.make} ${resultMap.vehicleLookupResponse.model}`
|
||||||
);
|
);
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save vin, vehicle, customer and service information
|
// Save vin, vehicle, customer and service information
|
||||||
|
|
@ -382,7 +376,7 @@ export default {
|
||||||
this.displayInvalidZipAlert = true;
|
this.displayInvalidZipAlert = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.$refs.funnelFooter.removeLoader();
|
return this.$refs.navbar.removeLoader();
|
||||||
},
|
},
|
||||||
async navigateForward() {
|
async navigateForward() {
|
||||||
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||||
|
|
@ -494,7 +488,7 @@ export default {
|
||||||
vin() {
|
vin() {
|
||||||
this.displayVinNotFoundAlert = false;
|
this.displayVinNotFoundAlert = false;
|
||||||
this.displayVinScanFailedAlert = false;
|
this.displayVinScanFailedAlert = false;
|
||||||
this.$refs.funnelFooter.updateButtonText(
|
this.$refs.navbar.updateButtonText(
|
||||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -504,7 +498,7 @@ export default {
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
navbar,
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
textboxQuestion,
|
textboxQuestion,
|
||||||
|
|
|
||||||
|
|
@ -116,11 +116,11 @@ export default {
|
||||||
return lineItem.kitPrice + lineItem.laborAmount + lineItem.sellingPrice;
|
return lineItem.kitPrice + lineItem.laborAmount + lineItem.sellingPrice;
|
||||||
},
|
},
|
||||||
scrollToPageTop() {
|
scrollToPageTop() {
|
||||||
const container = document.getElementsByClassName("page-container-grouped-styles")[0];
|
const container = document.getElementsByClassName("container-fluid")[0];
|
||||||
container.scrollTo({ top: 0, left: 0, behavior: "smooth" });
|
container.scrollTo({ top: 0, left: 0, behavior: "smooth" });
|
||||||
},
|
},
|
||||||
scrollToPageBottom() {
|
scrollToPageBottom() {
|
||||||
const container = document.getElementsByClassName("page-container-grouped-styles")[0];
|
const container = document.getElementsByClassName("container-fluid")[0];
|
||||||
container.scrollTo({ top: container.scrollHeight, left: 0, behavior: "smooth" });
|
container.scrollTo({ top: container.scrollHeight, left: 0, behavior: "smooth" });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -447,9 +447,15 @@ export default {
|
||||||
const payment = store.getters.payment;
|
const payment = store.getters.payment;
|
||||||
|
|
||||||
if (store.getters.order.referralNumber?.length === 6) {
|
if (store.getters.order.referralNumber?.length === 6) {
|
||||||
navigateToHeritageFunnel({ loadingModal: self.$refs.loadingModal });
|
navigateToHeritageFunnel({
|
||||||
|
shouldSaveSession: true,
|
||||||
|
loadingModal: self.$refs.loadingModal,
|
||||||
|
});
|
||||||
} else if (payment.isInsurance && payment.insuranceCoverage.isVerified) {
|
} else if (payment.isInsurance && payment.insuranceCoverage.isVerified) {
|
||||||
navigateToHeritageFunnel({ loadingModal: self.$refs.loadingModal });
|
navigateToHeritageFunnel({
|
||||||
|
shouldSaveSession: true,
|
||||||
|
loadingModal: self.$refs.loadingModal,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
self.$router.navigateWithSaving(
|
self.$router.navigateWithSaving(
|
||||||
self.navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
self.navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js"
|
||||||
import { routingTable } from "@/router/router-constants/routing-table.js";
|
import { routingTable } from "@/router/router-constants/routing-table.js";
|
||||||
import { globalEvents, globalEventTypes } from "@/constants/events";
|
import { globalEvents, globalEventTypes } from "@/constants/events";
|
||||||
import { queryStrings } from "@/constants/query-strings";
|
import { queryStrings } from "@/constants/query-strings";
|
||||||
|
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||||
import { getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper";
|
import { getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper";
|
||||||
|
|
||||||
// Heritage integration
|
// Heritage integration
|
||||||
|
|
@ -74,17 +75,7 @@ const routes = [
|
||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
const pageToRedirectTo = await getPageToRouteExistingOrderTo(
|
const pageToRedirectTo = await getPageToRouteExistingOrderTo(to);
|
||||||
to,
|
|
||||||
loadSessionResponse
|
|
||||||
);
|
|
||||||
|
|
||||||
// If getPageToRouteExistingOrderTo determines that the return user needs to
|
|
||||||
// go back to heritage funnel, send them there and stop our current navigation.
|
|
||||||
if (pageToRedirectTo === "heritage") {
|
|
||||||
await navigateToHeritageFunnel();
|
|
||||||
return next(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign our fmgPage so it will load normally like the other pages.
|
// Assign our fmgPage so it will load normally like the other pages.
|
||||||
to.query.fmgPage = pageToRedirectTo;
|
to.query.fmgPage = pageToRedirectTo;
|
||||||
|
|
@ -284,14 +275,9 @@ async function navigate(
|
||||||
fmgPage: destinationFmgPageValue,
|
fmgPage: destinationFmgPageValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
const queryString = window.location.search;
|
const hasZip = getQuerystringParameter(queryStrings.ZIP_CODE);
|
||||||
const urlParams = new URLSearchParams(queryString);
|
const zip = getQuerystringParameter(queryStrings.ZIP_CODE);
|
||||||
const lowerCaseParams = new URLSearchParams();
|
const promo = getQuerystringParameter(queryStrings.PROMO);
|
||||||
for (const [name, value] of urlParams) {
|
|
||||||
lowerCaseParams.append(name.toLowerCase(), value);
|
|
||||||
}
|
|
||||||
const hasZip = lowerCaseParams.has(queryStrings.ZIP_CODE);
|
|
||||||
const zip = lowerCaseParams.get(queryStrings.ZIP_CODE);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hasZip &&
|
hasZip &&
|
||||||
|
|
@ -303,6 +289,10 @@ async function navigate(
|
||||||
queryStringsObject[queryStrings.ZIP_CODE] = zip;
|
queryStringsObject[queryStrings.ZIP_CODE] = zip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (promo) {
|
||||||
|
queryStringsObject[queryStrings.PROMO] = promo;
|
||||||
|
}
|
||||||
|
|
||||||
router.push({
|
router.push({
|
||||||
name: "root",
|
name: "root",
|
||||||
query: Object.assign(optionalQuery, queryStringsObject),
|
query: Object.assign(optionalQuery, queryStringsObject),
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import {
|
||||||
getDisplayTextForDurationLength,
|
getDisplayTextForDurationLength,
|
||||||
} from "@/layouts/schedule/helpers/schedule-helper";
|
} from "@/layouts/schedule/helpers/schedule-helper";
|
||||||
|
|
||||||
|
import { getDateDifferenceInDays } from "@/helpers/date-helper";
|
||||||
// Export State
|
// Export State
|
||||||
const getDefaultState = () => {
|
const getDefaultState = () => {
|
||||||
return {
|
return {
|
||||||
|
|
@ -634,8 +635,24 @@ function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
|
||||||
return (array ?? []).map((x) => x[propertyName]).filter((x) => x);
|
return (array ?? []).map((x) => x[propertyName]).filter((x) => x);
|
||||||
}
|
}
|
||||||
|
|
||||||
function provisionalTriggersToString(provisionalTriggers) {
|
function getTimeSlotsAdditionalEventData(
|
||||||
return "ProvisionalTriggers:" + provisionalTriggers.join(",");
|
provisionalTriggers,
|
||||||
|
zipCode,
|
||||||
|
firstAvailableAppointmentDateString,
|
||||||
|
shopAppointmentType
|
||||||
|
) {
|
||||||
|
var numberOfDays = null;
|
||||||
|
if (firstAvailableAppointmentDateString)
|
||||||
|
numberOfDays = getDateDifferenceInDays(new Date(), firstAvailableAppointmentDateString);
|
||||||
|
|
||||||
|
if (shopAppointmentType)
|
||||||
|
return `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ShopAppointmentType:${shopAppointmentType},ProvisionalTriggers:${provisionalTriggers.join(
|
||||||
|
","
|
||||||
|
)}`;
|
||||||
|
else
|
||||||
|
return `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ProvisionalTriggers:${provisionalTriggers.join(
|
||||||
|
","
|
||||||
|
)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export Actions
|
// Export Actions
|
||||||
|
|
@ -1362,7 +1379,12 @@ export const actions = {
|
||||||
endpoint: endpoints.GetShopTimeSlots.url,
|
endpoint: endpoints.GetShopTimeSlots.url,
|
||||||
payload: payload,
|
payload: payload,
|
||||||
additionalSuccessEventDataHandler: (response) =>
|
additionalSuccessEventDataHandler: (response) =>
|
||||||
provisionalTriggersToString(response.data.provisionalTriggers),
|
getTimeSlotsAdditionalEventData(
|
||||||
|
response.data.provisionalTriggers,
|
||||||
|
order.serviceLocation.zipCode,
|
||||||
|
response.data.days?.[0]?.date,
|
||||||
|
shopAppointmentType
|
||||||
|
),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -1419,7 +1441,11 @@ export const actions = {
|
||||||
endpoint: endpoints.GetMobileTimeSlots.url,
|
endpoint: endpoints.GetMobileTimeSlots.url,
|
||||||
payload: payload,
|
payload: payload,
|
||||||
additionalSuccessEventDataHandler: (response) =>
|
additionalSuccessEventDataHandler: (response) =>
|
||||||
provisionalTriggersToString(response.data.provisionalTriggers),
|
getTimeSlotsAdditionalEventData(
|
||||||
|
response.data.provisionalTriggers,
|
||||||
|
order.serviceLocation.zipCode,
|
||||||
|
response.data.days?.[0]?.date
|
||||||
|
),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,7 @@ body {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
color: #4d5151;
|
color: #4d5151;
|
||||||
.container-fluid {
|
.container-fluid {
|
||||||
max-width: 576px; //Remove once desktop app is complete
|
max-width: 1400px;
|
||||||
&.container-shadow {
|
|
||||||
box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.15); //Use instead of Bootstrap's helper
|
|
||||||
}
|
|
||||||
&.make-tall {
|
|
||||||
height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.prevent-squish {
|
.prevent-squish {
|
||||||
overflow-x: unset;
|
overflow-x: unset;
|
||||||
}
|
}
|
||||||
|
|
@ -44,10 +36,6 @@ body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-container-grouped-styles {
|
|
||||||
@extend .container-fluid, .shadow, .rounded-3, .p-2, .position-relative, .make-tall, .px-5;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Footer modal backdrop adjustments for positioning
|
//Footer modal backdrop adjustments for positioning
|
||||||
.modal-backdrop {
|
.modal-backdrop {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
|
|
|
||||||
|
|
@ -170,15 +170,6 @@ $spacers: (
|
||||||
//Enable negative spacing (does NOT work on padding)
|
//Enable negative spacing (does NOT work on padding)
|
||||||
$enable-negative-margins: true;
|
$enable-negative-margins: true;
|
||||||
|
|
||||||
//Grid breakpoints
|
|
||||||
$grid-breakpoints: (
|
|
||||||
xs: 0,
|
|
||||||
sm: 576px,
|
|
||||||
md: 838px,
|
|
||||||
lg: 1074px,
|
|
||||||
xl: 1416px,
|
|
||||||
);
|
|
||||||
|
|
||||||
//Shadow
|
//Shadow
|
||||||
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15);
|
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15);
|
||||||
$box-shadow-sm: 0 0.125rem 0.25rem rgba($black, 0.075);
|
$box-shadow-sm: 0 0.125rem 0.25rem rgba($black, 0.075);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue